<?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>Корчагин Станислав &#187; разработка</title>
	<atom:link href="http://korchasa.ru/index.php/tag/%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0/feed/" rel="self" type="application/rss+xml" />
	<link>http://korchasa.ru</link>
	<description>Разработка, тестирование, запуск</description>
	<lastBuildDate>Mon, 24 May 2010 23:28:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Limb3 2010.1 RC</title>
		<link>http://korchasa.ru/index.php/2010/05/limb3-2010-1-rc/</link>
		<comments>http://korchasa.ru/index.php/2010/05/limb3-2010-1-rc/#comments</comments>
		<pubDate>Mon, 24 May 2010 18:41:12 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Анонсы]]></category>
		<category><![CDATA[Новости]]></category>
		<category><![CDATA[limb]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=303</guid>
		<description><![CDATA[Ну вот и RC!
С 2007 года мы жили на trunk-версии. Доколе! Хватит!
hg clone https://limb3.googlecode.com/hg/#RC-prepare limb2010.1
Список изменений настолько велик, что проще описать, что мы умеем:
Ядро &#8211; пакет CORE
Подключение классов и поддержка отложенной загрузки кода, работа с пакетами (lmb_package_*), работа с переменными окружения (lmb_env_*), проверка входных параметров (lmb_assert_*), коллекции и единичные контейнеры.
IoC  -пакет TOOLKIT
Пакет TOOLKIT &#8211; есть реализация паттерна Dynamic Service [...]]]></description>
			<content:encoded><![CDATA[<p>Ну вот и RC!</p>
<p>С 2007 года мы жили на trunk-версии. Доколе! Хватит!</p>
<p><code>hg clone https://limb3.googlecode.com/hg/#RC-prepare limb2010.1</code></p>
<p>Список изменений настолько велик, что проще описать, что мы умеем:</p>
<h3><span id="more-303"></span>Ядро &#8211; пакет CORE</h3>
<p>Подключение классов и поддержка отложенной загрузки кода, работа с пакетами (lmb_package_*), работа с переменными окружения (lmb_env_*), проверка входных параметров (lmb_assert_*), коллекции и единичные контейнеры.</p>
<h3>IoC  -пакет TOOLKIT</h3>
<p><a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:toolkit:usage">Пакет TOOLKIT</a> &#8211; есть реализация паттерна <strong>Dynamic Service Locator</strong>. Суть этого паттерна состоит в том, что есть некий легко доступный объект, который является общим местом для доступа ко всем популярным объектам (сервисам) и в том, что возможности этого объекта можно легко расширять. Основное отличие от большинства подобных решений в том, что инстанцирование описывается императивно.</p>
<h3>DBAL (Data Base Abstraction Layer) &#8211; пакет DBAL</h3>
<p>В данный момент поддерживаются: MySQL 4.1+, SQLite, Oracle (OCI8), PostgreSQL 8.2+, Linter</p>
<p>Архитектура <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:dbal:intro">пакета DBAL</a> вполне стандартная:</p>
<ul>
<li>Driver	Драйвер (Driver) &#8211; базовые классы для работы с базами данных, которые абстрагируют доступ к базе данных. При помощи них осуществляются операции выборки и изменения состояния базы данных (select, update, insert, delete и т.д.).</li>
<li>Query  - группа классов, позволяющих тем или иным образом инкапсулировать SQL запросы.</li>
<li>Criteria  - группа классов, позволяющих строить условия для SQL запросов.</li>
<li>Dump  - группа классов, используемых для загрузки sql-дампов.</li>
</ul>
<h3>ORM (Object-Relation Mapping) &#8211; пакет ACTIVE_RECORD</h3>
<p>Первоначальная идея <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:active_record:intro">пакета ACTIVE_RECORD</a> взята из фреймворка Ruby-On-Rails. RoR в данном случае выступали в качестве функционального ориентира, но мы не копировали полностью его API и функционал, а реализовывали только то, что было необходимо в текущий момент.</p>
<p>Основные характеристики:</p>
<ul>
<li> автоматическое определение наименований и типов полей таблицы</li>
<li>поддержка отношений один-к-одному, один-ко-многим и много-ко-многим</li>
<li>поддержка ValueObjects</li>
<li>поддержка наследования в рамках одной таблицы (Single Table Inheritance)</li>
<li>поддержка “отложенной загрузки” (LazyLoading) для коллекций</li>
<li>тесная интеграция с шаблонными системами WACT и MACRO</li>
<li>&#8220;жадные&#8221; операции  - attach и join</li>
<li>пользовательские коллекции</li>
</ul>
<h3>Шаблонизация &#8211; пакеты VIEW, WACT и MACRO</h3>
<p>limb3 следует парадигме MVC, как средству логичного разбиения кода, на относительно независимые куски. Пакет VIEW представляет одноименный слой MVC, и представляет из себя абстракцию от конкретного механизма шаблонизации. В данный момент основным шаблонизатором в limb3 является <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro:intro">MACRO</a>, пришедший на смену <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:wact">WACT&#8217;у</a>. Помимо них VIEW поддерживает Blitz, JSON и нативный PHP.</p>
<p>MACRO &#8211; это своего рода syntactic sugar для нативного РНР. Мы пошли не по пути хэлперов, а остались верны тегам и фильтрам. Кратко о нем:</p>
<ul>
<li>промежуточная компиляция в PHP-код</li>
<li>две области видимости переменных: глобальная и локальная (на уровне шаблона)</li>
<li>механизм фильтров</li>
<li>шаблоны комбинируются через <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro:tags:core_tags:include_tag">include</a> (включение дочернего шаблона), <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro:tags:core_tags:wrap_tag">wrap</a> (включение в родительский шаблон) и <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro:tags:core_tags:template_tag">template+apply</a> (применение шаблона)</li>
<li>поддерживается концепция слотов</li>
<li>готовые теги для работы со списками, деревьями, пейджингом, формами и их полями, ссылками и интернационализацией</li>
<li>готовые фильтры для различного форматирования строк, чисел, дат и специальных форматов</li>
<li>расширяем через собственные теги и фильтры</li>
</ul>
<h3>Веб-приложение &#8211; пакет WEB_APP</h3>
<p><a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:web_app">Пакет WEB_APP</a> позволяет стоить веб-приложения, применяя парадигму MVC (Model-View-Controller). Сам WEB_APP пакет предоставляет классы для реализации только Controller составляющей. Выбор средства для реализации модели и отображения все равно лежит на конечном разработчике приложения, хотя пакет реализован таким образом чтобы максимально упростить работу с приложениями, где в качестве модели будут выбраны “родные” Limb3 пакеты DBAL и ACTIVE_RECORD, а в качестве отображения &#8211; пакет VIEW.</p>
<p>Limb3-приложения строятся обычно на основе цепочки фильтров, которая запускается из файла index.php. Цепочка фильтров стоится из набора типовых фильтров пакета WEB_APP или из тех, которые сочтет нужными реализовать конечный разработчик приложения.</p>
<h3>Тестирование &#8211; пакет TESTS_RUNNER</h3>
<p>TESTS_RUNNER &#8211; пакет для организации и запуска <a style="padding-top: 1px; padding-right: 0px; padding-bottom: 1px; padding-left: 16px; color: purple; text-decoration: underline; background-image: url(http://wiki.limb-project.com/lib/tpl/limb/images/link_icon.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: 0px 1px; background-repeat: no-repeat no-repeat; margin: 0px;" title="http://www.simpletest.org/" rel="nofollow" href="http://www.simpletest.org/">SimpleTest</a> тестов для приложений, которые содержат большие тестовые наборы. В поставку с пакетом входят классы, которые позволяют выполнять тесты в cli или web-режиме.</p>
<p>Данный пакет не содержит никаких зависимостей от других пакетов, входящих в Limb3, поэтому может использоваться полностью отдельно.</p>
<h3>Прочие пакеты</h3>
<p>Набор практически стандартен: ACL, деревья, кэширование, календарь, CLI-скрипты, админка, работа с конфигами, конвертация дат, интернационализация, обработка изображений, отправка почти и так далее. Полный список пакетов можно найти на <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages">соответствующей странице</a> в документации.</p>
<h3>Инкубатор</h3>
<p>Некоторое время назад мы ввели концепцию инкубатора. В него помещаются все &#8220;молодые&#8221; пакеты, которые еще не прошли испытание боем, недокументированные пакеты или пакеты не покрытые тестами. В данный момент в нем находятся:</p>
<ul>
<li>CONSTRUCTOR &#8211; генератор моделей, контроллеров, шаблонов на основе схемы БД</li>
<li>PROFILE &#8211; средство для профилирования кода, запросов к БД и кешам</li>
<li>CRON &#8211; базовая функциональность для крон-задач, с ведением лога в БД и административной страничкой просмотра этого дела</li>
</ul>
<h2>Текущие проблемы</h2>
<p>Самой большой, на мой взгляд, проблемой является не слишком удобная документация. В данный момент она разбита по пакетам. Опыт показал, что иногда новички испытывают проблему с поискам, ибо не знают где и как оно реализовано.</p>
<p>Помимо этого на версии RC проходят не все тесты, но это поправим до релиза.</p>
<h2>Итого</h2>
<p>Если вы матерый РНР-программист, и всякие ZF и Symfony вам жмут в плечах и не дают расправить крылья, то приходите к нам. Мы очень гибкие, честно-честно.</p>
<ul>
<li>Код: hg clone https://limb3.googlecode.com/hg/#RC-prepare limb2010.1</li>
<li><a href="http://wiki.limb-project.com/doku.php?id=limb3:ru">Документация</a></li>
<li><a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:tutorials:basic">Чтобы въехать</a> (быстрый старт)</li>
<li><a href="http://forum.limb-project.com/">Форум поддержки</a></li>
<li><a href="http://tracker.korchasa.ru">Временный треккер</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2010/05/limb3-2010-1-rc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Презентация от старого доклада о кэшировании</title>
		<link>http://korchasa.ru/index.php/2009/05/%d0%bf%d1%80%d0%b5%d0%b7%d0%b5%d0%bd%d1%82%d0%b0%d1%86%d0%b8%d1%8f-%d0%be%d1%82-%d1%81%d1%82%d0%b0%d1%80%d0%be%d0%b3%d0%be-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4%d0%b0-%d0%be-%d0%ba%d1%8d%d1%88%d0%b8/</link>
		<comments>http://korchasa.ru/index.php/2009/05/%d0%bf%d1%80%d0%b5%d0%b7%d0%b5%d0%bd%d1%82%d0%b0%d1%86%d0%b8%d1%8f-%d0%be%d1%82-%d1%81%d1%82%d0%b0%d1%80%d0%be%d0%b3%d0%be-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4%d0%b0-%d0%be-%d0%ba%d1%8d%d1%88%d0%b8/#comments</comments>
		<pubDate>Sat, 16 May 2009 22:09:35 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Без рубрики]]></category>
		<category><![CDATA[кэширование]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=249</guid>
		<description><![CDATA[Видео со скончавшегося secon&#8217;а видимо не будет никогда, поэтому выкладываю только презентацию.
Cache in web (Secon 2008)

]]></description>
			<content:encoded><![CDATA[<p>Видео со скончавшегося <a href="http://www.secon.ru/">secon&#8217;а</a> видимо не будет никогда, поэтому выкладываю только презентацию.</p>
<div id="__ss_988908" style="width: 425px; text-align: left;"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" title="Cache in web (Secon 2008)" href="http://www.slideshare.net/korchasa/cache-in-web-secon-2008?type=presentation">Cache in web (Secon 2008)</a><object width="425" height="355" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=my-1233767974539817-1&amp;stripped_title=cache-in-web-secon-2008" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=my-1233767974539817-1&amp;stripped_title=cache-in-web-secon-2008" /><param name="allowfullscreen" value="true" /></object></div>
<p><img src="http://bs.yandex.ru/resource/spacer.gif?sign=25368431.4908262.1244038590.04e67eb813a8ee36e21abadd633caff9" width="1" height="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2009/05/%d0%bf%d1%80%d0%b5%d0%b7%d0%b5%d0%bd%d1%82%d0%b0%d1%86%d0%b8%d1%8f-%d0%be%d1%82-%d1%81%d1%82%d0%b0%d1%80%d0%be%d0%b3%d0%be-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4%d0%b0-%d0%be-%d0%ba%d1%8d%d1%88%d0%b8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как сократить количество правил в ACL (Access Control List)?</title>
		<link>http://korchasa.ru/index.php/2009/02/acl-access-control-list/</link>
		<comments>http://korchasa.ru/index.php/2009/02/acl-access-control-list/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 21:55:44 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[limb]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=208</guid>
		<description><![CDATA[Главная проблема ACL &#8211; ее размер
Из этой проблемы формируются две гадости: во-первых правила долго писать, во-вторых по ним искать сложно. Попробуем пойти нестандартным путем и решить проблему, сделав роли более селективными.

Стандартные способы борьбы
Для уменьшения количества правил, обычно применяют наследование ролей и ресурсов, а так же множественные роли на один инстанс объекта. В итоге имеем дерево, [...]]]></description>
			<content:encoded><![CDATA[<h3>Главная проблема ACL &#8211; ее размер</h3>
<p>Из этой проблемы формируются две гадости: во-первых правила долго писать, во-вторых по ним искать сложно. Попробуем пойти нестандартным путем и решить проблему, сделав роли более селективными.<br />
<span id="more-208"></span></p>
<h3>Стандартные способы борьбы</h3>
<p>Для уменьшения количества правил, обычно применяют наследование ролей и ресурсов, а так же множественные роли на один инстанс объекта. В итоге имеем дерево, нелинейный алгоритм, и количество проходов по нему отличное от нуля <img src='http://korchasa.ru/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>Обратная сторона &#8211; использование масок доступа. Проверка по маске это быстро, но маска не бесконечная. А как же &#8220;показывать только друзьям&#8221;?</p>
<p>В общем надо решать как-то иначе.</p>
<h3>Как же?</h3>
<p>Кто лучше всех знает кем для статьи является конкретный пользователь?</p>
<p>Правильно, сама статья.</p>
<p>На практике оказывается, что информация, которая необходима для определения роли конкретного объекта, в рамках конкретного субъекта, лежит либо в самом субъекте, либо &#8220;близко&#8221; к нему. Так пусть он и определяет, кто в данный момент перед ним.</p>
<p>В <a href="http://wiki.limb-project.com/">LIMB&#8217;е</a> это выглядит так:</p>
<pre lang="php">class Article implements lmbRolesResolverInterface, lmbResourceProviderInterface
{
  function getRoleFor(Member $member)
  {
    if($this->getOwnerId() === $member->getId())
      return 'owner';
    if($this->getCategory()->getModeratorId() === $member->getId())
      return 'moderator';
  }

  function getResource()
  {
    return 'article';
  }
}

class Member implements lmbRoleProviderInterface
{
  function getRole()
  {
    return 'member';
  }
}

//простой пользователь сайта
$this->acl->addRole('member');

//наш контенто-писака, жаждущий кармы
$this->acl->addRole('owner', 'member');

//модер, уныло бдящий за порядком на сайте
$this->acl->addRole('moderator', 'owner');

//а я статья. Просто статья
$this->acl->addResource('article');

//простой пользователь может статью комментировать
$this->acl->allow('member', 'article', 'comment');
//автор ее редактировать
$this->acl->allow('owner', 'article', 'edit');
// модератор акцептировать
$this->acl->allow('moderator', 'article', 'accept');

/* создадим по объектику на каждую роль */
$just_member = new Member();
$just_member->save();
$owner = new Member();
$owner->save();
$moderator = new Member();
$moderator->save();

$category = new ArticleCategory();
$category->setTitle('About LIMB');
$category->setModerator($moderator);
$category->save();

$article = new Article();
$article->setCategory($category);
$article->setOwnerId($owner->getId());
$article->save();

/* проверим нашу "магию" */
var_dump($this->acl->isAllowed($member, $article, 'comment')); //bool(true)
var_dump($this->acl->isAllowed($member, $article, 'edit')); //bool(false)
var_dump($this->acl->isAllowed($member, $article, 'approve')); //bool(false)

var_dump($this->acl->isAllowed($owner, $article, 'comment')); //bool(true)
var_dump($this->acl->isAllowed($owner, $article, 'edit')); //bool(true)
var_dump($this->acl->isAllowed($owner, $article, 'approve')); //bool(false)

var_dump($this->acl->isAllowed($moderator, $article, 'comment')); //bool(true)
var_dump($this->acl->isAllowed($moderator, $article, 'edit')); //bool(false)
var_dump($this->acl->isAllowed($moderator, $article, 'accept')); //bool(true)
</pre>
<p>Данный подход впервые пришлось использовать при создании acl, для фреймворка <a href="http://adept-project.ru/">Adept</a>, а теперь <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:acl#%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%80%D0%BE%D0%BB%D0%B8_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0_%D0%B2_%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B5_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0-%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D0%B0">подобная штука</a> есть и в LIMB&#8217;е.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2009/02/acl-access-control-list/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Лебедь, рак и щука: огранизация работы нескольких программистов на малых и средних проектах</title>
		<link>http://korchasa.ru/index.php/2008/11/%d0%bb%d0%b5%d0%b1%d0%b5%d0%b4%d1%8c-%d1%80%d0%b0%d0%ba-%d0%b8-%d1%89%d1%83%d0%ba%d0%b0-%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d0%bd/</link>
		<comments>http://korchasa.ru/index.php/2008/11/%d0%bb%d0%b5%d0%b1%d0%b5%d0%b4%d1%8c-%d1%80%d0%b0%d0%ba-%d0%b8-%d1%89%d1%83%d0%ba%d0%b0-%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d0%bd/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 09:00:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[базы данных]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=3</guid>
		<description><![CDATA[Для начала определимся с тем, что мы делаем. Обычно наш продукт состоит из:

сервера или нескольких серверов
настроек сторонних приложений (http-сервера, СУБД, прочие хранилища данных и утилиты)
нашей схемы размещения файлов (фото, видео, и прочий хлам контент)
наших кэшей
нашей структуры БД
нашего кода
бессоных ночей

Начнем с конца, пропустив бессоные ночи.

Обычно все начинают с одного и того же&#8230;
Коммунизм
Один сервер, одна база, один [...]]]></description>
			<content:encoded><![CDATA[<p>Для начала определимся с тем, что мы делаем. Обычно наш продукт состоит из:</p>
<ul>
<li>сервера или нескольких серверов</li>
<li>настроек сторонних приложений (http-сервера, СУБД, прочие хранилища данных и утилиты)</li>
<li>нашей схемы размещения файлов (фото, видео, и прочий хлам контент)</li>
<li>наших кэшей</li>
<li>нашей структуры БД</li>
<li>нашего кода</li>
<li>бессоных ночей</li>
</ul>
<p>Начнем с конца, пропустив бессоные ночи.</p>
<p><span id="more-66"></span></p>
<p><span style="font-style: italic;">Обычно все начинают с одного и того же&#8230;</span></p>
<h3>Коммунизм</h3>
<p>Один сервер, одна база, один код. Правим по очереди или по алфавиту. Правки то и дело сопровождаются криками «Не трогайте пока User.php. Мне надо выборки поправить». Версионность кода поддерживается ежедневным архивированием папочки с кодом и дампом БД.</p>
<p><span style="font-style: italic;">И надоело им материться, и явился им <a href="http://ru.wikipedia.org/wiki/Subversion">SVN</a> (<a href="http://ru.wikipedia.org/wiki/CVS">CVS</a>, <a href="http://ru.wikipedia.org/wiki/Git">Git</a>, <a href="http://en.wikipedia.org/wiki/Bazaar_%28software%29">Bazaar</a>, нужное подчеркнуть). И поняли они, что это хорошо&#8230;</span></p>
<h3>База на то и база, чтобы одна была</h3>
<p>Стало лучше, но все равно то и дело слышаться возгласы «Ёп! Кто поле is_hidden у статьи убрал? Оно же во всех выборках! Давай коммить (новые выборки) быстрей!».</p>
<p>Призадумались ребята. Подумали, поспали, еще подумали. И поняли, что схему БД надо «привязывать» к коду, который с ней работает. Погуглили, и нашли:</p>
<ul>
<li><a href="http://www.google.com/search?q=mysql+diff">кучу утилит</a>, которые умеют делать «diff» между двумя базами</li>
<li>для ROR на Ruby &#8211; <a href="http://www.railsforum.com/viewtopic.php?id=1011">миграции</a> на SQL DDL</li>
<li>для Django на Python &#8211; <a href="http://www.aswmc.com/dbmigration/">DbMigration</a></li>
<li>а для РНР — всю туже кучу утилит типа mysql diff, ну еще и <a href="http://www.doctrine-project.org/documentation/manual/1_0?chapter=migration">Doctrine Migration</a> для <a href="http://ru.wikipedia.org/wiki/ORM">ORM</a> <a href="http://www.doctrine-project.org/">Doctrine</a>.</li>
</ul>
<p>А отдельные храбрецы, разрабатывающие на <a href="http://limb-project.com/">LIMB</a>&#8216;е используют <a href="https://svn.limb-project.com/limb/misc/migration/">вот эту радость</a>. Радость представляет из себя набор консольных утилит для автоматического создания, тестирования и применения миграций, а так же для создания дампов БД. Подробности <a href="http://forum.limb-project.com/viewtopic.php?t=2315">можно прочитать</a> на нашем <a href="http://forum.limb-project.com/">форуме</a>.<br />
Все вроде бы хорошо, но вот беда — на продакшене кэши решили хранить в <a href="http://ru.wikipedia.org/wiki/Memcached">memcached</a>, а на машинах разработчиков толи памяти мало, толи им на содержимое кэша часто смотреть приходится.</p>
<h3>Делим cash, то есть cache</h3>
<p>Что у нас есть такое куда смотреть легко, и где место не жалко. Эврика! Файлы на диске. Теперь дело за малым — нужна библиотечка, которая позволит простым изменением настройки переключаться между разными хранилищами.</p>
<p>ИМХО, каждый, уважающий себя, фреймворк должен иметь такую штуку. Хотя бы для того, чтобы мерятся с другими. У <a href="http://framework.zend.com/">Zend Framework</a> есть Zend_Cache. В <a href="http://limb-project.com/">LIMB</a> таких штук целых две. Пакет сache — нормально работает и вполне стабилен (по API), и второй писал я, со всеми вытекающими. Пакет <a href="https://svn.limb-project.com/limb/3.x/trunk/limb/cache2/">cache2</a>:</p>
<ul>
<li>6 хранилищ: память скрипта, APC, memcached, БД, файлы, сессия, фейк для тестов, (и еще, как минимум, добавится кэш в РНР-файл)</li>
<li>хранилища будут иметь абсолютно одинаковый интерфейс и потокобезопасность:
<ul>
<li>add</li>
<li>get</li>
<li>set</li>
<li>delete</li>
<li>flush</li>
<li>increment/decrement</li>
<li>safeIncrement/safeDecrement</li>
<li>lock/unlock</li>
</ul>
</li>
<li>логгер, позволяющий отслеживать операции с кэшом</li>
<li>утилитка для проведения микротестов</li>
<li>полустабильное состояние</li>
</ul>
<p>Вся информация о хранилище задается с помощью <a href="http://en.wikipedia.org/wiki/Database_Source_Name">DSN</a>. Например:</p>
<pre lang="PHP">file:///tmp/cache //кэш на файлах
apc:///?prefix=foo //кэш в APC, ключи префиксуются строкой foo.</pre>
<p><span style="font-style: italic;">Ну совсем все радостно, но файлы на продакшене на отдельном сервере лежат, а у разработчиков локально надо. Или настройкой sphinx занимается только один человек, и поднимать его у остальных — бессмысленно.</span></p>
<h3>Абстракция. Как много в этом слове</h3>
<p>Как известно любая проблема, кроме одной, решается введением абстракции. Решим и нашу.</p>
<p>Для начала разделим каждый наш файл конфигурации на две части: общую и специфичную для конкретной машины. У нас это, например, <code>avatar.conf.php</code> и <code>avatar.conf.override.php</code>. Специфичные штуки игнорируем в нашей системе контроля версий. Общие кладем рядом с кодом. Желательно, чтобы в файле с общими настройками задавались настройки для продакшена. Тогда вы во-первых их(настройки продакшена) не потеряете, а во-вторых проще будет продакшен обновлять.</p>
<p>Разница при работе с медиа-файлами обычно сводится к двум задачам:</p>
<ul>
<li>куда-то положить</li>
<li>откуда-то запросить</li>
</ul>
<p>Для указания размещения файлов мы, используем URL и обычную функцию copy(). Например на продакшене</p>
<pre lang="PHP">'scp://storage_user@storage_host1/'
.'?rsa_pub='.urlencode('/home/php-fpm/.ssh/id_rsa.pub')
.'&amp;rsa;=' .urlencode('/home/php-fpm/.ssh/id_rsa').'/media'</pre>
<p>, а на машине разработчика просто</p>
<pre lang="PHP">'/www/somesite/www/media/'</pre>
<p>Ну а с тем откуда запрашивать еще проще. Для продакшена <code>'img-1.somesite.ru/media/'</code>, а у разработчика <code>somesite.pupkin.local/media/'</code>. Это базовые пути и URL&#8217;ы для медиа-файлов. Остальное определяется, исходя из id файла.</p>
<p>Со Sphinx&#8217;ом поступим схожим образом. Добавим в конфигурационный файл директиву fake_search, которая будет определять тип поискового сервиса. Используя фабричный метод, наподобие такого:</p>
<pre lang="PHP">static function createSearchService($config)
{
  if(!isset($config['fake_search']) || !$config['fake_search'])
    return SphinxClient();
  else
    return FakeSphinxClient();
}</pre>
<p>, т.к.  SphinxClient и  FakeSphinxClient реализуют общий интерфейс, то для остальной программы такая замена пройдет незаметно.  FakeSphinxClient будет просто отдавать первые  подходящие объекты, а следовательно верстальщик сможет застилить страницу с результатами поиска, не занимаясь такими «магическими» штуками, как установка Sphinx.</p>
<p><span style="font-style: italic;">Разработчики рады, и поют песни, восхваляющие абстракции. Осталась одна маленькая проблемка — разница в версиях ПО третих сторон, и их настройках.</span></p>
<h3>Может хватит, а?</h3>
<p>Вот на этом шаге мы остановились и находимся в данный момент. Следующий этап эволюции   это работа в среде, максимально приближенной к «боевой». Т.е. работа на общем сервере, где с помощью виртуализации поддерживается среда, в которой нам придется работать на продакшене. У каждого свой код, своя база(и не одна), в общей СУБД, свои хосты. Все межсерверные взаимодействия отлаживаются еще на этапе разработки. И проблем с разными версиями ПО не возникает.</p>
<p>Коммит.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/11/%d0%bb%d0%b5%d0%b1%d0%b5%d0%b4%d1%8c-%d1%80%d0%b0%d0%ba-%d0%b8-%d1%89%d1%83%d0%ba%d0%b0-%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d0%bd/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dog-pile эффект. Как отгонять стаи собак.</title>
		<link>http://korchasa.ru/index.php/2008/04/dog-pile-%d1%8d%d1%84%d1%84%d0%b5%d0%ba%d1%82-%d0%ba%d0%b0%d0%ba-%d0%be%d1%82%d0%b3%d0%be%d0%bd%d1%8f%d1%82%d1%8c-%d1%81%d1%82%d0%b0%d0%b8-%d1%81%d0%be%d0%b1%d0%b0%d0%ba/</link>
		<comments>http://korchasa.ru/index.php/2008/04/dog-pile-%d1%8d%d1%84%d1%84%d0%b5%d0%ba%d1%82-%d0%ba%d0%b0%d0%ba-%d0%be%d1%82%d0%b3%d0%be%d0%bd%d1%8f%d1%82%d1%8c-%d1%81%d1%82%d0%b0%d0%b8-%d1%81%d0%be%d0%b1%d0%b0%d0%ba/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 02:16:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[кэширование]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=32</guid>
		<description><![CDATA[Dog-pile эффект — ситуация когда кэш протухает, а большое количество запросов генерирует высокую нагрузку на источник данных, из которых строиться кэш.  Представьте, что вы кэшируете результат какого то тяжёлого запроса, например, список популярных статей. В какой-то момент времени кэш протухает, и его кто-то должен построить заново. В общем то пока все хорошо. Кроме случаев [...]]]></description>
			<content:encoded><![CDATA[<p><dfn>Dog-pile эффект</dfn> — ситуация когда кэш протухает, а большое количество запросов генерирует высокую нагрузку на источник данных, из которых строиться кэш.  <span id="more-32"></span>Представьте, что вы кэшируете результат какого то тяжёлого запроса, например, список популярных статей. В какой-то момент времени кэш протухает, и его кто-то должен построить заново. В общем то пока все хорошо. Кроме случаев когда построение кэша тяжёлая операция, а запросов на него много. Например, запрос для генерации кэша занимает 1 секунду, а пользователи ломятся по 10 штуков в секунду. Соответственно, 9 пользователей (кроме первого) будут только зря нагружать базу. А при большом количестве запросов могут и полностью ее положить.</p>
<h3>И пусть весь мир подождёт</h3>
<p>Первое, что нужно решить — может ли пользователь ждать генерации кэша. Пример с популярными статьями это цветочки, ибо есть еще сложно рассчитываемые рейтинги, которые могут считаться оооочень долго.  Предположим, что у нас простой случай и пользователь не сломается, если подождёт секунду-другую.</p>
<h4>Честные блокировки на генерацию</h4>
<p>Решение в лоб. Первый пришедший лочит кэш на генерацию, и отправляется генерировать кэш. Остальные, увидев лок, понимают, что не успели, чешут репы и думают, что делать.  Как именно делать лок зависит только от вашей фантазии и имеющихся средств. Это может быть, что угодно:</p>
<dl>
<dt>Лок файловой системы</dt>
<dd>есть косяки, но иногда работает <img src='http://korchasa.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Подробности в описании функции <a href="http://ru2.php.net/manual/en/function.flock.php">flock()</a>.</dd>
<dt>Мьютекс в хранилище</dt>
<dd>Если мы используем memcache и генерируемый кэш имеет ключ «popular_articles», тогда наличие данных с ключем «popular_articles_lock», говорит о том, что наш кэш уже кто-то генерирует. Тоже самое справедливо и для других хранилищ.</dd>
<dt>IPC семафоры</dt>
<dd>Настоящие пацанские <a href="http://ru2.php.net/manual/en/ref.sem.php">семафоры</a> <img src='http://korchasa.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Ни разу не использовал — руки не доходят.</dd>
</dl>
<p>Плюсы локов в том, что клиент сам решает, что делать в ситуации, когда ему нужны данные, а их кто-то генерирует. Например, если есть старые данные, то мы можем их отдать, а если данных нет, то либо подождать, либо честно вывести пользователю, что данных нет. На самом деле висящие в течении секунды пользователи совсем не есть гуд, но иногда можно допустить и такое.  Так же не стоит забывать, что при генерации может возникнуть ошибка, и в этом случае лок может остаться висеть(в случае memcache можно ставить ttl на лок).</p>
<h4>Организация «окна» для генерации</h4>
<p>Способ был подсмотрен в исходниках какого-то фреймворка <img src='http://korchasa.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Суть его в том, что ttl поддерживается не самим хранилищем, а клиентом, в виде отдельного ключа, и при истечение данные не удаляются. Т.е. приходит первый запрос,   видит что ttl истек, и начинает генерировать новое значение. Чтобы остальные запросы подумали, что все нормально, он продлевает ttl существующего кэша на какую-то заранее определённую величину. Если писатель умирает, то кэш быстро снова протухнет и кто-нибудь подхватит знамя генерации с трупа павшего товарища. Если же все нормально, то будет записан новое значение кэша и установлен новый ttl.  Основным минусом такого подхода является то, что ttl нельзя хранить средствами самого кэш-storage, т.к. во всех самых известных хранилищах невозможно получить значение ttl и сами данные с истекшим ttl.</p>
<h3>Я хочу вас всех, я хочу вас сразу!</h3>
<p>Случай у нас тяжёлый, и пользователю будет скучно коротать 20 секунд рисуя матом надписи на пыльном столе. Я знаю про кого будут эти надписи.  Главное откровение: чтобы избавиться от последствий многопоточности надо свести ее к одному потоку. Просто и со вкусом. Убираем всю генерацию кэша в оффлайн. ttl-ем в данном случае будет время перезапуска генерирующих кэш скриптов. Помимо быстрого ответа пользователю тут есть еще один плюс — наборы кэшей часто генерировать быстрее, чем каждый из них по отдельности, ибо можно хранить какие-то промежуточные данные.  UPD: Вот <a href="http://www.smira.ru/2008/10/28/web-caching-memcached-4/">ещё статья</a> по теме.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/04/dog-pile-%d1%8d%d1%84%d1%84%d0%b5%d0%ba%d1%82-%d0%ba%d0%b0%d0%ba-%d0%be%d1%82%d0%b3%d0%be%d0%bd%d1%8f%d1%82%d1%8c-%d1%81%d1%82%d0%b0%d0%b8-%d1%81%d0%be%d0%b1%d0%b0%d0%ba/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Организация &quot;кусочкового&quot; кеширование HTML</title>
		<link>http://korchasa.ru/index.php/2008/04/%d0%be%d1%80%d0%b3%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%ba%d1%83%d1%81%d0%be%d1%87%d0%ba%d0%be%d0%b2%d0%be%d0%b3%d0%be-%d0%ba%d0%b5%d1%88%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8/</link>
		<comments>http://korchasa.ru/index.php/2008/04/%d0%be%d1%80%d0%b3%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%ba%d1%83%d1%81%d0%be%d1%87%d0%ba%d0%be%d0%b2%d0%be%d0%b3%d0%be-%d0%ba%d0%b5%d1%88%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 18:15:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[limb]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[кэширование]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=33</guid>
		<description><![CDATA[Навеяно парой статей на Хабре, и тем, что вчера сделал cache тег для Macro.

Зачем?
Хочется убить двух зайцев: избавиться от запросов за редко изменяемыми данными, и их отрисовки. Вообще это смахивает на попытку минимальным количеством движений сделать глобальное счастье. Можно потом перед другими фрэймворками меряться, ага.
На самом деле задача избавиться от отрисовки куска страницы вообще какая-то [...]]]></description>
			<content:encoded><![CDATA[<p>Навеяно <a href="http://habrahabr.ru/blog/php/38628.html">парой</a> <a href="http://habrahabr.ru/blog/django/39423.html">статей</a> на Хабре, и тем, что вчера сделал cache тег для <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro">Macro</a>.<br />
<span id="more-33"></span></p>
<h3>Зачем?</h3>
<p>Хочется убить двух зайцев: избавиться от запросов за редко изменяемыми данными, и их отрисовки. Вообще это смахивает на попытку минимальным количеством движений сделать глобальное счастье. Можно потом перед другими фрэймворками меряться, ага.</p>
<p>На самом деле задача избавиться от отрисовки куска страницы вообще какая-то странная, если мы используем быстрый шаблонизатор. Application-сервера, при нормальной  арихитектуре, масштабируются легко и непринужденно, а APC, сам закэширует скомпилированный шаблон, если он компилируется в РНР-код, как это сделано в Smarty,  <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:macro">Macro</a> и многих других.</p>
<p>С другой стороны, если есть простой способ закэшировать, то почему бы и нет.</p>
<h3>Откуда данные, и как заставить протухнуть кэш.</h3>
<p>Данные в шаблоне могут получаться двумя способами. Первый и традиционный это push-подход, когда контроллер заполняет какой-то <a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html">data-transfer-object</a>, или в сам шаблон. Такой подход используется чаще всего, ибо это &#8220;тру MVC&#8221;! <img src='http://korchasa.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Второй подход &#8211; pull. При pull подходе в шаблоне расставляются инструкции по получению данных, в обход контроллера, напрямую от моделей, сервисов и прочих провайдеров данных. Этот способ позволяет избавиться от повторяющихся set&#8217;ов в контроллере, но не позволяет ограничить, из контроллера, их получение, и усложняет поддержку шаблонов, ибо иногда трудно понять откуда получены данные.</p>
<p>Теперь об определении развалидации кэша. Тут тоже два основных подхода. Первый &#8211; ttl(time-to-live &#8211; время жизни). Мы определяем, что список новостей, например, валиден в течении 15 минут. Основной плюс &#8211; мы уверены, что за данными скрипт будет обращаться не чаще чем раз в 15 минут, и зная частоту обращений можем точно расчитать эффективность такого кеша. Второй плюс &#8211; простота реализации. Главный же минус в том, что наш список на самом деле может измениться через секунду после построения кэша, а пользователь увидит изменения только через 15 минут.</p>
<p>Второй вариант сброса кэша &#8211; по действию. Например, тот контроллер(экшн), который отвечает за публикацию новостей, сам убивает кеш, и формирует новый (тут тоже много разных камней, типа lost updates, и прочих порождений многопоточности, но все они решаемы). Плюс &#8211; кэш всегда валиден. Первый минус это сложность реализации (нам нужно добавлять код для работы с кэшем во все места, где идет работа с данными кэша &#8211; публикация новостей, их удаление, и т.д.). Второй минус в том, что эффективность такого кэша сильно зависит от частоты изменения данных.</p>
<p>А теперь тоже самое, но в свете кэширования частей страницы.</p>
<h3>Push me. And then just touch me&#8230;</h3>
<p>Кэшировать части страницы, при push-данных хуже, чем кэшировать эти самые данные. Почему? Потому что мы &#8220;загадим&#8221; кодом работы с кэшем и шаблон, и контроллер, а из плюсов только экономия на отрисовке.</p>
<h3>Pull-данные и развалидация по действию</h3>
<p>Что мы получаем? Логика работы с кешем в шаблоне и тех контроллерах, которые отвечают за действия. Опять не тру, и лучше опять кэшировать данные, через какой-нибудь LastNewsService.</p>
<h3>Pull-данные и ttl</h3>
<p>Вот то ради чего собственно и делаются теги cache, блоки django, компоненты и т.д. Вся логика только в шаблоне (или настройках компонента). Красотища!</p>
<h3>Вывод:</h3>
<p>Кэширование части HTML имеет смысл только для pull данных с устареванием по времени. Во всех остальных случаях его плюсы, по сравнению с кэшированием данных, сводятся к экономии работы шаблонизатора.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/04/%d0%be%d1%80%d0%b3%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%ba%d1%83%d1%81%d0%be%d1%87%d0%ba%d0%be%d0%b2%d0%be%d0%b3%d0%be-%d0%ba%d0%b5%d1%88%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP 5.3: что пых грядущий нам готовит?</title>
		<link>http://korchasa.ru/index.php/2008/02/php-53-%d1%87%d1%82%d0%be-%d0%bf%d1%8b%d1%85-%d0%b3%d1%80%d1%8f%d0%b4%d1%83%d1%89%d0%b8%d0%b9-%d0%bd%d0%b0%d0%bc-%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d1%82/</link>
		<comments>http://korchasa.ru/index.php/2008/02/php-53-%d1%87%d1%82%d0%be-%d0%bf%d1%8b%d1%85-%d0%b3%d1%80%d1%8f%d0%b4%d1%83%d1%89%d0%b8%d0%b9-%d0%bd%d0%b0%d0%bc-%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d1%82/#comments</comments>
		<pubDate>Fri, 22 Feb 2008 00:00:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[базы данных]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=36</guid>
		<description><![CDATA[То о чем так долго говорили большевики&#8230;
Кратенько:

пространства имен
mysqlnd
позднее статическое связывание
динамические вызовы статических методов
Прочие изменения

А теперь подробно&#8230;

Пространства имен
/* Серое и унылое настоящее */
class MyAclSimpleRole {}
$a = new MyAclSimpleRole;

/* или (Zend FW) */
class My_Acl_Simple_Role {}
$a = new My_Acl_Simple_Role;

/* А теперь так */
namespace My::Acl::Simple;
class Role {}

/* По прежнему можем использовать полное имя */
$a = new My::Acl::Simple::Role;

/* А если [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>То о чем так долго говорили большевики&#8230;</p></blockquote>
<p>Кратенько:</p>
<ul>
<li>пространства имен</li>
<li>mysqlnd</li>
<li>позднее статическое связывание</li>
<li>динамические вызовы статических методов</li>
<li>Прочие изменения</li>
</ul>
<p>А теперь подробно&#8230;<br />
<span id="more-36"></span></p>
<h3>Пространства имен</h3>
<pre><code class="php">/* Серое и унылое настоящее */
class MyAclSimpleRole {}
$a = new MyAclSimpleRole;

/* или (Zend FW) */
class My_Acl_Simple_Role {}
$a = new My_Acl_Simple_Role;

/* А теперь так */
namespace My::Acl::Simple;
class Role {}

/* По прежнему можем использовать полное имя */
$a = new My::Acl::Simple::Role;

/* А если use добавить... */
use My;
$a = new Acl::Simple::Role;

use My::Acl;
$a = new Simple::Role;

use My::Acl::Simple;
$a = new Role;

/* А если alias добавить, то вообще красота */
use My::Acl::Simple as defaultAcl;
$a = new defaultAcl::Role;

use My as default;
$a = new default::Acl::Role;</pre>
<p>Помимо этого введена константа __NAMESPACE__, добавки в рефлексии, глобальное пространство "::".</p>
<p>Людям, использующим в названии классов идеологию, схожую с идеологией Zend Framework, данная фича очень понравится. Возможно она "под него" и вводилась <img src='http://korchasa.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>К сожалению не смог найти информацию о том, можно ли будет повесить обработчик на команду use, а следовательно анализировать и всячески инициализировать пространства.</p>
<h3><a href="http://blog.ulf-wendel.de/?p=149">mysqlnd</a> (MySQL native driver)</h3>
<p>Наконец то в РНР появится замена для libmysql, причем "заточенная" под PHP на C-шном уровне. Напомню, что в самом начале 5-ой ветки libmysqli пришлось убрать из ядра по лицензионным соображениям. mysqlnd же выпускается под <a href="http://www.php.net/license">лицензией PHP</a>. Вы наверное уже обрадовались, что из-за нового API, сможете выбить из начальства время на review всего кода, работающего с БД?</p>
<p>К сожалению я не знаю код символа изображающего фигу, сейчас бы пригодился.</p>
<p>mysqlnd это низкоуровневая С-шная библиотека для работы с базой данных, а не новое расширение для PHP. mysqlnd уже "понимает" API ext/mysqli, поддержка PDO/MySQL сейчас пишеться, а поддержки ext/mysql не будет.</p>
<p><a href="http://www.hristov.com/andrey/projects/php_stuff/pres/mysqlnd_vikinger.pdf"><img src="http://blog.ulf-wendel.de/images/mysqlnd2.gif" alt="#########" /></a></p>
<p>Уже приведены <a href="http://blog.ulf-wendel.de/?p=136">бенчмарки</a>, и их результаты мягко говоря радуют.</p>
<h3>Позднее статическое связывание</h3>
<p>Проще всего текущее бедственное состояние будет пояснить на примере:</p>
<pre lang="php">class Foo {
  public static function whoIsItDrinkins() {
      return __CLASS__;
  }
}

class Bar extends Foo {}

echo Bar::whoIsItDrinkins(); //Foo</pre>
<p>Проблема в том, что переменная указывающая на текущий класс (__CLASS__ или self) указывает на тот класс, в котором метод объявляется, а не тот, у которого он вызван.</p>
<p>Острее всего эта проблема проявляется при попытке реализовать в РНР паттерн <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:active_record">ActiveRecord</a>, и приводит к <a href="http://forum.agiledev.ru/index.php?t=msg&amp;goto=5540">использованию грязноватых хаков</a> <img src='http://korchasa.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>В версии 5.3 появится метод get_called_class(), который будет указывать на класс, у которого этот метод вызван.</p>
<pre lang="php">class Foo {
  public static function whoIsItDrinkins() {
      return get_called_class();
  }
}

class Bar extends Foo {}

echo Bar::whoIsItDrinkins(); //та-да!</pre>
<h3>__callstatic()</h3>
<pre lang="php">class FooFactory {
  static function call() {
    echo 'Простите все операторы сейчас заняты';
  }
  static function __callStatic( $methodname, $args ) {
    echo '

Добрый день! Вы только вызвали статический метод ' . $methodname . '

';
    echo '

С параметрами:

';
    echo '</pre>
<pre>' . print_r( $args, true ) . '</pre>
<p>';<br />
echo '</p>
<p>Спасибо. Ваш вызов для нас очень важен.</p>
<p>';<br />
}<br />
}</p>
<p>FooFactory :: call();<br />
FooFactory :: callAnotherTime('А ну отозвались!');</p>
<p>Давно пора. Это же какие красоты открываются. Можно например автоматом маппить поиски в, уже упомянутый, <a href="http://wiki.limb-project.com/doku.php?id=limb3:ru:packages:active_record">ActiveRecord</a>:</p>
<pre lang="php">$posted_articles = Articles::findByIsPosted(true);

$new_members = Member::findByRegistrationDateLessWhat($today);</pre>
<p>И все это без единой дополнительной строчки в классах Article и Member!</p>
<p><small>Когда же появиться нативная функция для преобразования camel case в underlines <img src='http://korchasa.ru/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </small></p>
<h3>Динамические вызовы статических методов</h3>
<pre lang="php">$method = 'callAnotherTime';
FooFactory :: $method('Я вас каждый день вызывать буду!');</pre>
<p>Практического применения я вот так сходу найти не смог, но но думаю оно как суслик, я его не вижу, а оно есть</p>
<h3>Новый уровень ошибок E_DEPRECATED</h3>
<p>Новый уровень позволит заранее начать избавляться от функционала, который впоследствии не будет поддерживаться</p>
<h3>Конфигурационные файлы</h3>
<ul>
<li>конфиги теперь можно делать для конкретной директории, а не использовать для этого .htaccess и php_value/php_admin_valie</li>
<li>в php.ini добавлены секции для конкретных директорий. Их опции не могут переопределяться ни в скриптах, ни в конфигурационных файлах директорий</li>
<li>сообщения об ошибках в конфигурационных файлах теперь более "говорящие"</li>
<li>добавлена поддержка ключей для массивов</li>
</ul>
<h3>Прочие изменения</h3>
<ul>
<li>в расширение openSSL добавленна поддержка алгоритма <a href="http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B8%D1%84%D1%84%D0%B8_%E2%80%94_%D0%A5%D0%B5%D0%BB%D0%BB%D0%BC%D0%B0%D0%BD%D0%B0">Диффи-Хеллмана</a>, который необходим для тех, кто работает с OpenID.</li>
<li>функция <a href="http://php.net/getopt">get_opt()</a> теперь кроссплатформенная</li>
<li>в расширение sqlite добавленна поддержка Sqlite3</li>
<li>сделано несколько улучшений в SPL</li>
<li>добавлена константа __DIR__, которая заменит dirname(__FILE__)</li>
</ul>
<p><strong>UPD</strong>: добавлена информация о __DIR__</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/02/php-53-%d1%87%d1%82%d0%be-%d0%bf%d1%8b%d1%85-%d0%b3%d1%80%d1%8f%d0%b4%d1%83%d1%89%d0%b8%d0%b9-%d0%bd%d0%b0%d0%bc-%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d1%82/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>4 в 1 &#8211; простой комбайн для оптимизации статики</title>
		<link>http://korchasa.ru/index.php/2008/01/4-%d0%b2-1-%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b9-%d0%ba%d0%be%d0%bc%d0%b1%d0%b0%d0%b9%d0%bd-%d0%b4%d0%bb%d1%8f-%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d1%81%d1%82/</link>
		<comments>http://korchasa.ru/index.php/2008/01/4-%d0%b2-1-%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b9-%d0%ba%d0%be%d0%bc%d0%b1%d0%b0%d0%b9%d0%bd-%d0%b4%d0%bb%d1%8f-%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d1%81%d1%82/#comments</comments>
		<pubDate>Thu, 24 Jan 2008 01:39:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Анонсы]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[кэширование]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разметка]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=38</guid>
		<description><![CDATA[Наткнулся на интересную библиотеку. Вот перевод интродакшена:

Как  уменьшить время загрузки сайта в 5 раз, тремя строчками кода.
Есть 4 относительно простых способа, с помощью которых вы можете уменьшить время  загрузки страницы:

делать меньше HTTP запросов
выставлять expires на далекое будущее
сжимать компоненты вашей страницы gzip&#8217;ом
обфускачивать ваши JavaScript и CSS файлы, а так же сам HTML-код

После моего поста [...]]]></description>
			<content:encoded><![CDATA[<p>Наткнулся на <a href="http://aciddrop.com/2008/01/21/boost-your-website-load-time-with-3-lines-of-code/">интересную библиотеку</a>. Вот перевод интродакшена:</p>
<blockquote>
<h3>Как  уменьшить время загрузки сайта в 5 раз, тремя строчками кода.</h3>
<p>Есть 4 относительно простых способа, с помощью которых вы можете уменьшить время  загрузки страницы:</p>
<ul>
<li>делать меньше HTTP запросов</li>
<li>выставлять expires на далекое будущее</li>
<li>сжимать компоненты вашей страницы gzip&#8217;ом</li>
<li>обфускачивать ваши JavaScript и CSS файлы, а так же сам HTML-код</li>
</ul>
<p>После моего поста об <a href="http://aciddrop.com/2008/01/03/automatically-join-your-javascript-and-css-into-a-single-file/">объединении CSS и JavaScript файлов</a>, я написал PHP-скрипт, который будет автоматически применять все вышеперечисленные способы. Все, что вам нужно сделать, это поместить следующий код в начало своего PHP-файла:</p>
<pre lang="php">require_once ( 'class.compressor.php' ) ;
$compressor = new compressor ( 'css,javascript,page' ) ;</pre>
<p>А этот код в конец:</p>
<pre lang="php">$compressor -&gt; finish ( ) ;</pre>
</blockquote>
<p><span id="more-38"></span><br />
Сравните:<br />
<img src="http://aciddrop.com/aciddrop/minify/uncompressed-small.gif" border="0" alt="Firebug before compression" /><br />
<img src="http://aciddrop.com/aciddrop/minify/compressed-small.gif" border="0" alt="Firebug before compression" /></p>
<p>Библиотека довольно интересная. Особенно для небольших сайтов, где еще можно отдавать весь js и css сразу. Да и в плане выставления правильных заголовков для заgzipенных данных есть чему поучиться.</p>
<p>Примеры <a href="http://aciddrop.com/aciddrop/minify/">с использованием gzip</a>, <a href="http://aciddrop.com/aciddrop/minify/compress_me.php?compress=no">без него</a>.</p>
<p>Скачать можно <a href="http://aciddrop.com/2008/01/23/site-speed-boost-script-updated/">тут</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/01/4-%d0%b2-1-%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b9-%d0%ba%d0%be%d0%bc%d0%b1%d0%b0%d0%b9%d0%bd-%d0%b4%d0%bb%d1%8f-%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d1%81%d1%82/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Inclued. Профайлинг подключаемых файлов в PHP</title>
		<link>http://korchasa.ru/index.php/2008/01/inclued-%d0%bf%d1%80%d0%be%d1%84%d0%b0%d0%b9%d0%bb%d0%b8%d0%bd%d0%b3-%d0%bf%d0%be%d0%b4%d0%ba%d0%bb%d1%8e%d1%87%d0%b0%d0%b5%d0%bc%d1%8b%d1%85-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%b2-php/</link>
		<comments>http://korchasa.ru/index.php/2008/01/inclued-%d0%bf%d1%80%d0%be%d1%84%d0%b0%d0%b9%d0%bb%d0%b8%d0%bd%d0%b3-%d0%bf%d0%be%d0%b4%d0%ba%d0%bb%d1%8e%d1%87%d0%b0%d0%b5%d0%bc%d1%8b%d1%85-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%b2-php/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 22:08:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Анонсы]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=40</guid>
		<description><![CDATA[Не все знают, но существует удобная утилита для определения подключаемых (include, require) файлов в PHP. И зовется она — Inclued. В данный момент последней версией является 0.3 (inclued-0.3.tar.gz 7.5Кб).
Inclued представляет из себя PECL-пакет, со всеми вытекающими последствиями. Что бы не дублировать информацию в интернете (а на самом деле лень писать) вот ссылка на информацию об [...]]]></description>
			<content:encoded><![CDATA[<p>Не все знают, но существует удобная утилита для определения подключаемых (include, require) файлов в PHP. И зовется она — <a href="http://t3.dotgnu.info/blog/tags/inclued/">Inclued</a>. В данный момент последней версией является 0.3 (<a href="http://t3.dotgnu.info/code/inclued-0.3.tar.gz">inclued-0.3.tar.gz</a> 7.5Кб).</p>
<p><span id="more-40"></span>Inclued представляет из себя PECL-пакет, со всеми вытекающими последствиями. Что бы не дублировать информацию в интернете (а на самом деле лень писать) <a href="http://handy-notes.blogspot.com/2007/06/pecl-php.html">вот</a> ссылка на информацию об установке PECL&#8217;овских пакетов.</p>
<p>Inclued версии 0.3 в процессе работы строит дерево подключений и самостоятельно сохраняет его в файл, вида inclued.XXXXX.X в dumpdir, указанный в php.ini.<br />
Пример php.ini, для использования inclued:</p>
<pre lang="ini">...
inclued.enabled = On
inclued.dumpdir = /tmp/
...</pre>
<p>Создадим несколько файлов:<br />
<strong>a.php</strong></p>
<pre lang="php">';</pre>
<p><strong>b.php</strong></p>
<pre lang="php">';</pre>
<p><strong>c.php</strong></p>
<pre lang="php">';</pre>
<p><strong>d.php</strong></p>
<pre lang="php">';</pre>
<p><strong>index.php</strong></p>
<pre lang="php">';
var_dump(inclued_get_data());</pre>
<p>и посмотрим, что нам «выдаст» index.php. В моем случае (с включенным xdebug) это:</p>
<blockquote><p>a.php<br />
d.php<br />
c.php<br />
b.php<br />
index.php</p>
<pre><strong>array</strong>
'request' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
'_REQUEST' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
<span style="color: #888a85;"><em>empty</em></span>
'_COOKIE' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
<span style="color: #888a85;"><em>empty</em></span>
'SCRIPT_FILENAME' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/index.php'</span> <em>(length=26)</em>
'REQUEST_URI' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/inclued/'</span> <em>(length=9)</em>
'REQUEST_TIME' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">1200852009</span>
'includes' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
0 <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
    'operation' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'include'</span> <em>(length=7)</em>
    'op_type' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">2</span>
    'filename' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'a.php'</span> <em>(length=5)</em>
    'opened_path' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/a.php'</span> <em>(length=22)</em>
    'fromfile' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/index.php'</span> <em>(length=26)</em>
    'fromline' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">2</span>
1 <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
    'operation' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'include_once'</span> <em>(length=12)</em>
    'op_type' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">4</span>
    'filename' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'b.php'</span> <em>(length=5)</em>
    'opened_path' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/b.php'</span> <em>(length=22)</em>
    'fromfile' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/index.php'</span> <em>(length=26)</em>
    'fromline' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">3</span>
2 <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
    'operation' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'require'</span> <em>(length=7)</em>
    'op_type' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">8</span>
    'filename' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'c.php'</span> <em>(length=5)</em>
    'opened_path' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/c.php'</span> <em>(length=22)</em>
    'fromfile' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/b.php'</span> <em>(length=22)</em>
    'fromline' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">2</span>
3 <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
    'operation' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'require_once'</span> <em>(length=12)</em>
    'op_type' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">16</span>
    'filename' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'d.php'</span> <em>(length=5)</em>
    'opened_path' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/d.php'</span> <em>(length=22)</em>
    'fromfile' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">string</span> <span style="color: #cc0000;">'/var/www/inclued/c.php'</span> <em>(length=22)</em>
    'fromline' <span style="color: #888a85;">=&gt;</span> <span style="font-size:85%;">int</span> <span style="color: #4e9a06;">2</span>
'inheritance' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
<span style="color: #888a85;"><em>empty</em></span>
'classes' <span style="color: #888a85;">=&gt;</span>
<strong>array</strong>
<span style="color: #888a85;"><em>empty</em></span></pre>
</blockquote>
<p>Помимо того, что информацию можно получить с помошью inclued_get_data(), как уже было сказано выше, inclued сохраняет схему вызовов в отдельный файл, в формате JSON.</p>
<p>Сохраненный файл можно использовать для построения графиков вызовов. Для это в пакете присутствует скрипт gengraph.php, предназначенный для генерации описания графа на языке <a href="http://www.graphviz.org/doc/info/lang.html">DOT</a>, который потом можно визуализировать с помощью <a href="http://ru.wikipedia.org/wiki/Graphviz">Graphviz</a></p>
<p>Для имеющегося у нас набора файлов график будет выглядеть следующим образом:<br />
<a href="http://bp1.blogger.com/_sG5w5ttg_ig/R5OfGqCakJI/AAAAAAAAAZs/4twy2ak2CGc/s1600-h/inclued.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5157640934981800082" style="cursor: pointer;" src="http://bp1.blogger.com/_sG5w5ttg_ig/R5OfGqCakJI/AAAAAAAAAZs/4twy2ak2CGc/s400/inclued.png" border="0" alt="" /></a></p>
<p>В завершение <a href="http://korchasa.googlepages.com/gengraph.php">вот</a> моя интерпритация gengraph.php, для генерации графиков «в одно действие».</p>
<p>PS: Помимо графиков подключений файлов inclued умеет строить графики иерархий классов.  Но это позже, если кому то будет интересно.</p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2008/01/inclued-%d0%bf%d1%80%d0%be%d1%84%d0%b0%d0%b9%d0%bb%d0%b8%d0%bd%d0%b3-%d0%bf%d0%be%d0%b4%d0%ba%d0%bb%d1%8e%d1%87%d0%b0%d0%b5%d0%bc%d1%8b%d1%85-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%b2-php/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Google Chart API</title>
		<link>http://korchasa.ru/index.php/2007/12/google-chart-api/</link>
		<comments>http://korchasa.ru/index.php/2007/12/google-chart-api/#comments</comments>
		<pubDate>Fri, 07 Dec 2007 03:28:00 +0000</pubDate>
		<dc:creator>korchasa</dc:creator>
				<category><![CDATA[Анонсы]]></category>
		<category><![CDATA[производительность]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://korchasa.ru/?p=41</guid>
		<description><![CDATA[Несколько дней назад компания Google выпустила новый сервис &#8211; Google Chart API.
Сервис как и все гениальное прост: теперь все, что необходимо для построение графиков это сформировать URL.
На сегодняшний день поддерживаются несколько типов диаграмм:

    
Поддерживаются все необходимые(на первое время) опции:

заголовок
легенда
набор цветов
заливка цветом диаграмм, фона и поверхностей
различные типы осей координат
сетка
вертикальные и горизонтальные маркеры
различные типы [...]]]></description>
			<content:encoded><![CDATA[<p>Несколько дней назад компания Google выпустила новый сервис &#8211; <a href="http://code.google.com/apis/chart/">Google Chart API</a>.</p>
<p>Сервис как и все гениальное прост: теперь все, что необходимо для построение графиков это сформировать URL.</p>
<p>На сегодняшний день поддерживаются несколько типов диаграмм:<br />
<a href="http://chart.apis.google.com/chart?cht=lc&amp;chco=ff0000,00ff00,0000ff&amp;chs=200x125&amp;chd=s:FOETHECat,lkjtf3asv,KATYPSNXJ&amp;chxt=x,y&amp;chxl=0:%7COct%7CNov%7CDec%7C1:%7C%7C20K%7C%7C60K%7C%7C100K"><br />
<img src="http://habrahabr.ru/pictures/00/00/00/92/60/picture_3.png" border="0" alt="" hspace="10" vspace="10" width="200" height="125" /></a> <a href="http://chart.apis.google.com/chart?cht=bhs&amp;chco=ff0000,00ff00,0000ff,&amp;chs=200x125&amp;chd=s:FOE,THE,Bar&amp;chxt=x,y&amp;chxl=1:%7CDec%7CNov%7COct%7C0:%7C%7C20K%7C%7C60K%7C%7C100K%7C"><img src="http://habrahabr.ru/pictures/00/00/00/92/60/picture_4.png" border="0" alt="" hspace="10" vspace="10" width="200" height="125" /></a> <a href="http://chart.apis.google.com/chart?cht=p3&amp;chs=200x90&amp;chd=s:Hellobla&amp;chl=May%7CJun%7CJul%7CAug%7CSep%7COct&amp;chco=0000ff"><img src="http://habrahabr.ru/pictures/00/00/00/92/60/picture_5.png" border="0" alt="" hspace="10" vspace="10" width="200" height="90" /></a> <a href="http://chart.apis.google.com/chart?cht=v&amp;chs=200x100&amp;chd=t:100,80,60,30,30,30,10"><img src="http://habrahabr.ru/pictures/00/00/00/92/60/picture_6.png" border="0" alt="" hspace="10" vspace="10" width="200" height="100" /></a> <a href="http://chart.apis.google.com/chart?cht=s&amp;chd=s:984sttvuvkQIBLKNCAIi,DEJPgq0uov17zwopQODS,AFLPTXaflptx159gsDrn&amp;chxt=x,y&amp;chxl=0:%7C0%7C2%7C3%7C4%7C5%7C6%7C7%7C8%7C9%7C10%7C1:%7C0%7C25%7C50%7C75%7C100&amp;chs=200x125"><img src="http://habrahabr.ru/pictures/00/00/00/92/60/picture_7.png" border="0" alt="" hspace="10" vspace="10" width="200" height="125" /></a></p>
<p>Поддерживаются все необходимые(на первое время) <a href="http://code.google.com/apis/chart/#required_params">опции</a>:</p>
<ul>
<li>заголовок</li>
<li>легенда</li>
<li>набор цветов</li>
<li>заливка цветом диаграмм, фона и поверхностей</li>
<li>различные типы осей координат</li>
<li>сетка</li>
<li>вертикальные и горизонтальные маркеры</li>
<li>различные типы линий</li>
<li>выносные метки, для круговых диаграмм</li>
</ul>
<p>Отличный способ разгрузить собственный сервер <img src='http://korchasa.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://korchasa.ru/index.php/2007/12/google-chart-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
