2011-02-05 3 views
0

Я сделал свой первый класс, используя TDD (SimpleTest). Он работает очень хорошо. Этот класс анализирует файл конфигурации XML и возвращает его как массив. Как я могу улучшить его (производительность, любые подсказки)? Как насчет класса ответственности? Возможно, XMLtoArray следует перенести в другой класс, я не знаю ...Усовершенствования PHP-класса

<?php 
class Configuration 
{ 
    private $domdocument_object; 
    private $domxpath_object; 

    public function __construct($filename) { 
     $this->loadXML($filename); 
     $this->domxpath_object = new DOMXPath($this->domdocument_object); 
    } 

    private function loadXML($filename) 
    { 
     if (!file_exists($filename)) 
     { 
      throw new ConfigurationException('Configuration file not found'); 
     } 

     $this->domdocument_object = $domdocument_object = new DOMDocument(); 
     $this->domdocument_object->preserveWhiteSpace = false; 

     if (!$this->domdocument_object->load($filename)) 
     { 
      throw new ConfigurationException('Malformed configuration file'); 
     } 
    } 

    public function get($path = '/*') { 
     $configuration = array(); 

     $domnodelist_object = $this->domxpath_object->query($path); 
     $configuration = $this->XMLToArray($domnodelist_object); 

     /** 
     * Get a configuration entry as string or array 
     * 
     * For example: 
     * $xml = '<foo><bar>baz</bar></foo>' 
     * $path = '/foo/bar/' 
     * return just baz, as string instead of an array('baz'); 
     * 
     * Another example: 
     * $xml = '<foo><bar>baz</bar><lorem>ipsum</lorem></foo>'; 
     * $path = '/foo' 
     * return just array('bar' => 'baz', 'lorem' => ipsum); 
     * instead of array('foo' => array('bar' => 'baz', 'lorem' => ipsum)); 
     */ 
     while (!is_string($configuration) && count($configuration) == 1) 
     { 
      $configuration_values = array_values($configuration); 
      $configuration = $configuration_values[0]; 
     } 

     if (empty($configuration)) 
     { 
      $configuration = null; 
     } 

     return $configuration; 
    } 

    public function XMLToArray(DOMNodeList $domnodelist_object) { 
     $configuration = array(); 

     foreach ($domnodelist_object as $element) 
     { 
      if ($element->nodeType == XML_DOCUMENT_NODE) 
      { 
       if ($element->hasChildNodes()) 
       { 
        $configuration = $this->XMLToArray($element->childNodes); 
       } 
      } 
      else if ($element->nodeType == XML_ELEMENT_NODE) 
      { 
       if (!$element->hasChildNodes()) 
       { 
        $configuration[$element->nodeName] = null; 
       } 
       else if (
        $element->firstChild->nodeType == XML_TEXT_NODE || 
        $element->firstChild->nodeType == XML_CDATA_SECTION_NODE 
       ) 
       { 
        $configuration[$element->nodeName] = $element->nodeValue; 
       } 
       else if ($element->firstChild->nodeType == XML_ELEMENT_NODE) 
       { 
        $configuration[$element->nodeName] = $this->XMLToArray($element->childNodes); 
       } 
      } 
     } 

     return $configuration; 
    } 
} 
?> 

Этот класс игнорирует атрибуты XML. Спасибо.

+3

Это должно быть перемещено на http://codereview.stackexchange.com/ – RobertPitt

ответ

0

Это плохо сказывается на производительность:

$xml = preg_replace("/>\s+</", "><", $xml); 

Aditionally не гарантируется, чтобы быть надежными (это может изменить комментарии и CDATA-секцию в нежелательных способах). Нелегко найти лучшее решение. Итерация по всем текстовым узлам, обрезающая их, будет более надежной, но не более быстрой.

Если вам просто нужно сделать это, то может быть более подходящим парсер SAX-анализатора php или SimpleXML. Оба варианта могут быть быстрее (я не тестировал).

+0

Это свойство сохранено: http://www.php.net/manual/en/class.domdocument.php#domdocument.props.preservewhitespace. Спасибо. Какие-нибудь советы? – thom

+0

@thom: Да ... Я думал, что для этого должен быть вариант. Почему я не нашел его? Во всяком случае, я думаю, это одно улучшение. – yankee

+0

Человек, ты мне очень помог. Не обвиняйте себя: D. Большое спасибо. – thom

1

Что-то, что выделялось для меня, это создание нового объекта каждый раз, когда объект выполняется, вы должны хранить объект локально (в объекте), а затем он использует только 1 часть вашей памяти.

Вот изменения, которые я хотел бы сделать:

class Configuration 
{ 
    private $domdocument_object; 
    private $domxpath_object; //+ 

    public function __construct($filename) 
    { 
     $this->loadXML($filename); 
     $this->domxpath_object = new DOMXPath($this->domdocument_object); //+ 
    } 

    public function get($path = '/*') 
    { 
     //Remove the following 
     $domxpath_object = new DOMXPath($this->domdocument_object); 
    } 
} 

, а затем изменить $domxpath_object к $this->domxpath_object, где его требуется.

Но это действительно должно быть перенесено на CoderReview, поскольку это не в тему.

+0

Я внес изменения. Спасибо. – thom