
Pour rappel, Magento s'appuie sur des fichiers XML pour configurer ses modules (entre autre). Le soucis avec l’utilisation qu'en fait Magento, c'est qu'il ne vérifie pas l'intégrité des fichiers XML.
En effet, si vous faite une faute de frappe, qu'une balise est mal fermé ou tout être erreur dans la structure XML de votre fichier de configuration, Magento levera une erreur (ou plutôt un warning) du type :
Notes :
- ce message est loggué dans system.log (si les logs sont activés)
- dans le cas où le DeveloperMode n'est pas activée, l'erreur sera silencieuse
Vous me direz, ça n'est pas bloquant : un coup d'oeil dans le fichier exception.log pour déterminer l'origine du problème et l'affaire est réglée ! Sauf que non, ce type d'erreur n'est pas "protégée" par un try/catch...
De ce fait, mise à part le fait de savoir qu'un fichier XML de configuration est en cause, vous n'êtes pas très avancé.
L'idée, pour se simplifier, est de connaitre le non (où plutôt le chemin) du fichier en cause et la ligne qui pose problème.
Pour cela, je vous propose un overlap de classe Varien en charge des fichiers de configuration XML : Varien_Simplexml_Config. Le code est simple et mériterait d'être retravaillé, mais il fonctionne bien en l'état.
app/code/local/Varien/Simplexml/Config.php :
[...]
/**
* Imports XML file
*
* @param string $filePath
* @return boolean
*/
public function loadFile($filePath)
{
if (!is_readable($filePath)) {
//throw new Exception('Can not read xml file '.$filePath);
return false;
}
$fileData = file_get_contents($filePath);
$fileData = $this->processFileData($fileData);
/**
* Custom code: $filePath added
*/
// original
//return $this->loadString($fileData, $this->_elementClass);
// new
return $this->loadString($fileData, $this->_elementClass, $filePath);
}
/**
* Imports XML string
*
* @param string $string
* @return boolean
*/
public function loadString($string)
{
if (is_string($string)) {
/**
* Custom code: dealing with config file XML errors
*/
libxml_use_internal_errors(true);
$xmlcheck = simplexml_load_string($string);
if (!is_object($xmlcheck)) {
$argslist = func_get_args();
$filePath = $argslist[2];
foreach(libxml_get_errors() as $error) {
$error = array(
'message' => trim($error->message),
'code' => 'Code: ' . $error->code,
'file' => 'File: ' . ($error->file != '' ? $error->file : $filePath),
'line' => 'Line: ' . $error->line,
'column' => 'Column: ' . $error->column,
);
}
libxml_clear_errors();
// log
Mage::log("\n" . implode("\n", $error), Zend_Log::ERR, 'exception_config.log');
// throw in developer mode
if (Mage::getIsDeveloperMode()) {
Mage::printException(new Exception(implode("\n", $error)), 'CONFIG FILE ERROR');
}
}
// /Custom code
$xml = simplexml_load_string($string, $this->_elementClass);
if ($xml instanceof Varien_Simplexml_Element) {
$this->_xml = $xml;
return true;
}
} else {
Mage::logException(new Exception('"$string" parameter for simplexml_load_string is not a string'));
}
return false;
}
[...]
}
Le principe est très simple : je me contente d'utiliser l'outillage founi par PHP et libxml_use_internal_errors() :
- j'active le gestionnaire d'erreur de la librairie
- je contrôle le fichier XML chargé dont je connais le chemin via
$filePath - en cas d'erreurs, je les compile dans un tableau
- j'enregistre ces erreurs (message, code, fichier, ligne et colonne) dans un fichers de log dédié
- si le DeveloperMode est activée, je lève une exception bien violente
Voilà, c'est tout simple et le résultat est tout de même plus explicite :
expected '>'
Code: 73
File: magento\app\code\local\Narno\MonModule\etc\config.xml
Line: 20
Column: 1
Il semblerait que j'ai mal fermé une balise à la ligne 20 du fichier de configuration de MonModule ! :-)
Encore une fois j'insiste sur le fait qu'il s'agit d'un overlap simple et perfectible (et surtout bourrin). Si vous avez des idées d'amélioration, n'hésitez pas ! :-)
Pour aller plus loin dans la validation des fichiers XML de Magento, il serait nécessaire de valider leur schéma via une DTD (via l'option LIBXML_DTDVALID de l'objet SimpleXMLElement), mais le chantier s'annonce long et pénible...

Bonjour,
Ce code est-il toujours fonctionnel sur une CE 1.6.2 ?
J'ai volontairement supprimé un chevron sur un layout de mon design
xmlcheck est bien un objet, je ne rentre pas du coup dans le test
xmlcheck contient notamment toutes les déclarations Mage
A votre bon coeur
Bonne continuation
P.
A priori le code est toujours valide pour la branche 1.6, mais je n'ai pas testé.
Bon courage !