<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code-Is-Art &#187; PHP</title>
	<atom:link href="http://www.codeisart.ru/rubric/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codeisart.ru</link>
	<description>Статьи по SEO, дизайну и программированию. Переводы на веб-тематику. Исследования и наработки в области интернет-технологий.</description>
	<lastBuildDate>Thu, 17 Dec 2009 12:00:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.3</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP: Получение последнего сообщения из Twitter-блога</title>
		<link>http://www.codeisart.ru/php-extracting-the-last-twitter-record/</link>
		<comments>http://www.codeisart.ru/php-extracting-the-last-twitter-record/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 17:45:39 +0000</pubDate>
		<dc:creator>Skaizer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=1244</guid>
		<description><![CDATA[Написал небольшой скрипт, который получает последнее сообщение из&#160;Twitter-блога указанного пользователя. Имеет функцию кеширования&#160;&#8212;&#160;сохраняет сообщение в&#160;текстовом файле, что позволяет избежать необходимости каждый раз загружать и&#160;обрабатывать RSS-ленту микроблога. Через определенный промежуток времени кеш обновляется из&#160;web.

Как работает
Писал данный скрипт для одного из&#160;разрабатываемых проектов. Принцип прост: грузится RSS-лента нужного вам пользователя, выбирается последняя запись и,&#160;при необходимости, кешируется в&#160;текстовом файле. [...]]]></description>
			<content:encoded><![CDATA[<p>Написал небольшой скрипт, который получает последнее сообщение из&nbsp;Twitter-блога указанного пользователя. Имеет функцию кеширования&nbsp;&mdash;&nbsp;сохраняет сообщение в&nbsp;текстовом файле, что позволяет избежать необходимости каждый раз загружать и&nbsp;обрабатывать RSS-ленту микроблога. Через определенный промежуток времени кеш обновляется из&nbsp;web.</p>
<p><span id="more-1244"></span></p>
<h3>Как работает</h3>
<p>Писал данный скрипт для одного из&nbsp;разрабатываемых проектов. Принцип прост: грузится RSS-лента нужного вам пользователя, выбирается последняя запись и,&nbsp;при необходимости, кешируется в&nbsp;текстовом файле. XML обрабатывается через <code class="php">DOMDocument</code>.</p>
<p>Атрибут <code class="php">public $cache_file</code> определяет расположение файла кеша.</p>
<p>Атрибут <code class="php">public $cache_period</code> отвечает за&nbsp;частоту обновления кеша. Указывается в&nbsp;секундах (3600&nbsp;соответствует 1&nbsp;часу). Если значение равно 0,&nbsp;кеш игнорируется.</p>
<p>Все остальное, думаю, понятно. Если есть вопросы, задавайте.</p>
<p>Кстати возник вопрос, если интегрировать этот скрипт в&nbsp;какой-либо сайт, допустим в&nbsp;блог, увеличит&nbsp;ли это частоту посещения сайта роботом поисковиков? Ведь с&nbsp;каждым новым обновлением в&nbsp;твиттере будет изменяться частичка контент почти на&nbsp;всех страницах сайта.</p>
<h3>Скомпонованный код</h3>
<pre><code class="php">class GetLastTwitt{

    public $cache_file = './last_twitt.txt';
    public $cache_period = 3600;

    private $username;
    private $dom;

    function __construct($username){
        $this->username = $username;
    }

    private function setEnv(){
        $feed_url = 'http://twitter.com/statuses/user_timeline/'.$this->username.'.rss';

        $this->dom = new DOMDocument();
        $this->dom->load($feed_url);
    }

    private function returnLastTwitt (){
        if&nbsp;($this->cache_period != 0)
            if&nbsp;(file_exists($this->cache_file))
                if&nbsp;($this->cache_period > $this->getCacheDateDiff())
                    return $this->getLastFromCache();

        return $this->getLastFromWeb($this->username);
    }

    private function getLastFromWeb($username){
        $this->setEnv();
        $rows = $this->dom->getElementsByTagName('item');
        $last_twitt = $rows->item(0)->getElementsByTagName('title')->item(0)->nodeValue;
        $this->cache_twitt($last_twitt);
        return $last_twitt;
    }

    private function cache_twitt($msg){
        $handle = fopen($this->cache_file,'w');
        fwrite($handle, $msg);
        fclose($handle);
    }

    private function getCacheDateDiff(){
        return date('U')&nbsp;&#8212; filemtime($this->cache_file);
    }

    private function getLastFromCache(){
        $handle = fopen($this->cache_file,'r');
        $cached_twitt = fread($handle, filesize($this->cache_file));
        fclose($handle);
        return $cached_twitt;
    }

    final function getLast(){
        return $this->returnLastTwitt();
    }

}

$a = new GetLastTwitt('skaizer');
echo $a-&gt;getLast();</code></pre>
<p><b>Скомпонованный готовый скрипт можно</b> <a class="attach zip" href="http://www.codeisart.ru/files/last_twitt.zip">скачать здесь</a>.</p>
<p><img title="Twitter icon" alt="Twitter icon" src="http://www.codeisart.ru/wp-content/uploads/2009/01/twitter-icon.png" class="left"/>У вас есть Twitter аккаунт?<br />
Если да, можете подписаться на мой <a title="Аккаунт Skaizer на Twitter" rel="nofollow" href="http://twitter.com/skaizer" style="text-decoration: line-through;">микроблог</a>, а я, в свою очередь, подпишусь на ваш.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/php-extracting-the-last-twitter-record/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>PHP: Класс-обертка для методов</title>
		<link>http://www.codeisart.ru/php-wrapper-class-for-the-methods/</link>
		<comments>http://www.codeisart.ru/php-wrapper-class-for-the-methods/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 19:32:17 +0000</pubDate>
		<dc:creator>Stepler</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=1154</guid>
		<description><![CDATA[Порой, при написании некоего кода возникают нестандартные требования. К&#160;примеру, при написании модели (MVC) для сайта, мне нужно было, чтобы любой вызываемый из&#160;модели метод был &#171;обернут&#187; неким другим методом, в&#160;котором&#160;бы выполнялись подготовительные действия. В&#160;моем случае должен был, вставлялся блок try&#160;- catch, который&#160;бы &#171;ловил&#187; исключения при обработке запросов к&#160;БД.&#160;О&#160;том, как решил эту проблему, я&#160;хотел&#160;бы написать сегодня.

Итак, наиболее [...]]]></description>
			<content:encoded><![CDATA[<p>Порой, при написании некоего кода возникают нестандартные требования. К&nbsp;примеру, при написании модели (MVC) для сайта, мне нужно было, чтобы любой вызываемый из&nbsp;модели метод был &laquo;обернут&raquo; неким другим методом, в&nbsp;котором&nbsp;бы выполнялись подготовительные действия. В&nbsp;моем случае должен был, вставлялся блок <code class="php">try&nbsp;- catch</code>, который&nbsp;бы &laquo;ловил&raquo; исключения при обработке запросов к&nbsp;БД.&nbsp;О&nbsp;том, как решил эту проблему, я&nbsp;хотел&nbsp;бы написать сегодня.</p>
<p><span id="more-1154"></span></p>
<p>Итак, наиболее простое решение&nbsp;&mdash;&nbsp;это создать метод (<code class="php">wrapper</code>) который в&nbsp;качестве параметров будет принимать название и&nbsp;параметр вызываемого метода. В&nbsp;данном случае метод <code class="php">wrapper</code> и&nbsp;является той самой &laquo;оберткой&raquo;. Реализация этого решения может быть следующей:</p>
<h2>Exceptions.php</h2>
<pre><code class="php">class ExceptionDb extends Exception {}
class ExceptionModel extends Exception {}</code></pre>
<h2>ModelExtension.php</h2>
<pre><code class="php">class ModelExtension {

  function wrapper($method, $data = null) {
    try {

      if (!is_callable(array($this, $method)))
        throw new ExceptionModel('Method "' . $method . '" not found'."\n");

      try {
        return $this->$method($data);
      } catch(ExceptionDb $e) {
        echo $e->getMessage();
      }

    } catch(ExceptionModel $e) {
      echo $e->getMessage();
    }
  }
}</code></pre>
<h2>MyModel.php</h2>
<pre><code class="php">class MyModel extends ModelExtension {

  function query() {
    if (true) {
      echo 'Method "query" is loaded'."\n";
    } else {
      throw new ExceptionDb('Error in method "query"'."\n");
    }
  }

  function errorQuery() {
    if (false) {
      echo 'method "errorQuery" is loaded'."\n";
    } else {
      throw new ExceptionDb('Error in method "errorQuery"'."\n");
    }
  }
}</code></pre>
<h2>index.php</h2>
<pre><code class="php">include 'Exceptions.php';
include 'ModelExtension.php';
include 'MyModel.php';

$myModel = new MyModel();
$myModel->wrapper('query');
$myModel->wrapper('errorQuery');
$myModel->wrapper('anotherQuery'); </code></pre>
<p>Давайте разберем что я&nbsp;тут понаписал.</p>
<p>В&nbsp;примере участвуют несколько файлов:</p>
<ul>
<li><b>Exceptions.php</b>&nbsp;- в&nbsp;нем созданы в&nbsp;исключения, для перехвата ошибок в&nbsp;запросах <code class="php">ExceptionDb</code> и&nbsp;в&nbsp;модели <code class="php">ExceptionModel</code>.</li>
<li><b>ModelExtension.php</b>&nbsp;- родительский класс модели. От&nbsp;него наследуются все модели используемые в&nbsp;проекте. В&nbsp;нем&nbsp;же описан метод <code class="php">wrapper</code>. В&nbsp;качестве первого аргумента он&nbsp;принимает название вызываемого метода, вторым аргументом идут данные, передаваемые в&nbsp;вызываемый метод. Перед вызовом метода, через функцию <code class="php">is_callable</code> проверяется что он&nbsp;существует и&nbsp;может быть вызван, в&nbsp;противном случае генерируется исключение <code class="php">ExceptionModel</code>, которое тут&nbsp;же и&nbsp;перехватывается, т.к. конструкция <code class="php">if&nbsp;- else</code> помещена в&nbsp;блок <code class="php">try&nbsp;- catch</code>. Если метод существует, то&nbsp;он&nbsp;вызывается помещенный при этом в&nbsp;блок <code class="php">try&nbsp;- catch</code>, который перехватывает исключения <code class="php">ExceptionDb</code> запросов в&nbsp;БД.&nbsp;Именно этот момент и&nbsp;нужно было реализовать.</li>
<li><b>MyModel.php</b>&nbsp;- тестовая модель. Класс <code class="php">MyModel</code> расширяет <code class="php">ModelExtension</code>. В&nbsp;нем описаны тестовые методы, выполняющиеся успешно (метод <code class="php">query</code>) или завершающиеся возвратом исключения <code class="php">ExceptionDb</code> (метод <code class="php">errorQuery</code>).</li>
<li><b>index.php</b>&nbsp;- собирает все файлы и&nbsp;запускает тестовый пример.</li>
</ul>
<p>Результатом работы этого примера будут сообщения:</p>
<blockquote><p>Method &laquo;query&raquo; is loaded<br />
Error in method &laquo;errorQuery&raquo;<br />
Method &laquo;anotherQuery&raquo; not found</p>
</blockquote>
<p>Все работает как и&nbsp;ожидалось. Однако очевидно, что конструкция<br />
<code class="php">$model-&lt;wrapper(method [,data])</code> не&nbsp;совсем удачно решение. Куда удобнее и&nbsp;привычнее использовать <code class="php">$model-&lt;method([data])</code>. Сделать это нам поможет один из&nbsp;&laquo;магических&raquo; методов PHP, а&nbsp;именно метод <code class="php">__call</code>. Напомню, что он&nbsp;вызывается всякий раз, когда запрашивается несуществующий метод класса. Можно создать псевдо-класс модели, в&nbsp;котором будет описан только метод <code class="php">__call()</code>, который будет перенаправлять вызов методов на&nbsp;реальный класс модели. Чтобы воплотить задуманное, нужно модифицировать имеющийся код:</p>
<h2>ModelLoader.php</h2>
<pre><code class="php">class ModelLoader {
  private $_modelName;
  private $_model;
  private $_isLoad = false;

  function __construct($name) {
    $this->_modelName = $name;
  }

  function __call($method, $data = null) {
    try {

      if ($this->_isLoad === false) {
        if (!is_callable(array($this->_modelName, '__construct')))
          throw new ExceptionModel('Model class "' . $this->_modelName . '" not found');

        $this->_create_model_();
        $this->_isLoad = true;
      }

      if (!is_callable(array($this->_modelName, $method)))
        throw new ExceptionModel('Method "' . $method . '" not found'."\n");

      try {
        return $this-&gt;_model-&gt;$method($data);
      } catch(ExceptionDb $e) {
        echo $e->getMessage();
      }

    } catch(ExceptionModel $e) {
      echo $e->getMessage();
    }
  }

  private function _create_model_() {
    $this->_model = new $this->_modelName();
  }
}</code></pre>
<h2>MyModel.php</h2>
<pre><code class="php">class MyModel {

  function __construct() {}
  ...

}</code></pre>
<h2>index.php</h2>
<pre><code class="php">include 'Exceptions.php';
include 'ModelLoader.php';
include 'MyModel.php';

$myModel = new ModelLoader('MyModel');
$myModel->query();
$myModel->errorQuery();
$myModel->anotherQuery();</code></pre>
<p>В&nbsp;этом примере мы&nbsp;избавились от&nbsp;класса <code class="php">ModelExtension</code>, и&nbsp;добавили новый&nbsp;&mdash;&nbsp;<code class="php">ModelLoader</code>.</p>
<p>При создании объекта <code class="php">ModelLoader</code> в&nbsp;него передается название класса модели. Метод <code class="php">__call</code> в&nbsp;классе <code class="php">ModelLoader</code> полностью повторяет метод <code class="php">wrapper</code>, с&nbsp;небольшим дополнением, при первом вызове создается экземпляр модели. Перед созданием проверяется, существует&nbsp;ли вызываемый класс. Для того чтобы осуществить эту проверку, мы&nbsp;дополнили класс <code class="php">MyModel</code> функцией <code class="php">__construct</code>.</p>
<p>Вот впринципе и&nbsp;все. Если запустить index.php то&nbsp;результат будет идентичный результату первого примера.</p>
<p><b>Акция</b> &laquo;<a title="Акция обмена постовыми" href="http://www.codeisart.ru/obmen-postovimi/">Обмен постовыми</a>&raquo; продолжается!</p>
<p><b>Скомпонованный готовый скрипт можно</b> <a class="attach zip" href="http://www.codeisart.ru/files/php-wrapper-class-for-the-methods-example.zip">скачать здесь</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/php-wrapper-class-for-the-methods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Создание объектно-ориентированного аналога массива в PHP. Часть 2</title>
		<link>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part2/</link>
		<comments>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part2/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 10:35:37 +0000</pubDate>
		<dc:creator>Stepler</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=1034</guid>
		<description><![CDATA[В&#160;этой статье мы&#160;продолжаем улучшать созданный в&#160;первой части класс ObjectsArr.
В&#160;прошлый раз мы&#160;описали базовую функциональность класса, позволяющую управлять своим содержимым. Но&#160;в&#160;таком виде его использование не&#160;является удобным. В этой статье мы это исправим.

Добавляя данные в&#160;массив, мы&#160;привыкли использовать конструкцию $objArray[key] = value и&#160;врядли мы&#160;нас устроит текущая альтернатива&#160;&#8212;&#160;$objArray-&#62;add(value, key). Так&#160;же в&#160;текущей реализации невозможно просмотреть массив с&#160;помощью конструкции foreach, поэтому если [...]]]></description>
			<content:encoded><![CDATA[<p>В&nbsp;этой статье мы&nbsp;продолжаем улучшать созданный в&nbsp;<a href="http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part1/" title="Создание объектно-ориентированного аналога массива в PHP. Часть 1">первой части</a> класс <code class="php">ObjectsArr</code>.</p>
<p>В&nbsp;прошлый раз мы&nbsp;описали базовую функциональность класса, позволяющую управлять своим содержимым. Но&nbsp;в&nbsp;таком виде его использование не&nbsp;является удобным. В этой статье мы это исправим.</p>
<p><span id="more-1034"></span></p>
<p>Добавляя данные в&nbsp;массив, мы&nbsp;привыкли использовать конструкцию <code class="php">$objArray[key] = value</code> и&nbsp;врядли мы&nbsp;нас устроит текущая альтернатива&nbsp;&mdash;&nbsp;<code class="php">$objArray-&gt;add(value, key)</code>. Так&nbsp;же в&nbsp;текущей реализации невозможно просмотреть массив с&nbsp;помощью конструкции <code class="php">foreach</code>, поэтому если мы&nbsp;добавляем элемент без ключа (ключ будет присвоен автоматически), то&nbsp;мы&nbsp;фактически &laquo;теряем&raquo; элемент.</p>
<p>К&nbsp;счастью, разработчики PHP позаботились об&nbsp;этом, и&nbsp;предоставили в&nbsp;наше распоряжение различные предопределенные интерфейсы, которые позволяют выполнять несвойственные объектам операции.</p>
<p>Наш класс <code class="php">ObjectsArr</code> будет реализовывать интерфейсы: <code class="php">ArrayAccess</code>, <code class="php">IteratorAggregate</code> и&nbsp;<code class="php">Countable</code>. Также будет создан новый класс <code class="php">ObjectsArrInrerator</code>, реализующий интерфейс <code class="php">Iterator</code>.</p>
<p>Теперь обо всем по&nbsp;порядку:</p>
<p>Интерфейс <code class="php">ArrayAccess</code>&nbsp;&mdash;&nbsp;позволяет обращаться к&nbsp;объекту, используя принцип обращения к&nbsp;обычному массиву.</p>
<p>Интерфейс <code class="php">Countable</code>&nbsp;&mdash;&nbsp;позволяет применять функцию <code class="php">count</code> к&nbsp;объекту.</p>
<p>Класс <code class="php">ObjectsArrInrerator</code> в&nbsp;связке с&nbsp;интерфейсом <code class="php">IteratorAggregate</code>&nbsp;&mdash;&nbsp;позволяет просматривать массив, используя оператор <code class="php">foreach</code>.</p>
<h3>Реализация интерфейса ArrayAccess</h3>
<pre><code class="php">//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess {
  //добавляем новые методы
  public function offsetSet($key, $value) {
        $this-&gt;add($value, $key);
  }
  public function offsetUnset($key) {
    $this-&gt;del($key);
  }
  public function offsetGet($key) {
    return $this-&gt;get($key);
    }
  public function offsetExists($key) {
    return $this-&gt;exist($key);
  }
  //остальное описание класса …
}</code></pre>
<p>Как вы&nbsp;можете видеть, новые методы являются оберткой уже существующих, но&nbsp;именно с&nbsp;помощью них можно обращаться к&nbsp;объекту, как к&nbsp;массиву. В&nbsp;частности теперь возможно:</p>
<ul>
<li>использовать <code class="php">$objArray[key] = value</code> вместо <code class="php">$objArray-&gt;add(value, key)</code></li>
<li>использовать <code class="php">unset($objArray[key])</code> вместо <code class="php">$objArray-&gt;del(key)</code></li>
<li>использовать <code class="php">$objArray[key]</code> вместо <code class="php">$objArray-&gt;get(key)</code></li>
<li>использовать <code class="php">isset($objArray[key])</code> или <code class="php">empty($objArray[key])</code> вместо <code class="php">$objArray-&gt;exist (key)</code></li>
</ul>
<h3>Реализация интерфейса Countable</h3>
<pre><code class="php">//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess, Countable {
//добавляем новые методы
  public function count() {
    return $this-&gt;length();
  }
//остальное описание класса …
}</code></pre>
<p>Как и&nbsp;в&nbsp;предыдущем случае, теперь можно использовать <code class="php">count($objArray)</code> вместо <code class="php">$objArray-&gt;length()</code>.</p>
<h3>Разработка класса ObjectsArrInrerator и&nbsp; реализация интерфейса IteratorAggregate</h3>
<p>Новый класс, который будет использоваться при просмотре объекта в&nbsp;<code class="php">foreach</code>:</p>
<pre><code class="php">class ObjectsArrInrerator implements Iterator {
  private $_list;
  private $_current;
  private $_keys;

  function __construct(ObjectsArr $obj) {
    $this-&gt;_list = $obj;
    $this-&gt;_keys = $this-&gt;_list-&gt;keys();
  }

  function rewind() {
    $this-&gt;_current = 0;
  }

  function valid() {
    return $this-&gt;_current < $this-&gt;_list-&gt;length();
  }

  function key() {
    return $this-&gt;_keys[$this-&gt;_current];
  }

  function next() {
    $this-&gt;_current++;
  }

  function current() {
    return $this-&gt;_list-&gt;get($this-&gt;_keys[$this-&gt;_current]);
  }
}</code></pre>
<p>Готово! Эти методы объяснять думаю не&nbsp;стоит. Названия у&nbsp;них говорят сами за&nbsp;себя. Они будут использоваться конструкцией <code class="php">foreach</code> при просмотре объекта. Если Вам интересна последовательность их&nbsp;вызова, добавьте в&nbsp;каждый из&nbsp;них <code class="php">echo</code> с&nbsp;названием метода, и&nbsp;увидите как <code class="php">foreach</code> &laquo;смотрит&raquo; наш объект.</p>
<p>И&nbsp;последнее на&nbsp;сегодня:</p>
<pre><code class="php">//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess, Countable, IteratorAggregate {
  //добавляем новые методы
  function getIterator() {
    return new ObjectsArrInrerator (clone $this);
  }
  //остальное описание класса …
}</code></pre>
<p>Метод <code class="php">getIterator</code> будет вызываться при попытке просмотреть объект через <code class="php">foreach</code>.</p>
<p>В&nbsp;PHP существует сразу встроенный аналог только что созданного нами класса. Это класс <code class="php">ArrayObject</code>. Но&nbsp;попытка изменения объекта в&nbsp;ходе перебора его элементов, может привести к&nbsp;плачевным последствиям. Об&nbsp;этом я&nbsp;написал в&nbsp;комментарии, к&nbsp;<a href="http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part1/#comment-2393" title="Создание объектно-ориентированного аналога массива в PHP. Часть 1">предыдущей статье</a>. Избежать такого поведения позволяет передача интератору, не&nbsp;самого просматриваемого объекта, а&nbsp;его копии&nbsp;&mdash;&nbsp;<code class="php">return new ObjectsArrInrerator(clone $this)</code>.</p>
<h3>Тестирование класса <code class="php">ObjectsArr</code></h3>
<p>Осталось только протестировать наш класс. Для тестирования я взял тот же пример, что и в предыдущей статье, чтобы наглядно было видно как изменился наш класс.</p>
<pre><code class="php">$clientsList = new ObjectsArr();
try {
$clientsList['ivan'] = new Client('Ваня'); //Добавляем нового клиента
$clientsList['alexander'] = new Client('Саша'); //Добавляем нового клиента
$clientsList['petr'] = new Client('Петя'); //Добавляем нового клиента

$objIvan = $clientsList['ivan']; //Извлекаем клиента
echo $objIvan; // выведет ->  Клиент - "Ваня"

foreach ($clientsList as $key => $value) { //Просмотр всей коллекции объектов
  echo $key . ' -> ' . $value . "\r\n";
}

unset($clientsList['ivan']); //удаляем клиента

$clientsList['petr'] = new Client('Петр Иванович'); /*перехват исключения, т.к. ключ "petr" уже используется
                                                          выведет -> Ключ "petr" уже используется. */
} catch (Exception $e) {
  echo $e->getMessage();
}</code></pre>
<p>На&nbsp;данный момент все. Мы&nbsp;реализовали еще одно из&nbsp;предъявленных к&nbsp;классу <code class="php">ObjectsArr</code> требований, а&nbsp;именно:</p>
<blockquote><p> возможность перебора всей коллекции элементов</p></blockquote>
<p>Использование класса так&nbsp;же стало более удобным. Теперь его трудно отличить от&nbsp;обычного массива.</p>
<p>В&nbsp;следующей&nbsp;&mdash;&nbsp;заключительной статье мы&nbsp;добавим механизм заполнения массива при первом обращении к&nbsp;нему.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Создание объектно-ориентированного аналога массива в PHP. Часть 1</title>
		<link>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part1/</link>
		<comments>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part1/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 13:12:06 +0000</pubDate>
		<dc:creator>Stepler</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=1017</guid>
		<description><![CDATA[В&#160;этой статье речь пойдет о&#160;том, как создать объектно-ориентированный аналог массива в&#160;PHP.
Но&#160;для начала давайте разберемся, чем нас не&#160;устраивает обычный массив. Предположим, Вы&#160;разрабатываете какое-либо корпоративное приложение, и&#160;в&#160;нем необходим перечень менеджеров с&#160;прилагающимся списком обслуженных клиентов.

class Client  {
  public $name;
//описание класса
}
class Manager  {
  public $clients = array();
//описание класса
//где-то в нем происходит  заполнение массива
//объектами класса [...]]]></description>
			<content:encoded><![CDATA[<p>В&nbsp;этой статье речь пойдет о&nbsp;том, как создать объектно-ориентированный аналог массива в&nbsp;PHP.</p>
<p>Но&nbsp;для начала давайте разберемся, чем нас не&nbsp;устраивает обычный массив. Предположим, Вы&nbsp;разрабатываете какое-либо корпоративное приложение, и&nbsp;в&nbsp;нем необходим перечень менеджеров с&nbsp;прилагающимся списком обслуженных клиентов.</p>
<p><span id="more-1017"></span></p>
<pre><code class="php">class Client  {
  public $name;
//описание класса
}
class Manager  {
  public $clients = array();
//описание класса
//где-то в нем происходит  заполнение массива
//объектами класса Client
}
//просмотр список обслуженных клиентов
$objManager  = new Manager(‘id’);
foreach ($objManager-&gt;clients as $client) {
  echo $client-&gt;name;
}</code></pre>
<p>В&nbsp;принципе мы&nbsp;получили что хотели&nbsp;&mdash;&nbsp;список клиентов. Однако данный подход не&nbsp;является хорошим решением по&nbsp;нескольким причинам:</p>
<ul>
<li>открытый массив <code class="php">$objManager->clients</code> нарушает <a href="http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%BA%D0%B0%D0%BF%D1%81%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)" title="Значение слова инкапсуляция в википедии">инкапсуляцию</a>. Массив можно сделать закрытым с&nbsp;доступом к&nbsp;нему через метод <code class="php">$objManager->getClients()</code>. Но&nbsp;такой подход не&nbsp;поможет, в&nbsp;случае если возникнет необходимость его модифицировации по&nbsp;ходу его просмотра. Если&nbsp;же оставить массив открытым для возможности модификации, то&nbsp;мы&nbsp;не&nbsp;сможем контролировать и/или фильтровать информацию заносящуюся в&nbsp;него.</li>
<li>информация по&nbsp;клиентам будет загружена при создании объекта, даже если нужно только имя менеджера и&nbsp;не&nbsp;больше. Конечно, можно создать метод <code class="php">$objManager->loadClientsInfo()</code>, только после вызова которого будет подгружена информация о&nbsp;клиентах, однако удобнее было&nbsp;бы если информация будет подгружена автоматически в&nbsp;момент когда к&nbsp;ней обратятся.</li>
</ul>
<p>Для решения этих проблем создадим класс <code class="php">ObjectsArr</code>&nbsp;&mdash;&nbsp;оболочку вокруг массива объектов. Предъявим к&nbsp;нему следующие требования:</p>
<ol>
<li>предоставление механизма добавления, удаления и&nbsp;извлечения элементов;</li>
<li>заполнение информации по&nbsp;клиентам при первом обращении к&nbsp;ней;</li>
<li>возможность перебора всей коллекции элементов. (<code class="php">for</code>, <code class="php">foreach</code>)</li>
</ol>
<p>Описание реализации этих требований довольно громоздко, поэтому разобьем нашу статью на&nbsp;несколько частей. В&nbsp;каждой новой части мы&nbsp;будем наращивать функциональность класса <code class="php">ObjectsArr</code>.</p>
<p>Итак, давайте создадим класс <code class="php">ObjectsArr</code> и&nbsp;прикрутим к&nbsp;нему механизм управления содержимым.</p>
<h3>Класс <code class="php">ObjectsArr</code></h3>
<pre><code class="php">class ObjectsArr {
  private $_list = array();
}</code></pre>
<h4>Метод добавления элемента</h4>
<pre><code class="php">public  function add($value, $key = null) {
  if ($key === null || empty($key)){
    $this-&gt;_list[] = $data;
    return;
  }
 
  if (!isset($this-&gt;_list[$key])){
    $this-&gt;_list[$key] = $data;
  } else {
    throw new Exception('Ключ &quot;' . $key . '&quot; уже  используется.');
  }
}</code></pre>
<p>Метод <code class="php">add</code> принимает 2&nbsp;аргумента, добавляемый элемент и&nbsp;его ключ. Ключ является необязательным, если его опустить, то&nbsp;он&nbsp;будет генерироваться автоматически. При попытке добавить элемент с&nbsp;уже существующим ключом будет сгенерировано исключение.</p>
<h4>Метод удаления элемента</h4>
<pre><code class="php">public  function del($key)  {
  if (isset($this-&gt;_list[$key])) {
    unset($this-&gt;_list[$key]);
  } else {
    throw new Exception('Элемент с ключем  &quot;' . $key . '&quot; отсутсвует.');
  }
}</code></pre>
<p>Удаляет элемент по&nbsp;его ключу. Если ключ отсутствует, то&nbsp;генерируется исключение.</p>
<h4>Метод извлечения элемента</h4>
<pre><code class="php">public  function get($key) {
  if (isset($this-&gt;_list[$key])) {
    return $this-&gt;_list[$key];
  } else {
    throw new Exception('Элемент с ключем  &quot;' . $key .  '&quot; отсутсвует.');
  }
}</code></pre>
<p>Извлекает элемент по&nbsp;его ключу. Если ключ отсутствует, то&nbsp;генерируется исключение.</p>
<h4>Метод проверки наличия элемента</h4>
<pre><code class="php">public function exist($key) {
  return isset($this-&gt;_list[$key]);
}</code></pre>
<p>Поскольку добавление элемента с&nbsp;существующим ключем сгенерирует исключение, то&nbsp;данная функция позволяет проверить, используется&nbsp;ли ключ или нет.</p>
<h4>Метод получения всех элементов</h4>
<pre><code class="php">public function keys() {
  return array_keys($this-&gt;_list);
}</code></pre>
<p>Эта функция позволяет получить все имеющиеся ключи добавленных элементов.</p>
<h4>Метод подсчета добавленных элементов</h4>
<pre><code class="php">public function length() {
  return count($this-&gt;_list);
}</code></pre>
<p>Эта функция возвращает количество установленных элементов.</p>
<h4>Весь класс, полностью</h4>
<p>Это все. Полностью класс <code class="php">ObjectsArr</code> будет выглядеть так:</p>
<pre><code class="php">class ObjectsArr {
  private $_list = array();
 
  public function add($value, $key = null) {
    if ($key === null || empty($key)){
      $this-&gt;_list[] = $data;
      return;
    }
   
    if (!isset($this-&gt;_list[$key])){
      $this-&gt;_list[$key] = $data;
    } else {
      throw new Exception('Ключ &quot;' . $key . '&quot; уже  используется.');
    }
  }
 
  public function del($key) {
    if (isset($this-&gt;_list[$key])) {
      unset($this-&gt;_list[$key]);
    } else {
      throw new Exception('Элемент с  ключем &quot;' . $key .  '&quot; отсутсвует.');
    }
  }
 
  public function get($key) {
    if (isset($this-&gt;_list[$key])) {
      return $this-&gt;_list[$key];
    } else {
      throw new Exception('Элемент с  ключем &quot;' . $key .  '&quot; отсутсвует.');
    }
  }
 
  public function exist($key) {
    return isset($this-&gt;_list[$key]);
  }
 
  public function keys() {
    return array_keys($this-&gt;_list);
  }
 
  public function length() {
    return count($this-&gt;_list);
  }
}</code></pre>
<h3>Тестирование класса <code class="php">ObjectsArr</code></h3>
<pre><code class="php">$clientsList = new ObjectsArr();
try {
$clientsList->add(new Client('Ваня'), 'ivan'); //Добавляем нового клиента
$clientsList->add(new Client('Саша'), 'alexander'); //Добавляем нового клиента
$clientsList->add(new Client('Петя'), 'petr'); //Добавляем нового клиента

$objIvan = $clientsList->get('ivan'); //Извлекаем клиента
echo $objIvan; // выведет ->  Клиент - "Ваня"
$clientsList->del('ivan'); //удаляем клиента
$clientsList->add(new Client('Петр Иванович'), 'petr'); /*перехват исключения, т.к. ключ "petr" уже используется
                                                          выведет -> Ключ "petr" уже используется. */
} catch (Exception $e) {
  echo $e->getMessage();
}</code></pre>
<p>Добавляемую информацию, так&nbsp;же можно фильтровать. Я&nbsp;намеренно не&nbsp;стал этого делать, т.к. от&nbsp;приложения к&nbsp;приложению требования (а&nbsp;значит и&nbsp;фильтры) могут меняться. Все их&nbsp;можно добавить, расширив базовый класс <code class="php">ObjectsArr</code>. Для примера, реализуем возможность добавления только объектов в&nbsp;коллекцию:</p>
<pre><code class="php">class MyObjectsArr extends ObjectsArr {
  public function add(object $value, $key = null) {
    parent::add($value, $key);
  }
}</code></pre>
<p>Или</p>
<pre><code class="php">class MyObjectsArr extends ObjectsArr {
  public function add($value, $key = null) {
    if (!is_object($value))
      throw new Exception('Добавляемый элемент не является объектом.');

    parent::add($value, $key);
  }
}</code></pre>
<p>Итак, класс <code class="php">ObjectsArr</code> функционирует и&nbsp;отвечает нашему первому требованию:</p>
<blockquote><p>предоставление механизма добавления, удаления и&nbsp;извлечения элементов</p>
</blockquote>
<p>Использовать класс в&nbsp;таком виде, в&nbsp;каком он&nbsp;представлен сейчас&nbsp;&mdash;&nbsp;неудобно. Связано это с&nbsp;тем что мы&nbsp;не&nbsp;реализовали все требования предъявленные к&nbsp;нему.</p>
<p>В&nbsp;следующий статьях мы&nbsp;продолжим наращивать его функциональность.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/creating-object-oriented-analog-array-in-php-part1/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Создание и разбор данных формата JSON в PHP</title>
		<link>http://www.codeisart.ru/creating-parsing-json-data-php/</link>
		<comments>http://www.codeisart.ru/creating-parsing-json-data-php/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 22:38:34 +0000</pubDate>
		<dc:creator>Skaizer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=1006</guid>
		<description><![CDATA[В&#160;этой статье я&#160;хочу рассказать о&#160;текстовом формате обмена данными&#160;&#8212;&#160;JSON, а&#160;именно&#160;&#8212;&#160;про работу с&#160;этим форматом в&#160;PHP.
JSON&#160;&#8212;&#160;компактный текстовый формат данных. Может применяться как в&#160;интернет-службах передачи данных, так и&#160;для хранения информации в&#160;структурированном виде.

Описание JSON из&#160;википедии:
JSON (англ. JavaScript Object Notation)&#160;&#8212;&#160;текстовый формат обмена данными, основанный на&#160;JavaScript и&#160;обычно используемый именно с&#160;этим языком. Как и&#160;многие другие текстовые форматы, JSON легко читается людьми.
Несмотря на&#160;происхождение от&#160;JavaScript [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.codeisart.ru/wp-content/uploads/2008/12/json.gif" class="left" alt="Логотип JSON" />В&nbsp;этой статье я&nbsp;хочу рассказать о&nbsp;текстовом формате обмена данными&nbsp;&mdash;&nbsp;JSON, а&nbsp;именно&nbsp;&mdash;&nbsp;про работу с&nbsp;этим форматом в&nbsp;PHP.</p>
<p>JSON&nbsp;&mdash;&nbsp;компактный текстовый формат данных. Может применяться как в&nbsp;интернет-службах передачи данных, так и&nbsp;для хранения информации в&nbsp;структурированном виде.</p>
<p><span id="more-1006"></span></p>
<p>Описание <a href="http://json.org/">JSON</a> из&nbsp;<a href="http://ru.wikipedia.org/wiki/JSON" title="Описание формата JSON из&nbsp;википедии">википедии</a>:</p>
<blockquote><p>JSON (<i>англ. JavaScript Object Notation</i>)&nbsp;&mdash;&nbsp;текстовый формат обмена данными, основанный на&nbsp;JavaScript и&nbsp;обычно используемый именно с&nbsp;этим языком. Как и&nbsp;многие другие текстовые форматы, JSON легко читается людьми.</p>
<p>Несмотря на&nbsp;происхождение от&nbsp;JavaScript (точнее, от&nbsp;подмножества языка стандарта ECMA-262&nbsp;1999&nbsp;года), формат считается языконезависимым и&nbsp;может использоваться практически с&nbsp;любым языком программирования. Для многих языков существует готовый код для создания и&nbsp;обработки данных в&nbsp;формате JSON.</p>
<p>Практическая польза использования JSON открывается при использовании технологии <abbr title="Asynchronous Javascript and XML">AJAX</abbr>. Формат JSON является более кратким и&nbsp;удобочитаемым по&nbsp;сравнению с&nbsp;<abbr title="eXtensible Markup Language">XML</abbr>, является &laquo;родным&raquo; для Javascript. Кроме того, в&nbsp;JSON-код возможна вставка вполне работоспособных функций.</p>
</blockquote>
<p>Да,&nbsp;именно в&nbsp;технологии <abbr title="Asynchronous Javascript and XML">AJAX</abbr>, на&nbsp;мой взгляд, его основное применение. Так как технология <abbr title="Asynchronous Javascript and XML">AJAX</abbr> подразумевает отправку запроса клиентов на&nbsp;сервер. Далее на&nbsp;сервере запрос обрабатывается, и&nbsp;результат отправляется в&nbsp;ответ клиенту.</p>
<h3>Вид данных в&nbsp;формате JSON</h3>
<p>JSON поддерживает все основные форматы данных: строки, числа, булевые значения, а&nbsp;так&nbsp;же массивы и&nbsp;объекты (комбинации ключ: значение, разделенные запятыми и&nbsp;заключающимися в&nbsp;фигурные скобки).</p>
<p>Приведем пример представления данных в&nbsp;формате JSON:</p>
<pre><code>{&quot;id&quot;:&quot;1&quot;,&quot;name&quot;:&quot;ivan&quot;,&quot;country&quot;:&quot;Russia&quot;,&quot;office&quot;:[&quot;yandex&quot;,&quot;management&quot;]}</code></pre>
<p>Давайте разберем, что этой строкой можно передать: человек с&nbsp;именем &laquo;ivan&raquo;, под идентификатором &laquo;1&raquo;, проживающий в&nbsp;стране &laquo;Russia&raquo; работает в&nbsp;компании &laquo;yandex&raquo; в&nbsp;отделе &laquo;management&raquo;.</p>
<p>Приведем еще один пример. На&nbsp;сайте имеется форма обратной связи, работающая по&nbsp;технологии <abbr title="Asynchronous Javascript and XML">AJAX</abbr>. Посетитель заполняет информацию, далее она отправляется на&nbsp;сервер для проверки, если ошибок не&nbsp;найдено, информация сохраняется в&nbsp;базу данных и&nbsp;отправляется ответ об&nbsp;успешном сохранении. Но&nbsp;если найдены ошибки, то&nbsp;возвращается ответ с&nbsp;типами ошибок.</p>
<p>Пример ответа об&nbsp;ошибке в&nbsp;формате JSON:</p>
<pre><code>{&quot;error&quot;:&quot;1&quot;,&quot;errorcode&quot;:[&quot;empty_pers&quot;,&quot;empty_mail&quot;,&quot;empty_phone&quot;,&quot;empty_letter&quot;,&quot;empty_scode&quot;]}</code></pre>
<p>Что, к&nbsp;примеру, означает:</p>
<ul>
<li>Необходимо заполнить поле &laquo;Контактное лицо&raquo;</li>
<li>Необходимо заполнить поле &laquo;E-mail&raquo;</li>
<li>Необходимо заполнить поле &laquo;Телефон&raquo;</li>
<li>Введите текст сообщения</li>
<li>Необходимо заполнить поле &laquo;Число на&nbsp;картинке&raquo;</li>
</ul>
<p>В&nbsp;случае, если ошибок нет, то&nbsp;возвращается ответ:</p>
<pre><code>{&quot;error&quot;:&quot;0&quot;}</code></pre>
<p>Что говорит об&nbsp;успешной отправке данных.</p>
<p>В&nbsp;PHP, для представления данных в&nbsp;формате JSON служит расширение <a href="http://ru2.php.net/json" title="Расширение языка PHP для работы с форматом JSON">JSON extension</a>. В&nbsp;версиях PHP старше 5.2.0&nbsp;поддержка JSON встроена в&nbsp;ядро, в&nbsp;более ранних версиях необходимо подключать к&nbsp;вашему скрипту дополнительный файл с&nbsp;функциями.</p>
<p>Итак в&nbsp;PHP, за&nbsp;работу с&nbsp;данными в&nbsp;формате JSON отвечают две функции: <a href="http://www.php.net/manual/ru/function.json-encode.php" title="Функция представления данных в формате JSON">json_encode()</a> и&nbsp;<a href="http://www.php.net/manual/ru/function.json-decode.php" title="Функция преобразования данных из формата JSON">json_decode()</a>.</p>
<h3>Конвертация данных в&nbsp;формат JSON</h3>
<pre><code class="php">$json_data = array ('id'=&gt;1,'name'=&gt;&quot;ivan&quot;,'country'=&gt;'Russia',&quot;office&quot;=&gt;array(&quot;yandex&quot;,&quot; management&quot;));
echo json_encode($json_data);</code></pre>
<h3>Обратное преобразование данных из&nbsp;формата JSON</h3>
<pre><code class="php">$json_string='{&quot;id&quot;:1,&quot;name&quot;:&quot;ivan&quot;,&quot;country&quot;:&quot;Russia&quot;,&quot;office&quot;:[&quot;yandex&quot;,&quot; management&quot;]} ';
$obj=json_decode($json_string);</code></pre>
<p>Теперь в&nbsp;$obj будут содержаться JSON данные переведенные в&nbsp;PHP-объект, доступ к&nbsp;которым вы&nbsp;сможете получить следующим образом:</p>
<pre><code class="php">echo $obj-&gt;name; //Отобразит имя ivan
echo $obj-&gt;office[0]; //Отобразит компанию yandex</code></pre>
<p>Как видите, $obj-&gt;office является  массивом.</p>
<pre><code class="php">foreach($obj-&gt;office as $val)
&nbsp;&nbsp;echo $val;</code></pre>
<p>Работа с&nbsp;JSON позволяет обмениваться с&nbsp;сервером данными в&nbsp;<i>&laquo;чистом виде&raquo;</i>. Полностью отпадает необходимость пересылать громоздкие куски HTML кода.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/creating-parsing-json-data-php/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Автоматическая подгрузка файлов с&#160;PHP-классами или избавляемся от&#160;include-ов</title>
		<link>http://www.codeisart.ru/php-class-files-autoload/</link>
		<comments>http://www.codeisart.ru/php-class-files-autoload/#comments</comments>
		<pubDate>Sat, 20 Dec 2008 23:37:04 +0000</pubDate>
		<dc:creator>Stepler</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=998</guid>
		<description><![CDATA[В этой статье я&#160;хочу рассказать, как избавиться от&#160;include-ов файлов с&#160;PHP-классами и&#160;сделать их&#160;подгрузку полностью автоматической.
Этот метод актуален только для объектно-ориентированного стиля программирования, и&#160;будет работать в&#160;версии PHP 5.1.2 и&#160;выше.

Давайте рассмотрим пример. Имеем два файла:
Файл example.php:
&#60;?php
class example {
  static  function call() {
    echo  'You call &#34;' . __CLASS__ . '&#34; class.';
  [...]]]></description>
			<content:encoded><![CDATA[<p>В этой статье я&nbsp;хочу рассказать, как избавиться от&nbsp;include-ов файлов с&nbsp;PHP-классами и&nbsp;сделать их&nbsp;подгрузку <strong>полностью автоматической</strong>.</p>
<p>Этот метод актуален только для объектно-ориентированного стиля программирования, и&nbsp;будет работать в&nbsp;версии <b>PHP 5.1.2 и&nbsp;выше</b>.</p>
<p><span id="more-998"></span></p>
<p>Давайте рассмотрим пример. Имеем два файла:</p>
<p>Файл example.php:</p>
<pre><code class="php">&lt;?php
class example {
  static  function call() {
    echo  'You call &quot;' . __CLASS__ . '&quot; class.';
  }
}
?&gt;</code></pre>
<p>Файл index.php:</p>
<pre><code class="php">&lt;?php
  include 'example.php';
  example::call();
?&gt;</code></pre>
<p>Оба файла находятся в&nbsp;одной директории. В&nbsp;первом файле example.php объявлен класс example. Во&nbsp;втором файле мы&nbsp;подключаем example.php и&nbsp;вызываем метод call класса example. Метод call является статическим, поэтому нам не&nbsp;обязательно создавать экземпляр класса example для его вызова.</p>
<p>Результатом выполнения этого скрипта будет сообщение &laquo;You call &quot;example&quot; class.&raquo;</p>
<p>Для использования класса example, нам нужно было подгрузить соответствующий файл&nbsp;&mdash;&nbsp;example.php.</p>
<p>А теперь представьте, что классов у&nbsp;вас сотни, и&nbsp;вам нужно вручную каждый раз прописывать инклуды файлов с&nbsp;классами, чтобы все их&nbsp;использовать.</p>
<p>Давайте поступим проще! Напишем функцию, которая будет <strong>автоматически подгружать</strong> нужный нам файл с&nbsp;классом только тогда, когда мы&nbsp;начинаем использовать этот класс. То&nbsp;есть, если класс в&nbsp;ходе выполнения сценария не&nbsp;используется, то&nbsp;и&nbsp;подключать с&nbsp;ним файл нет необходимости.</p>
<p>Модифицируем предыдущий пример:</p>
<p>Файл autoload.php:</p>
<pre><code class="php">&lt;?php
spl_autoload_register ('autoload');
function autoload ($className) {
  $fileName = $className . '.php';
  include  $fileName;
  }
?&gt;</code></pre>
<p>Файл example.php:</p>
<pre><code class="php">&lt;?php
  class example {
  static  function call() {
  echo  'You call &quot;' . __CLASS__ . '&quot; class.';
  }
  }
?&gt;</code></pre>
<p>Файл index.php:</p>
<pre><code class="php">&lt;?php
  include 'autoload.php';
  example::call();
?&gt;</code></pre>
<p>Мы добавили новый файл autoload.php и&nbsp;подгрузили его в&nbsp;index.php. Обратите внимание&nbsp;&mdash;&nbsp;мы&nbsp;все также вызываем <code class="php">example::call()</code>, и&nbsp;вместо &laquo;<i><b>Fatal error</b>: Class &quot;example&quot; not found in&nbsp;&#8230;</i>&raquo; получаем прежний результат&nbsp;&mdash;&nbsp;&laquo;<i>You call &quot;example&quot; class.</i>&raquo;. Даже без ручной подгрузки файла example.php, класс example нашелся и&nbsp;его метод вызвался. Как так получилось?</p>
<p>PHP позволяет задать обработчик (функцию или метод класса) который будет вызываться всякий раз при обращении к&nbsp;классу, который еще не&nbsp;определен. Аргументом функции-обработчика является имя вызываемого класса. Обработчик мы&nbsp;определяем с&nbsp;помощью функции <code class="php">spl_autoload_register()</code>. Если в&nbsp;качестве обработчика выступает функция, то&nbsp;аргументом <code class="php">spl_autoload_register()</code> будет являться строка с&nbsp;именем функции (как в&nbsp;примере). Если&nbsp;же в&nbsp;качестве обработчика выступает метод класса, то&nbsp;аргументом <code class="php">spl_autoload_register()</code> будет являться массив, первый элемент которого соответствует названию класса, а&nbsp;второй названию метода этого класса&nbsp;&mdash;&nbsp;<code class="php">spl_autoload_register(array('someoneClass', 'someoneMethod'))</code>. Метод-обработчик должен быть статическим.</p>
<p>В нашем примере, в&nbsp;качестве обработчика я&nbsp;использовал функцию <code class="php">autoload()</code>. К&nbsp;имени вызываемого класса она добавляет расширение &laquo;.php&raquo; и&nbsp;пытается подгрузить файл &lt;class&gt;.php, где &lt;class&gt;&nbsp;&mdash;&nbsp;имя вызываемого класса.</p>
<p>Мы привели простой пример, чтобы вы&nbsp;поняли, как работает метод автоматической подгрузки файлов с&nbsp;классами, в&nbsp;следующий раз покажем реальное применение, где это может использоваться.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/php-class-files-autoload/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>6&#160;PHP&#160;трюков, как&#160;сделать код&#160;короче</title>
		<link>http://www.codeisart.ru/php-coding-tips-to-write-less-code/</link>
		<comments>http://www.codeisart.ru/php-coding-tips-to-write-less-code/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 10:03:59 +0000</pubDate>
		<dc:creator>Skaizer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Переводы]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=429</guid>
		<description><![CDATA[Недавно нашел англоязычную статью, в&#160;которой описывались приемы сокращения PHP-кода. Признаюсь, некоторые методы мне&#160;были известны, а&#160;о&#160;некоторых я&#160;даже не&#160;подозревал. Поэтому решили выложить русскоязычный вариант статьи, думаю Вы&#160;найдете в&#160;ней&#160;что-то новое для&#160;себя.
		
PHP&#160;&#8212; хороший язык, но&#160;в&#160;нем всегда полно сюрпризов. И&#160;сегодня я&#160;увидел интересную статью в&#160;блоге Арнольда Дэниэлса. Он&#160;рассуждает о&#160;&#171;временных&#160;переменных&#187; в&#160;РНР. Этот&#160;прием полезен для&#160;&#171;ленивых&#187; разработчиков, которые даже&#160;не&#160;задумываются о&#160;названиях переменных. Они&#160;предпочитают такое наименование, [...]]]></description>
			<content:encoded><![CDATA[<p>Недавно нашел англоязычную <a href="http://www.alexatnet.com/node/100" title="6 PHP coding tips to write less code" hreflang="en" rel="original" rev="translation">статью</a>, в&nbsp;которой описывались приемы сокращения <abbr title="Hypertext Preprocessor">PHP</abbr>-кода. Признаюсь, некоторые методы мне&nbsp;были известны, а&nbsp;о&nbsp;некоторых я&nbsp;даже не&nbsp;подозревал. Поэтому решили выложить русскоязычный вариант статьи, думаю Вы&nbsp;найдете в&nbsp;ней&nbsp;что-то новое для&nbsp;себя.</p>
<p>		<span id="more-429"></span></p>
<p><abbr title="Hypertext Preprocessor">PHP</abbr>&nbsp;&mdash; хороший язык, но&nbsp;в&nbsp;нем всегда полно сюрпризов. И&nbsp;сегодня я&nbsp;увидел интересную статью в&nbsp;блоге Арнольда Дэниэлса. Он&nbsp;рассуждает о&nbsp;&laquo;<a href="http://blog.adaniels.nl/?p=58" hreflang="en">временных&nbsp;переменных</a>&raquo; в&nbsp;РНР. Этот&nbsp;прием полезен для&nbsp;&laquo;ленивых&raquo; разработчиков, которые даже&nbsp;не&nbsp;задумываются о&nbsp;названиях переменных. Они&nbsp;предпочитают такое наименование, как&nbsp;&laquo;<code>${0}</code>&raquo; и&nbsp;&laquo;<code>0</code>&raquo;&nbsp;&mdash; ведь&nbsp;это&nbsp;хорошее название для&nbsp;переменной, почему&nbsp;нет&hellip;</p>
<p>Но&nbsp;я&nbsp;уверен, что&nbsp;когда нет&nbsp;переменной, нет&nbsp;и&nbsp;проблемы. Поэтому приведу&nbsp;несколько приемов, которые делают Ваш&nbsp;код короче и&nbsp;труднее для&nbsp;восприятия&nbsp;:)</p>
<ol>
<li>
<h3>Используйте <code>||</code>&nbsp;(или) и&nbsp;<code>&amp;&amp;</code>&nbsp;(и) вместо&nbsp;<code>if</code></h3>
<p class="bold">Много кода:</p>
<pre><code class="php">$status = fwrite($h, 'some text');
if(!$status) {
    log('Writing failed');
}</code></pre>
<p class="bold">Меньше кода:</p>
<pre><code class="php">${0} = fwrite($h, 'some text');
if(!${0}) log('Writing failed');</code></pre>
<p class="bold">Еще меньше кода:</p>
<pre><code class="php">fwrite($h, 'some text') or log('Writing failed');</code></pre>
</li>
<li>
<h3>Используйте &laquo;тернарный оператор&raquo;</h3>
<p class="bold">Много кода:</p>
<pre><code class="php">if($age &lt; 16) {
    $message = 'Welcome!';
}
else {
  $message = 'You are too old!';
}</code></pre>
<p class="bold">Меньше кода:</p>
<pre><code class="php">$message = 'You are too old!';
if($age &lt; 16) {
    $message = 'Welcome!';
}</code></pre>
<p class="bold">Еще меньше кода:</p>
<pre><code class="php">$message = ($age &lt; 16) ? 'Welcome!' : 'You are too old!';</code></pre>
</li>
<li>
<h3>Используйте &laquo;<code>for</code>&raquo; вместо &laquo;<code>while</code>&raquo;</h3>
<p class="bold">Много кода:</p>
<pre><code class="php">$i = 0;
while($i &lt; 100) {
  $source[] = $target[$i];
  $i += 2;
}</code></pre>
<p class="bold">Меньше кода:</p>
<pre><code class="php">for($i = 0; $i &lt; 100; $source[] = $target[$i+=2]);</code></pre>
</li>
<li>
<p>В&nbsp;некоторых случаях <abbr title="Hypertext Preprocessor">PHP</abbr>&nbsp;требует от&nbsp;вас&nbsp;создания переменной. Например, при&nbsp;получении массива элементов, когда массив возвращается функцией:</p>
<pre><code class="php">$ext = pathinfo('file.png')['extension'];</code></pre>
<p>Результат: <samp><b>Parse&nbsp;error:</b> syntax&nbsp;error, unexpected&nbsp;&#8217;[' in&nbsp;&hellip; on&nbsp;line&nbsp;&hellip;</samp></p>
<p>Чтобы справиться с&nbsp;этими ситуациями Вы&nbsp;можете создать несколько небольших функций для&nbsp;быстрого вызова часто используемых операций:</p>
<pre><code class="php">// Возвращает ссылку на создаваемый объект
function &amp;r($v) {
	return $v;
}

// Возвращает сдвиг массива
function &amp;a(&amp;$a, $i) {
	return $a[$i];
}
</code></pre>
</li>
<li>
<h3>Исследуйте язык, который используете</h3>
<p><abbr title="Hypertext Preprocessor">PHP</abbr>&nbsp;&mdash;&nbsp;очень мощный язык и&nbsp;содержит множество функций и&nbsp;интересных аспектов, которые могут сделать Ваш&nbsp;код рациональнее и&nbsp;короче.</p>
</li>
<li>
<h3>Пишите комментарии</h3>
<p>В&nbsp;тех случаях, когда лучше написать больше кода и&nbsp;потом легко его читать, не&nbsp;ленитесь. Потратьте на&nbsp;пару секунд больше и&nbsp;напишите комментарий и&nbsp;более читаемую структуру. Это&nbsp;единственный прием из&nbsp;списка, который действительно может помочь <b>сэкономить часы, а&nbsp;не&nbsp;минуты.</b></p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/php-coding-tips-to-write-less-code/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Генерация Sitemap.XML с помощью DOMDocument</title>
		<link>http://www.codeisart.ru/sitemap-xml-generation-using-domdocument-php/</link>
		<comments>http://www.codeisart.ru/sitemap-xml-generation-using-domdocument-php/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 21:49:27 +0000</pubDate>
		<dc:creator>Skaizer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[sitemap]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=347</guid>
		<description><![CDATA[Итак, как я и обещал, выкладываю статью по созданию карты сайта Sitemap.XML для поисковых систем с использованием DOM в PHP, а именно DOMDocument.
Класс DOMDocument в PHP позволяет обращаться к XML файлам и данным в XML формате, а так же создавать их. Он имеет ряд методов, которые будут нам полезны при создании Sitemap.XML.
Данный метод полностью основан [...]]]></description>
			<content:encoded><![CDATA[<p>Итак, как я и обещал, выкладываю статью по <strong class="normal">созданию карты сайта Sitemap.XML</strong> для поисковых систем с использованием <strong class="normal">DOM в PHP, а именно DOMDocument</strong>.</p>
<p><strong class="normal">Класс DOMDocument в PHP</strong> позволяет обращаться к XML файлам и данным в XML формате, а так же создавать их. Он имеет ряд методов, которые будут нам полезны при <strong class="normal">создании Sitemap.XML</strong>.</p>
<p>Данный метод <strong class="normal">полностью основан на ООП</strong>, что позволяет легко улучшить или изменить для себя исходный код.</p>
<p>Данная статья посвящена именно <strong class="normal">генерации Sitemap.XML с помощью DOMDocument</strong>. Описание, что это такое вы можете найти на <a href="http://www.sitemaps.org/ru/" rel="nofollow">официальном сайте</a>.</p>
<p><span id="more-347"></span></p>
<p>Наша группа занималась разработкой портала &laquo;VLG Navigator&raquo;, представляющего собой <a href="http://www.vlg-nav.ru" title="Каталог организаций Волгоград">Каталог организаций Волгограда</a> с позиционированием на карте города.</p>
<p>Передо мной стояла задача &#8211; организовать возможность <strong class="normal">создавать Sitemap.XML</strong> из административного интерфейса. Все объекты в каталоге размещались администратором и, допустим, после добавления порядка 30 объектов в каталог необходимо было как можно быстрее оповестить о них поисковые системы.</p>
<p>В моем случае, каждый узел с URL в карте сайта был следующего типа:</p>
<pre><code class="xml">&lt;url&gt;
  &lt;loc&gt;http://www.vlg-nav.ru/&lt;/loc&gt;
  &lt;lastmod&gt;2008-07-24&lt;/lastmod&gt;
  &lt;changefreq&gt;daily&lt;/changefreq&gt;
  &lt;priority&gt;1.0&lt;/priority&gt;
&lt;/url&gt;</code></pre>
<p>Каждый из узлов URL я решил хранить в соответствующем объекте. Для этого был написан класс SitemapUrl:</p>
<pre><code class="php">class SitemapUrl{

  private $loc;
  private $lastmod;
  private $changefreq;
  private $priority;

  final function __construct($loc,$lastmod,$changefreq,$priority){

    $this->loc = $loc;
    unset ($loc);

    $this->lastmod = $lastmod;
    unset ($lastmod);

    $this->changefreq = $changefreq;
    unset ($changefreq);

    $this->priority = $priority;
    unset ($priority);

  }

  final function getLoc(){
    return $this->loc;
  }

  final function getLastmod(){
    return $this->lastmod;
  }

  final function getChangefreq(){
    return $this->changefreq;
  }

  final function getPriority(){
    return $this->priority;
  }
}</code></pre>
<p>Таким образом, в переменных $this->loc, $this->lastmod, $this->changefreq, $this->priority хранятся соответствующие значения элементов конкретного узла карты сайта.</p>
<p>Допустим в карту сайта Sitemap.XML нам необходимо сохранить URL http://www.webpp.ru, с датой 2008-07-08, приоритетностью 1.0 и ежедневной частотой обновления. Создадим объект класса SitemapUrl:</p>
<pre><code class="php">&lt;?php
$webpp = new SitemapUrl ('http://www.webpp.ru','2008-07-08','daily','1.0');
// Так мы создали объект $webpp класса SitemapUrl с необходимыми нам аргументами.
// В $webpp-&gt;loc хранится значения для  &lt;loc&gt;.
// В $webpp-&gt;lastmod хранится значения для  &lt;lastmod&gt;.
// В $webpp-&gt;changefreq хранится значения для  &lt;changefreq&gt;.
// В $webpp-&gt;priority хранится значения для  &lt;priority&gt;.
?&gt;</code></pre>
<p>Почемы я выбрал храненение значений в объектах, а не ,скажем, в массиве? Поясню на практике.</p>
<p>Допустим источником данных для построения карты сайта является некая база данных, в которой значение даты, необходимое нам в построении карты сайта хранится в собственном формате (формате базы данных). Нам нужно организовать преобразование, из формата базы данных в необходимый нам.</p>
<p>Хорошо, если генерация объектов происходит в одном месте, в этом случае мы можем на уровне выборки данных из БД преобразовать их в нужный нам формат каким-либо алгоритмом. А если точек генерации объектов десятки или сотни? Тогда нам нужно всех их пройти и внести в код заполнения наш алгоритм?</p>
<p>Поступим проще! Воспользуемся конструктором нашего класса function __construct.</p>
<p class="footnote">Конструктор класса вызывается при объявлении объекта этого класса. В него помещают код, который нужно выполнить сразу же, как только объект был создан. В версиях PHP ниже 5й, чтобы объявить конструктор класса, функцию класса должна иметь одинаковое с классом название. В Версиях PHP 5 и выше конструктор объявляется функцией __construct(). Так же существует и деструктор класса &mdash; __destruct(), который выполняется перед уничтожением объекта класса.</p>
<p>Поместим в конструктор нашего класса алгоритм преобразования над датой:</p>
<pre><code class="php">  final function __construct($loc,$lastmod,$changefreq,$priority){

    $this->loc = $loc;
    unset ($loc);

    // Допустим функция algoritm($lastmod) производит преобразование
    // даты из формата БД в нужный нам формат.
    $this->lastmod = algoritm($lastmod);
    unset ($lastmod);
    // Теперь значение даты будет храниться в таком виде, в каком нам нужно.

    $this->changefreq = $changefreq;
    unset ($changefreq);

    $this->priority = $priority;
    unset ($priority);

  }</code></pre>
<p>Добавив один раз в конструкторе класса SitemapUrl преобразование даты, мы автоматически организовали преобразование во всех точках создания объектов этого класса.</p>
<p>Теперь собственно нужно получить списки URL и параметры для них, и организовать для них хранение в объектах класса SitemapUrl.</p>
<p>Напишем еще один класс SiteMapUrlGenerator ,содержащий в себе логику, по которой будут извлекаться списки URL, и все параметры для них, и сохраняться в массив объектов класса SitemapUrl.</p>
<p>Если Вы захотите переписать мой скрипт под свои нужды, то редактировать Вам нужно будет только этот класс. В моем случае он содержит набор статических страниц, которые так же должны присутствовать в карте сайта, но по тем или иным причинам отсутствуют в базе данных. Т.е. если мнеизвестны страницы, которых нет в БД, но они мне также нужны, я просто укажу их руками.</p>
<p>Так как в нашем проекте нужно было создать карты сайта только для каталога организаций и для объявлений, то я заточил этот класс именно под эти нужды. Повторюсь, для своих проектов Вам нужно будет переписать данный класс.</p>
<pre><code class="php">class SiteMapUrlGenerator {

  //Приоритетность URL каждого объявления
  private $ad_priority = '0.8';

  //Периодичность посещения поисковой системой URL объявления
  private $ad_changefreq = 'weekly';

  //Приоритетность URL каждого объекта каталога
  private $cat_priority = '0.9';

  //Периодичность посещения поисковой системой URL объектов каталога
  private $cat_changefreq = 'weekly';

 /*
  Я храню эти значения в открытом виде, так сказать &quot;по умолчанию&quot;, так как в нашем проекте не предусмотрена логика вычислений данных значений.
  В вашем случая ничего не мешает вместо статических значений подставить результат выполнения какого-либо собственного алгоритма.
*/

  var $urlList = array(); //Массив объектов, в котором будут
  //храниться все экземпляры класса SitemapURL

  var $db_conn; // Сюда будет создаваться объект написанного нами класса
  // для работы с БД. В вашем случае он может быть не обязательным.

  final function __construct() {

    $this-&gt;db_conn = $GLOBALS['db_conn']; //Объявляем класс для работы с БД

    // Ниже вставляем в массив $this-&gt;urlList все нужные нам на карте сайта
    // статические URL.

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].'/',
                                      '2008-07-24',
                                      'daily',
                                      '1.0');

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].'/ad/',
                                      '2008-07-20',
                                      'daily',
                                      '0.7');

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].'/cat/',
                                      '2008-07-20',
                                      'daily',
                                      '0.7');

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].
                                      '/contact/',
                                      '2008-07-20',
                                      'weekly',
                                      '0.5');

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].
                                      '/advertising/',
                                      '2008-07-20',
                                      'weekly',
                                      '0.5');

    $this-&gt;urlList[] = new SitemapUrl ('http://'.$_SERVER['HTTP_HOST'].'/map/',
                                      '2008-07-20',
                                      'never',
                                      '0.6');
  }

  final function getUrls() {

    $this-&gt;getCatUrlList();
    $this-&gt;getAdUrlList();

    return $this-&gt;urlList;

  }

  final function getAdUrlList() {
    // Данння функция получает из БД все ссылки объектов каталога объявлений
    // не буду вдаваться в ее описание, так как оно не имеет значения.
    // Главное получить нужные нам URL, а каким способом неважно.

    //Объявляем шаблон по которому будет строиться строиться URL объявлений.
    $shablon = 'http://'.$_SERVER['HTTP_HOST'].'/ad/';

    $ads = $this-&gt;db_conn-&gt;SelAll('ad_records','`id`,`post_date`');

    if($ads) {
      foreach($ads as $ad) {
        // Выполняем заполнение массива объектов класса SitemapUrl
        // его экземплярами, сгенерированными для каталога объявлений.

        $this-&gt;urlList[] = new SitemapUrl ($shablon.$ad['id'].'/',
        $ad['post_date'],
        $this-&gt;ad_changefreq,
        $this-&gt;ad_priority);
      }
    }

  }

  final function getCatUrlList() {
   // Данная функция получает из БД все ссылки объектов каталога организаций
   // не буду вдаваться в ее описание, так как оно не имеет значения.
   // Главное получить нужные нам URL, а каким способом неважно.

  //Объявляем шаблон по которому будет строиться URL каталога организаций.
    $shablon = 'http://'.$_SERVER['HTTP_HOST'].'/cat/'; 

    $query = &quot;SELECT `icons_info`.`icon_id`,`icons_info`.`edit_date`&quot;;
    $query.= &quot; FROM `icons_info`&quot;;

    $cats = $this-&gt;db_conn-&gt;SelQuery($query);

    if($cats) {
      foreach($cats as $record) {
        // Выполняем заполнение массива объектов класса SitemapUrl
        // его экземплярами, сгенерированными для каталога организаций.

        $this-&gt;urlList[] = new SitemapUrl ($shablon.$record['icon_id'].'/',
        $record['edit_date'],
        $this-&gt;cat_changefreq,
        $this-&gt;cat_priority);
      }
    }

  }

}</code></pre>
<p>Абсолютно все URL хранятся в объектах класса SitemapUrl и хранятся в одном массиве $this-&gt;urlList .</p>
<p>Думаю понять как работает данный класс и написать свой подобный труда не составит. Главной генерировать нужные Вам URL и записывать их объекты класса SitemapURL. И вернуть в виде массива объектов.</p>
<p>Ну и осталось написать самый главный класс, который будет все это собирать в кучу и выдавать XML файл карты сайта.</p>
<pre><code class="php">class Sitemap {

  //Нужно пинговать поисковики или нет.
  var $needPing = False;

  // Флаг, существует ли файл sitemap.xml или нет
  private $XMLsitemapExist = False;

  // Относительный путь до XML файла карты сайта.
  private $XMLsitemapSaveFile = '../sitemap.xml';

  // Флаг, существует ли файл sitemap.txt или нет
  private $TXTsitemapExist = False;

  // Относительный путь до TXT файла карты сайта.
  private $TXTsitemapSaveFile = '../sitemap.txt';

  // Сюда будет происходить сохранение списка URL для
  // текстовой версии карты сайта
  private $TXTsitemapDump;

  // Сюда будем записывать массив объектов с URL для XML версии
  private $urlList;

  // Адрес, по которому пинговать Google, что карта сайта обновилась
  private $googlePingUrl;

  // Адрес, по которому пинговать Yahoo, что карта сайта обновилась
  private $yahooPingUrl;

  // Хранится полный URL до файла sitemap.xml
  private $sitemapFile;

  // Сюда будем создавать экземпляр класса DOMDocument
  private $dom;

  final function generate() {
    /*
    Главный метод класса Sitemap. Собвственно он и
    выполняет генерацию карты сайта с помощью DOMDocument.
    */

    // Так как объект класса DOMDocument у нас уже объявлен, а с ним и корневой
    // элемент &lt;xml&gt;, то создаем дочерний элемент &lt;urlset&gt;
    $root = $this-&gt;dom-&gt;appendChild($this-&gt;dom-&gt;createElement('urlset'));

    // Добавляем необходимые атрибуты.
    $root-&gt;setAttribute('xmlns','http://www.sitemaps.org/schemas/sitemap/0.9');
    $root-&gt;setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
    $root-&gt;setAttribute('xsi:schemaLocation',
              'http://www.sitemaps.org/schemas/sitemap/0.9'.' '.
              'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');

    // Запускаем генерацию массива объектов типа SitemapUrl
    $SiteMapUrlGenerator = new SiteMapUrlGenerator;
    $this-&gt;urlList = $SiteMapUrlGenerator-&gt;getUrls();

    // Очищаем память, так как массив был успешно создан
    // и более объект не требуется.
    unset($SiteMapUrlGenerator);

    // Перебираем значения полученного массива и формируем XML
    for($i=0;$i&lt;sizeof($this-&gt;urlList);$i++) {

     // Создаем узел &lt;url&gt;
      $url = $root-&gt;appendChild($this-&gt;dom-&gt;createElement('url'));

      // Создаем дочерний узел &lt;loc&gt; и заполняем его информацией.
      $url-&gt;appendChild($this-&gt;dom-&gt;createElement('loc',
                                    $this-&gt;urlList[$i]-&gt;getLoc()));

      // Создаем дочерний узел &lt;lastmod&gt; и заполняем его информацией.
      $url-&gt;appendChild($this-&gt;dom-&gt;createElement('lastmod',
                                    $this-&gt;urlList[$i]-&gt;getLastmod()));

      // Создаем дочерний узел &lt;changefreq&gt; и заполняем его информацией.
      $url-&gt;appendChild($this-&gt;dom-&gt;createElement('changefreq',
                                    $this-&gt;urlList[$i]-&gt;getChangefreq()));

      // Создаем дочерний узел &lt;priority&gt; и заполняем его информацией.
      $url-&gt;appendChild($this-&gt;dom-&gt;createElement('priority',
                                    $this-&gt;urlList[$i]-&gt;getPriority()));

      // Так же создаем список URL для текстовой версии карты сайта.
      $this-&gt;TXTsitemapDump .= $this-&gt;urlList[$i]-&gt;getLoc().&quot;\n&quot;;

    }

    // Если файл sitemap.xml существует, то удаляем его.
    if($this-&gt;XMLsitemapExist) {
      unlink($this-&gt;XMLsitemapSaveFile);
    }

    // Сохраняем сгенерированные XML данные в файл sitemap.xml
    $this-&gt;dom-&gt;save($this-&gt;XMLsitemapSaveFile);

    // Сохраняем сгенерированные TXT данные в файл sitemap.txt
    // Если файл sitemap.txt существует, он будет удален и создан новый.
    fwrite(fopen($this-&gt;TXTsitemapSaveFile,&quot;w-&quot;, $this-&gt;TXTsitemapDump);

    // Если требуется пинговка поисковиков, то выполняем.
    if($this-&gt;needPing) {
      $this-&gt;pingGoogle();
      $this-&gt;pingYahoo();
    }
  }

  final function pingGoogle() {

    //Метод, выполняющий пинг Google, о том, что карта сайта обновилась
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this-&gt;googlePingUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
  }

  final function pingYahoo() {

    //Метод, выполняющий пинг Yahoo, о том, что карта сайта обновилась
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this-&gt;yahooPingUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
 }

  final function __construct() {
    // Производим инициализацию объектов. Объявляем переменные окружения класса.

    // Объявляем URL до файла sitemap.xml
    $this-&gt;XMLsitemapFile = 'http://'.$_SERVER['HTTP_HOST'].'/sitemap.xml';

    // Объявляем URL по которому пинговать Google
    $this-&gt;googlePingUrl = 'http://www.google.com/webmasters/sitemaps/'.
                           'ping?sitemap=';
    $this-&gt;googlePingUrl .= urlencode($this-&gt;XMLsitemapFile);

    // Объявляем URL по которому пинговать Yahoo
    $this-&gt;yahooPingUrl = 'http://search.yahooapis.com/SiteExplorerService/V1/'.
                          'ping?sitemap=';
    $this-&gt;yahooPingUrl .= .urlencode($this-&gt;XMLsitemapFile);

    // Создаем объект класса DOMDocument
    $this-&gt;dom = new DOMDocument('1.0','UTF-8');
    $this-&gt;dom-&gt;formatOutput = true;

    // Так, на всякий случай
    $this-&gt;TXTsitemapDump = '';

    // Проверяем, существует ли уже файл sitemap.xml
    $this-&gt;XMLsitemapExist = file_exists($this-&gt;XMLsitemapFile);

    // Проверяем, существует ли уже файл sitemap.txt
    $this-&gt;TXTsitemapExist = file_exists($this-&gt;TXTsitemapSaveFile);
  }

}</code></pre>
<p>Вот собственно и все, старался ясно описывать все действия в комментариях, но повторюсь еще раз.</p>
<p>Итак, мы объявили наш класс Sitemap. Из чего он состоит? Первоначально мы создаем внутренние переменные класса, которые будут использоваться в нем, такие как флаги, существуют ли уже файлы карты сайта или нет. Адреса пинга поисковиков Google и Yahoo. Полный путь до файлов карты сайта. URL адрес файла sitemap.xml. И прочие необходимые нам переменные.</p>
<p>Далее они инициализируются в конструкторе класса. Так же в конструкторе класса происходит создание <strong class="normal">объекта класса DOMDocument</strong>, через который мы будем производить все манипуляции с XML данными.</p>
<p>Методы pingGoogle() и pingYahoo() поизводят пинг поисковых систем, о том, что карта сайта обновилась. Эти методы работают через библиотеку curl которая должна быть подключена в PHP.</p>
<p>Ну и основной метод generate(). Он и управляет самой <strong class="normal">генерацией карты сайта Sitemap.XML</strong> и TXT версии. Порядок, в котором работает данный метод описан в комментариях к коду.</p>
<p>Теперь осталось только создать объект класса Sitemap и вызвать генерацию XML карты сайта. Вместе с ней создастся и TXT версия.</p>
<pre><code class="php">$sitemap = new Sitemap;
$sitemap->generate();</code></pre>
<p>Все, готово! Таким образом мы получили нужную нам карту сайта со всеми выбранными URL.</p>
<p>Прошу прощения за возможно корявые подходы, вроде наращивания строк, где казалось бы можно было без этого обойтись. Сделано это для того, чтобы код корректно отображался в браузерах, т.к. слишком длинные строки выходят за рамки поля для контента.</p>
<p>Надеюсь, что Вы найдете эту статью полезной, и будете применять описанный мной метод в своих проектах. Повторюсь, для затачивания его под себя, нужно переписать только класс выборки данных для URL адресов, а именно SiteMapUrlGenerator. Все остальное можно оставить без изменений.</p>
<p><b>Скомпонованный готовый скрипт можно</b> <a href='http://www.codeisart.ru/wp-content/uploads/2008/08/class-sitemap-xml-php.zip' class="attach zip">скачать здесь</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/sitemap-xml-generation-using-domdocument-php/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Динамическая подмена запросов к Sitemap.XML</title>
		<link>http://www.codeisart.ru/%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bf%d0%be%d0%b4%d0%bc%d0%b5%d0%bd%d0%b0-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%ba-sitemap-xm/</link>
		<comments>http://www.codeisart.ru/%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bf%d0%be%d0%b4%d0%bc%d0%b5%d0%bd%d0%b0-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%ba-sitemap-xm/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 13:58:03 +0000</pubDate>
		<dc:creator>Skaizer</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[sitemap]]></category>

		<guid isPermaLink="false">http://www.codeisart.ru/?p=338</guid>
		<description><![CDATA[Иногда возникает необходимость использовать вместо статического файла &#171;sitemap.xml&#187; (XML-формат файла Sitemap) скрипт, генерирующий его динамически.
Когда это может понадобиться? Допустим у Вас имеется каталог объявлений, в котором каждый час появляются новые, соответственно, каждое из объявлений имеет уникальный URL-адрес, который побыстрее нужно сообщить поисковой системе посредством карты сайта. Или же для Вас важна динамическая генерация как &#171;sitemap.xml&#187; [...]]]></description>
			<content:encoded><![CDATA[<p>Иногда возникает необходимость использовать вместо статического файла &laquo;sitemap.xml&raquo; (<a href="http://www.sitemaps.org/ru/" rel="nofollow"><abbr title="eXtensible Markup Language">XML-</abbr>формат файла Sitemap</a>) скрипт, генерирующий его динамически.</p>
<p>Когда это может понадобиться? Допустим у Вас имеется каталог объявлений, в котором каждый час появляются новые, соответственно, каждое из объявлений имеет уникальный <abbr title="Uniform Resource Locator">URL</abbr>-адрес, который побыстрее нужно сообщить поисковой системе посредством карты сайта. Или же для Вас важна динамическая генерация как &laquo;sitemap.xml&raquo; так и карты текстовой (TXT) карты сайта, содержащей просто список всех <abbr title="Uniform Resource Locator">URL</abbr>.</p>
<p><span id="more-338"></span></p>
<p>Решить данную задачу можно с помощью модуля &laquo;mod_rewrite&raquo; сервера &laquo;Apache&raquo;. Требуется создать правила, которые будут при каждом обращении к файлам &laquo;sitemap.xml&raquo; или &laquo;sitemap.txt&raquo; запускать <abbr title="Hypertext Preprocessor">PHP</abbr>-скрипт, передавая параметры, какую из карт запросили. <abbr title="Hypertext Preprocessor">PHP</abbr>-скрипт в свою очередь соберет необходимые данные и создаст требуемую карту сайта.</p>
<p>Добавьте в файл &laquo;.htaccess&raquo; следующие строки:</p>
<pre><code class="no-hightlight">RewriteRule ^sitemap.xml$ /sitemap.php?type=xml [L]
RewriteRule ^sitemap.txt$ /sitemap.php?type=txt [L]</code></pre>
<p>Эти два правила осуществляют подмену запросов к файлу карты сайта формата &laquo;xml&raquo; (sitemap.xml) и к файлу карты сайта формата &laquo;txt&raquo; (sitemap.txt).</p>
<p>Подмена происходит следующим образом: как только пользователь или поисковая система запросили файл &laquo;sitemap.xml&raquo;, срабатывает правило, которое отсылает запрос скрипту &laquo;sitemap.php&raquo; с параметром &laquo;<code>type=xml</code>&raquo;. Скрипт генерирует карту сайта, с помощью какой-либо своей собственной логики и выдает ее с помощью функции &laquo;<code>echo</code>&raquo;.</p>
<p>Т.е. обратившись например по адресу <cite>http://localhost/sitemap.xml</cite>, на самом деле Вы получаете результат работы скрипта &laquo;sitemap.php&raquo;.</p>
<p>Аналогично происходит и для текстовой версии карты сайта.</p>
<p>В скрипте &laquo;sitemap.php&raquo; необходимо проверить значение элемента &laquo;<code>type</code>&raquo; суперглобального массива &laquo;<code>$_GET</code>&raquo;:</p>
<pre><code class="php">switch ($_GET['type']){
  case 'xml':
    //Выполняем генерацию XML версии карты сайта.
    //Лучше написать и вызвать в этом месте соответствующую функцию.
  break;

  case 'txt':
    //Выполняем генерацию TXT версии карты сайта.
    //Лучше написать и вызвать в этом месте соответствующую функцию.
  break;

  default:
    echo 'Генератор поисковых карт сайта.';
    echo 'Заходите на www.codeisart.ru';
}</code></pre>
<h3>Преимущества</h3>
<ul>
<li>карта сайта содержит самые последние <abbr title="Uniform Resource Locator">URL</abbr> на момент обращения;</li>
<li>легко можно добавить статические элементы в набор <abbr title="Uniform Resource Locator">URL</abbr> карты сайта.</li>
</ul>
<h3>Недостатки</h3>
<ul>
<li>при большом количестве <abbr title="Uniform Resource Locator">URL</abbr> на сайте, генерация карты может оказаться достаточно длительным и ресурсоемким процессом.</li>
</ul>
<p>Подобным образом можно перехватывать обращения к любым файлам на сервере. Особенно это может быть актуально для файла &laquo;<a href="http://www.codeisart.ru/meta-robots-%d0%b8%d0%bb%d0%b8-robots-txt/" title="META ROBOTS или robots.txt">robots.txt</a>&raquo;.</p>
<p>Лично я сам не пользуюсь данным методом, т.к. он создает большую нагрузку на сервер, но может быть Вам материал этой статьи когда-нибудь пригодится.</p>
<p>В ближайшем будущем опубликую статью, в которой постараюсь описать объектно-ориентированный метод генерации карт (как <abbr title="eXtensible Markup Language">XML</abbr>-версию, так и TXT) сайта с использованием &laquo;<code>DOMDocument</code>&raquo; в <abbr title="Hypertext Preprocessor">PHP</abbr>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codeisart.ru/%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bf%d0%be%d0%b4%d0%bc%d0%b5%d0%bd%d0%b0-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%ba-sitemap-xm/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
