<?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://job-interview.ru/articles/post/tag/%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%b8/feed" rel="self" type="application/rss+xml" />
	<link>http://job-interview.ru/articles</link>
	<description>вакансии, вопросы, статьи</description>
	<lastBuildDate>Thu, 29 Mar 2012 20:53:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ускоряем проект на Symfony через nginx+memcached</title>
		<link>http://job-interview.ru/articles/post/300</link>
		<comments>http://job-interview.ru/articles/post/300#comments</comments>
		<pubDate>Wed, 23 Feb 2011 15:11:09 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[фреймворки]]></category>

		<guid isPermaLink="false">/articles/?p=300</guid>
		<description><![CDATA[

Symfony — популярный фреймворк, использующий язык PHP, для ускорения процесса разработки web-приложений. Благодаря гибкой и продуманной структуре классов Symfony, программировать под этот фреймворк становится одним удовольствием, это действительно очень удобно.


Однако, плату за универсальность никто не отменял. И, хотя Symfony предоставляет обширные возможности для кэширования, оно не всегда спасает, особенно на нагруженных проектах и особенно на [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/img/symfony_speed_up.jpg" border="0"></p>
<p>
<strong>Symfony</strong> — популярный фреймворк, использующий <strong>язык PHP</strong>, для ускорения процесса разработки web-приложений. Благодаря гибкой и продуманной структуре классов Symfony, программировать под этот <strong>фреймворк</strong> становится одним удовольствием, это действительно очень удобно.
</p>
<p>
Однако, плату за универсальность никто не отменял. И, хотя Symfony предоставляет обширные возможности для <strong>кэширования</strong>, оно не всегда спасает, особенно на нагруженных проектах и особенно на страницах, которые состоят из часто меняющихся блоков.
</p>
<p>
В этой статье я постараюсь описать <strong>минусы кэширования</strong> в Symfony и приемы их обхода.
</p>
<p><span id="more-300"></span></p>
<p>
Представьте ситуацию, когда есть страница, на которой данные могут меняться только раз в 1-2 суток, тогда мы смело можем ее закэшировать на 24 часа. В Symfony это делается очень просто установкой параметров в файле cache.yml для модулей:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">enabled: true
with_layout: true
lifetime: <span style="">86400</span></pre></div></div>

</p>
<p>
Это означает, что раз в 24 часа при заходе одного пользователя страница будет перестраиваться, т. е. выполнять запросы к базе данных, исполнять <strong>код PHP</strong>, еще какие-то действия, после этого результат будет записан в кэш и отдан клиенту. После этого все последующие 24 часа каждый пользователь будет получать эту страницу из кэша — никаких запросов к базе, минимальное исполнение только самого необходимого кода. Красота!
</p>
<p>
И вот в один прекрасный момент руководство решает добавить на эту страницу блок с последними <em>комментариями пользователей</em>. Все, счастливая жизнь закончилась, пришло время пораскинуть мозгами. Думаю, очень многие <em>веб-разработчики</em> сталкивались с подобной историей.
</p>
<p>
Проблема в том, что блок с последними комментариями может обновиться как через минуту, так и через 2-3 часа, поэтому кэшировать всю страницу мы не можем, т. к. не понятно какое время жизни выставлять для кэша. Вообще это типичный случай, когда следует применять <strong>блочное кэширование</strong>, т. е. делим страницу на блоки (или компоненты в Symfony), каждому блоку задаем свои параметры кэширования.
</p>
<p>
Но такой тип кэширования далек от идеала, т. к. в этом случае Symfony придется выполнить большую часть своего кода. Код исполняется, как обычно, просто перед выполнением каждого блока будет проверка на наличие блока в кэше и, если он там есть и время жизни не истекло, то вместо выполнения этого блока будет просто вставлен html-код из кэша.<br />
При таком блочном кэшировании будет исполняться код Symfony при каждом <em>http-запросе</em>, кроме того, будет как минимум один <em>запрос к базе данных</em>, если пользователь авторизован &#8211;  Symfony получает данные о пользователе из базы еще до подключения блоков.
</p>
<p>
Однако, есть другой способ применения кэширования для случая, описанного выше. Для этого нам понадобится (я также привожу описание установки нужного ПО, для тех, кому оно понадобится, все примеры я проверял у себя на <em>Linux SUSE 11.3</em>):
</p>
<ul>
<li>
<strong>Nginx</strong> в качестве web-сервера</p>
<p><a href="#" onclick="jQuery('blockquote#nginx_install').toggle(); return false;" >Как установить и настроить Nginx</a></p>
<blockquote style="display: none;" id="nginx_install">
<p>
Скачиваем дистрибутив:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># wget http://sysoev.ru/nginx/nginx-0.8.54.tar.gz</span></pre></div></div>

<p>
Распаковываем его:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># tar zxf nginx-0.8.54.tar.gz</span></pre></div></div>

<p>
Переходим в созданную папку:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># cd nginx-0.8.54</span></pre></div></div>

<p>
Собираем и устанавливаем nginx:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># ./configure &amp;&amp; make &amp;&amp; make install</span></pre></div></div>

<p>
Для удобства работы с nginx создадим файл:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># touch /etc/init.d/nginx</span></pre></div></div>

<p>
И положим в него следующее содержимое:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#! /bin/bash</span>
&nbsp;
<span style="color: #666666; font-style: italic;">### BEGIN INIT INFO</span>
<span style="color: #666666; font-style: italic;"># Provides:          nginx</span>
<span style="color: #666666; font-style: italic;"># Required-Start:    $remote_fs $syslog $named $network $time</span>
<span style="color: #666666; font-style: italic;"># Required-Stop:     $remote_fs $syslog $named $network</span>
<span style="color: #666666; font-style: italic;"># Default-Start:     3 5</span>
<span style="color: #666666; font-style: italic;"># Default-Stop:      0 1 2 4 6</span>
<span style="color: #666666; font-style: italic;"># Short-Description: Start nginx at boot time</span>
<span style="color: #666666; font-style: italic;"># Description:       Enable service provided by nginx.</span>
<span style="color: #666666; font-style: italic;">### END INIT INFO</span>
&nbsp;
<span style="color: #007800;">PATH</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin:<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>bin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin
<span style="color: #007800;">NAME</span>=nginx
<span style="color: #007800;">DESC</span>=nginx
<span style="color: #007800;">PIDFILE</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>logs<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$NAME</span>.pid
<span style="color: #007800;">DAEMON</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$NAME</span>
<span style="color: #007800;">DAEMON_CONFIG</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf
&nbsp;
<span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-x</span> <span style="color: #007800;">$DAEMON</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-e</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #000000; font-weight: bold;">in</span>
  start<span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Starting <span style="color: #007800;">$DESC</span>: &quot;</span>
        <span style="color: #007800;">$DAEMON</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot; started&quot;</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
  stop<span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Stopping <span style="color: #007800;">$DESC</span>: &quot;</span>
 <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #c20cb9; font-weight: bold;">kill</span> <span style="color: #660033;">-15</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<span style="color: #000000; font-weight: bold;">`</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot; stopped&quot;</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
  restart<span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Restarting <span style="color: #007800;">$DESC</span>: &quot;</span>
 <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #c20cb9; font-weight: bold;">kill</span> <span style="color: #660033;">-15</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<span style="color: #000000; font-weight: bold;">`</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
        <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">1</span>
        <span style="color: #007800;">$DAEMON</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot; restarted&quot;</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
  reload<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Reloading <span style="color: #007800;">$DESC</span>: &quot;</span>
 <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #c20cb9; font-weight: bold;">kill</span> <span style="color: #660033;">-HUP</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$PIDFILE</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<span style="color: #000000; font-weight: bold;">`</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot; reloaded&quot;</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
  configtest<span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #007800;">$DAEMON</span> <span style="color: #660033;">-t</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
  <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #007800;">N</span>=<span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$NAME</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Usage: <span style="color: #007800;">$N</span> {start|stop|status|restart|reload|configtest}&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">2</span>
        <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
        <span style="color: #000000; font-weight: bold;">;;</span>
<span style="color: #000000; font-weight: bold;">esac</span> 
&nbsp;
<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span></pre></div></div>

<p>
Стартуем nginx:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/nginx start</span></pre></div></div>

<p>
Заходим на страницу http://localhost и видим:
</p>
<p>
«Welcome to nginx!»
</p>
<p><a href="#" onclick="jQuery('blockquote#nginx_install').toggle(); return false;" >свернуть</a></p>
</blockquote>
</li>
<li>
Фреймворк Symfony</p>
<p><a href="#" onclick="jQuery('blockquote#symfony_install').toggle(); return false;" >Как установить Symfony и настроить связку Nginx+Symfony</a></p>
<blockquote style="display: none;" id="symfony_install">
<p>
Заходим в папку, в которой будет находиться ваш проект Symfony. Далее выполняем команды:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mkdir -p lib/vendor</span>
<span style="color: #666666; font-style: italic;"># cd lib/vendor/</span>
<span style="color: #666666; font-style: italic;"># wget http://www.symfony-project.org/get/symfony-1.4.8.tgz</span>
<span style="color: #666666; font-style: italic;"># tar zxpf symfony-1.4.8.tgz</span>
<span style="color: #666666; font-style: italic;"># mv symfony-1.4.8 symfony</span>
<span style="color: #666666; font-style: italic;"># cd ../../</span>
<span style="color: #666666; font-style: italic;"># php lib/vendor/symfony/data/bin/symfony generate:project PROJECT_NAME</span>
<span style="color: #666666; font-style: italic;"># php symfony generate:app frontend</span></pre></div></div>

<p>
Мы создали наш проект Symfony, теперь нужно настроить связку Nginx+Symfony. Находим файл conf/nginx.conf и заполняем его следующим:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">worker_processes  <span style="color: #000000;">1</span>;
&nbsp;
events <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    worker_connections  <span style="color: #000000;">1024</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
http <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    include       mime.types;
    default_type  application<span style="color: #000000; font-weight: bold;">/</span>octet-stream;
&nbsp;
    log_format  main  <span style="color: #ff0000;">'$remote_addr - $remote_user [$time_local] &quot;$request&quot; '</span>
                      <span style="color: #ff0000;">'$status $body_bytes_sent &quot;$http_referer&quot; '</span>
                      <span style="color: #ff0000;">'&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;'</span>;
&nbsp;
    access_log  logs<span style="color: #000000; font-weight: bold;">/</span>access.log  main;
    error_log  logs<span style="color: #000000; font-weight: bold;">/</span>error.log info;
&nbsp;
    sendfile        on;
    keepalive_timeout  <span style="color: #000000;">65</span>;
&nbsp;
    upstream fcgi_www <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	server 127.0.0.1:<span style="color: #000000;">9000</span>;
    <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
    server <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        listen       <span style="color: #000000;">80</span>;
        server_name  localhost;
&nbsp;
        error_page   <span style="color: #000000;">500</span> <span style="color: #000000;">502</span> <span style="color: #000000;">503</span> <span style="color: #000000;">504</span>  <span style="color: #000000; font-weight: bold;">/</span>50x.html;
        location = <span style="color: #000000; font-weight: bold;">/</span>50x.html <span style="color: #7a0874; font-weight: bold;">&#123;</span>
            root   html;
        <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	root <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>web; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/web</span>
&nbsp;
	location ~ <span style="color: #ff0000;">&quot;^(/css/|/images/|/js/|/uploads/)&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    expires 3d;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	location <span style="color: #000000; font-weight: bold;">/</span>sf<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    root <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>vendor<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>data<span style="color: #000000; font-weight: bold;">/</span>web; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/lib/vendor/symfony/data/web</span>
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	location <span style="color: #000000; font-weight: bold;">/</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    fastcgi_param REQUEST_URI            <span style="color: #007800;">$request_uri</span>;
	    fastcgi_param DOCUMENT_URI           <span style="color: #007800;">$document_uri</span>;
	    fastcgi_param DOCUMENT_ROOT          <span style="color: #007800;">$document_root</span>;
	    fastcgi_param GATEWAY_INTERFACE      CGI<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.1</span>;
	    fastcgi_param SERVER_SOFTWARE        nginx<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$nginx_version</span>;
	    fastcgi_param REMOTE_ADDR            <span style="color: #007800;">$remote_addr</span>;
	    fastcgi_param REMOTE_PORT            <span style="color: #007800;">$remote_port</span>;
	    fastcgi_param SERVER_ADDR            <span style="color: #007800;">$server_addr</span>;
	    fastcgi_param SERVER_PORT            <span style="color: #007800;">$server_port</span>;
	    fastcgi_param SERVER_NAME            <span style="color: #007800;">$server_name</span>;
	    fastcgi_param SERVER_PROTOCOL        <span style="color: #007800;">$server_protocol</span>;
	    fastcgi_param CONTENT_TYPE           <span style="color: #007800;">$content_type</span>;
	    fastcgi_param CONTENT_LENGTH         <span style="color: #007800;">$content_length</span>;
	    fastcgi_param HTTP_ACCEPT_ENCODING   <span style="color: #c20cb9; font-weight: bold;">gzip</span>,deflate;
	    fastcgi_param QUERY_STRING           <span style="color: #007800;">$query_string</span>;
	    fastcgi_param REDIRECT_STATUS        <span style="color: #000000;">200</span>;
	    fastcgi_param REQUEST_METHOD         <span style="color: #007800;">$request_method</span>;
	    fastcgi_param SCRIPT_FILENAME        <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>web<span style="color: #000000; font-weight: bold;">/</span>index.php; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/web/index.php</span>
	    fastcgi_param SCRIPT_NAME            <span style="color: #000000; font-weight: bold;">/</span>index.php;
	    fastcgi_param PATH_INFO              <span style="color: #007800;">$request_uri</span>;
&nbsp;
	    fastcgi_pass  fcgi_www;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
    <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>
Теперь осталось запустить <strong>PHP в режиме FastCGI</strong>:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># php-cgi -a -b 127.0.0.1:9000 -c /etc/php5/fastcgi/php.ini</span></pre></div></div>

<p>
Если все правильно сделали, то по адресу http://localhost/ должна отобразиться страница примерно следующего содержания:
</p>
<p>
Symfony Project Created </p>
<p>Congratulations! You have successfully created your symfony project.
</p>
<p><a href="#" onclick="jQuery('blockquote#symfony_install').toggle(); return false;" >свернуть</a></p>
</blockquote>
</li>
<li>
<strong>Memcached</strong> и расширение для PHP</p>
<p><a href="#" onclick="jQuery('blockquote#memcached_install').toggle(); return false;" >Как установить memcached и расширение PHP к нему.</a></p>
<blockquote style="display: none;" id="memcached_install">
<p>
Устанавливаем memcached.
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz</span>
<span style="color: #666666; font-style: italic;"># tar zxf memcached-1.4.5.tar.gz</span>
<span style="color: #666666; font-style: italic;"># cd memcached-1.4.5/</span>
<span style="color: #666666; font-style: italic;"># ./configure</span></pre></div></div>

<p>
Если выскочит ошибка: <em>error: libevent is required.</em><br />
то устанавливаем libevent
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># cd ../</span>
<span style="color: #666666; font-style: italic;"># wget http://www.monkey.org/~provos/libevent-2.0.9-rc.tar.gz</span>
<span style="color: #666666; font-style: italic;"># tar zxf libevent-2.0.9-rc.tar.gz</span>
<span style="color: #666666; font-style: italic;"># cd libevent-2.0.9-rc/</span>
<span style="color: #666666; font-style: italic;"># ./configure</span>
<span style="color: #666666; font-style: italic;"># make &amp;&amp; make install</span></pre></div></div>

<p>
После этого продолжаем установку memcached:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># cd ../memcached-1.4.5/</span>
<span style="color: #666666; font-style: italic;"># ./configure</span>
<span style="color: #666666; font-style: italic;"># make &amp;&amp; make install</span></pre></div></div>

<p>
Устанавливаем расширение для PHP:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># pecl install memcache</span></pre></div></div>

<p>
После этого включаем расширение memcache.so в php.ini:
</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000099;">extension</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">memcache.so</span></pre></div></div>

<p>
Запускаем memcached:
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/memcached start</span></pre></div></div>

<p><a href="#" onclick="jQuery('blockquote#memcached_install').toggle(); return false;" >свернуть</a></p>
</blockquote >
</li>
</ul>
<p>
Сейчас после открытия в браузере http://localhost мы видим страницу нашего проекта на Symfony.
</p>
<p>
Итак, у нас все есть для работы, начнем ускорять наш проект. За основу берется то, что Nginx умеет обращаться к memcached по ключу и отдавать значение, которое содержится по этому ключу, в качестве ответа web-сервера.
</p>
<p>
<strong>Memcached</strong> — это демон, который хранит данные в оперативной памяти, обращаться к этим данным мы можем по определенному ключу.
</p>
<p>
Воспользуемся всеми вышеописанными возможностями memcached и nginx. В качестве ключа в memcached мы будем использовать URL-адрес страниц нашего сайта, а в качестве содержимого HTML страницы. Теперь нам нужно настроить nginx так, чтобы он при наличии в memcached значения (html) по ключу (url страницы) отдавал его сразу же в ответе клиенту, в противном случае запрос должен передаваться к Symfony, который его обрабатывает, сохраняет в memcached и отдает ответ для клиента. Таким образом, если в данный момент страница не в кэше, то его добавит в кэш Symfony, и при следующем запросе к этой странице ответ будет получен еще на стороне nginx, не доходя даже до Symfony.
</p>
<p>
<img src="/img/nginx_memcached.png" border="0">
</p>
<p>
Итак, добавим в наш проект возможность записи ответа сервера в memcached. Для этого воспользуемся механизмом фильтров в Symfony. Создадим в директории lib нашего проекта поддиректорию cache, а в ней создадим файл sfHtmlCacheFilter.class.php. Содержимое этого файла будет следующее:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> sfHtmlCacheFilter <span style="color: #000000; font-weight: bold;">extends</span> sfFilter
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$replacement</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$multi_replacement</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$pageLimit</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Метод вызывается после того, как страница полностью сформирована,
     * здесь содержимое страницы записывается в memcached, если она указана в конфиге html_cache.yml.
     *
     * @param &lt;Object&gt; $filterChain
     * @return &lt;NULL&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute <span style="color: #009900;">&#40;</span><span style="color: #000088;">$filterChain</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$filterChain</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// Если в наших конфигах прописано не использовать кэширование или мы находимся в debug-режиме, то прекращем выполнение.</span>
	<span style="color: #666666; font-style: italic;">// Здесь также проверяется код ответа - если он не равен 200, то прекращем выполнение.</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>
          <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_cache'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGetParameters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPostParameters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
          <span style="color: #339933;">||</span>
          <span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_debug'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_no_script_name'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
          <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$uri</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouting</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCurrentInternalUri</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://'</span><span style="color: #339933;">.</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// Получаем запрошенный URI - будущий ключ для memcached</span>
        <span style="color: #000088;">$webUri</span> <span style="color: #339933;">=</span> <span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUri</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$uriCacheParams</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// Получаем из конфига страницы, которые подлежат кэшированию</span>
        <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getConfig</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$item</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$uriParams</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$routing_uri</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^(.*)\?.*$/i'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'$1'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">// Сравниваем запрошенный URI с записями в конфиге</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'#^'</span><span style="color: #339933;">.</span><span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'$#'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$webUri</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$uriCacheParams</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$uriParams</span><span style="color: #339933;">;</span>
                    <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
	    <span style="color: #666666; font-style: italic;">// Если запрошенная страница есть в конфиге, то прекращаем цикл</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uriCacheParams</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$webUri</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span>_decodeUri<span style="color: #009900;">&#40;</span><span style="color: #000088;">$webUri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$uriCacheParams</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'200'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
	    <span style="color: #666666; font-style: italic;">// Записываем содержимое ответа в кэш</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">setUri</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #000088;">$webUri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uriCacheParams</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'lifetime'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Получить конфиг тэгов
     *
     * @return &lt;Array&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> getConfig<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$conf</span> <span style="color: #339933;">=</span> sfYaml<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_config_dir'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/html_cache.yml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$conf</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Вызывается из методов save() моделей,
     * удаляет из кэша все страницы, зависящие от заданной модели
     *
     * @param &lt;Object&gt; $model - объект, для которого вызывается метод save в модели
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> deleteCache<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$model_name</span> <span style="color: #339933;">=</span> <span style="color: #990000;">get_class</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getConfig</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$arUri</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Получаем страницы из конфига по этой модели</span>
        <span style="color: #000088;">$arCacheParam</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$model_name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://'</span><span style="color: #339933;">.</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// Обходим в цикле страницы, строим из них ключи для memcache</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arCacheParam</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$uri</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$param</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$multi_replacement</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$pageLimit</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$pageLimit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$attr</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$param</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$param</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #990000;">settype</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'array'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$prop</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$method</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'get'</span><span style="color: #339933;">.</span><span style="color: #000088;">$prop</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
                <span style="color: #009933; font-style: italic;">/**
                 * method_exists не работает для Doctrine,
                 * но работает для Propel, is_callable всегда будет
                 * возвращать true для Doctrine, поэтому существование
                 * метода проверяется таким образом.
                 */</span>
                try <span style="color: #009900;">&#123;</span>
                        <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">' '</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span>_decodeUri<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^pageLimit:(\d+)$/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$prop</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$pageLimit</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'pageLimit'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">range</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pageLimit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #000088;">$isCachable</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$beforeDeleteCache</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$param</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'beforeDeleteCache'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$param</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'beforeDeleteCache'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #990000;">settype</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$beforeDeleteCache</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'array'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$beforeDeleteCache</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$callback</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$method</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$callback</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$isCachable</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$isCachable</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$uri</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace_callback</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/\(.*\)/U'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'self'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'replace_attr_callback'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$multi_replacement</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">replace_multi_attr</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$multi_replacement</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$arUri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$arUri</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #000088;">$uri</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Удаляем массив страниц из memcached</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arUri</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">deleteUri</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arUri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Используется для парсинга конфига при удалении страницы из memcached
     *
     * @param &lt;Array&gt; $matches
     * @return &lt;String&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> replace_attr_callback<span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$expr</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arKeys</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$arKeys</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">'pageLimit'</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$expr</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$expr</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$multi_replacement</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$expr</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'%MULTI_REPLACEMENT_'</span><span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$multi_replacement</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'%'</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$replacement</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$expr</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Используется для парсинга конфига при удалении страницы из memcached
     *
     * @param &lt;Array&gt; $attr
     * @param &lt;String&gt; $uri
     * @param &lt;Array&gt; $arUri
     * @param &lt;Integer&gt; $key
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> replace_multi_attr<span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uri</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$arUri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$ind</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">replace_multi_attr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #339933;">,</span>
                                <span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'%MULTI_REPLACEMENT_'</span><span style="color: #339933;">.</span><span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'%'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
                                <span style="color: #000088;">$arUri</span><span style="color: #339933;">,</span>
                                <span style="color: #000088;">$key</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span> <span style="color: #339933;">==</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$attr</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$arUri</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$host</span><span style="color: #339933;">.</span><span style="color: #000088;">$uri</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Возвращает объект для работы с memcached.
     *
     * @return &lt;Object&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> getMemcache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$memcache</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Memcache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$memcache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'127.0.0.1'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">11211</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$memcache</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Записываем содержимое страницы в memcached
     *
     * @param &lt;String&gt; $uri - ключ в memcached
     * @param &lt;String&gt; $data - значение в memcached
     * @param &lt;Integer&gt; $lifetime - время жизни кэша
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static  <span style="color: #000000; font-weight: bold;">function</span> setUri<span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lifetime</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$memcache</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getMemcache</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$memcache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lifetime</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Удаляет страницу из memcached
     *
     * @param &lt;Array&gt; $arUri - массив ключей memcached,
     * которые следует удалить
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> deleteUri<span style="color: #009900;">&#40;</span><span style="color: #000088;">$arUri</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">settype</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arUri</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'array'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$memcache</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getMemcache</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arUri</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$memcache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Метод декодирует URI через rawurldecode,
     * но символ пробела оставляет в прежнем виде,
     * т.к. nginx его не декодирует в своей переменной $uri
     *
     * @param &lt;string&gt; $uri
     * @param &lt;boolean&gt; $decode
     * @return &lt;string&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> _decodeUri<span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #339933;">,</span> <span style="color: #000088;">$decode</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$decode</span> ? <span style="color: #990000;">rawurldecode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$encodedUri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'%20'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</p>
<p>
Пока нас будет интересовать только первый метод класса execute. Он вызывается после того, как закончено формирование страницы, в этом методе у нас есть возможность обратиться к содержимому страницы, еще до того, как она отправлена клиенту.
</p>
<p>
Все, что делается в методе execute — это получение текущего адреса страницы, проверка его в конфиге html_cache.yml и, если он там есть, записываем содержимое в memcached.
</p>
<p>
Теперь создадим сам конфиг html_cache.yml и положим его в папку config нашего проекта:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">Index:
  /: <span style="">&#123;</span> lifetime: <span style="">86400</span> <span style="">&#125;</span></pre></div></div>

</p>
<p>
Здесь мы задаем адрес запрошенной страницы («/» &#8211; запрос главной страницы сайта), в фигурных скобках перечислены параметры кэширования, мы указали время жизни кэша 86400 секунд, т. е. сутки. Параметр Index сейчас используется только лишь в качестве группировки адресов страниц, но здесь можно также указывать названия <strong>моделей Symfony</strong>, об этом будет рассказано ниже.
</p>
<p>
По части Symfony у нас почти все готово, осталось включить использование кэширования и активировать наш фильтр.
</p>
<p>
Чтобы включить кэширование для секции prod прописываем в файле apps/frontend/config/settings.yml (изменения выделены жирным шрифтом):
</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
</pre>
</td>
<td class="code">
<pre class="ini" style="font-family:monospace;">prod:
  .settings:
    no_script_name:         true
    <b>cache:               true</b>
    logging_enabled:        true</pre>
</td>
</tr>
</table>
</div>
<p>А теперь активируем фильтр, добавляем в файл apps/frontend/config/filters.yml пару строчек:</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
</pre>
</td>
<td class="code">
<pre class="ini" style="font-family:monospace;">rendering: ~
security:  ~
&nbsp;
# insert your own filters here
&nbsp;
<b>htmlcache:
    class: sfHtmlCacheFilter</b>
&nbsp;
cache:     ~
execution: ~</pre>
</td>
</tr>
</table>
</div>
<p>
Тем самым мы активировали наш класс-фильтр.
</p>
<p>
Теперь сбрасываем <strong>кэш Symfony</strong>:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># php symfony cache:clear</span></pre></div></div>

</p>
<p>
И заходим на страницу http://localhost/ . Если все правильно сделали главная страница нашего сайта должна оказаться в memcached, проверяем:
</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre>
</td>
<td class="code">
<pre class="html" style="font-family:monospace;"><b># telnet localhost 11211</b>
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
<b>get http://localhost/</b>
VALUE http://localhost/ 0 2026
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt;
&lt;head&gt;
&nbsp;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

&lt;title&gt;&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;/css/main.css&quot; /&gt;

&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;/sf/sf_default/css/screen.css&quot; /&gt;
&nbsp;
&lt;link rel=&quot;shortcut icon&quot; href=&quot;/favicon.ico&quot; /&gt;

&nbsp;
&lt;!--[if lt IE 7.]&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;/sf/sf_default/css/ie.css&quot; /&gt;

&lt;![endif]--&gt;
&nbsp;
&lt;/head&gt;
&lt;body&gt;
&lt;div class=&quot;sfTContainer&quot;&gt;
  &lt;a href=&quot;http://www.symfony-project.org/&quot;&gt;&lt;img alt=&quot;symfony PHP Framework&quot; class=&quot;sfTLogo&quot; src=&quot;/sf/sf_default/images/sfTLogo.png&quot; height=&quot;39&quot; width=&quot;186&quot; /&gt;&lt;/a&gt;

&lt;div class=&quot;sfTMessageContainer sfTMessage&quot;&gt;
  &lt;img alt=&quot;ok&quot; class=&quot;sfTMessageIcon&quot; src=&quot;/sf/sf_default/images/icons/ok48.png&quot; height=&quot;48&quot; width=&quot;48&quot; /&gt;  &lt;div class=&quot;sfTMessageWrap&quot;&gt;

    &lt;h1&gt;Symfony Project Created&lt;/h1&gt;
    &lt;h5&gt;Congratulations! You have successfully created your symfony project.&lt;/h5&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;dl class=&quot;sfTMessageInfo&quot;&gt;

  &lt;dt&gt;Project setup successful&lt;/dt&gt;
  &lt;dd&gt;This project uses the symfony libraries. If you see no image in this page, you may need to configure your web server so that it gains access to the &lt;code&gt;symfony_data/web/sf/&lt;/code&gt; directory.&lt;/dd&gt;
&nbsp;
  &lt;dt&gt;This is a temporary page&lt;/dt&gt;

  &lt;dd&gt;This page is part of the symfony &lt;code&gt;default&lt;/code&gt; module. It will disappear as soon as you define a &lt;code&gt;homepage&lt;/code&gt; route in your &lt;code&gt;routing.yml&lt;/code&gt;.&lt;/dd&gt;

&nbsp;
  &lt;dt&gt;What's next&lt;/dt&gt;
  &lt;dd&gt;
    &lt;ul class=&quot;sfTIconList&quot;&gt;
      &lt;li class=&quot;sfTDatabaseMessage&quot;&gt;Create your data model&lt;/li&gt;

      &lt;li class=&quot;sfTColorMessage&quot;&gt;Customize the layout of the generated templates&lt;/li&gt;
      &lt;li class=&quot;sfTLinkMessage&quot;&gt;&lt;a href=&quot;http://www.symfony-project.org/doc&quot;&gt;Learn more from the online documentation&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;

  &lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
&nbsp;
END
<b>quit</b>
Connection closed by foreign host.</pre>
</td>
</tr>
</table>
</div>
<p>
Отлично! Теперь наш проект может перед отдачей ответа клиенту записывать в memcached HTML страниц.
</p>
<p>
Ну а теперь осталось настроить nginx, чтобы он мог сам отвечать клиенту, если запрошенная страница присутствует в memcached.
</p>
<p>
Для этого нам надо добавить еще один <strong>upstream для memcached</strong> в конфиг nginx и задать правила для проксирования в него запросов. Вот каким должен получиться конфиг для Nginx (изменения выделены жирным шрифтом):
</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
</pre>
</td>
<td class="code">
<pre class="bash" style="font-family:monospace;">worker_processes  <span style="color: #000000;">1</span>;
&nbsp;
&nbsp;
events <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    worker_connections  <span style="color: #000000;">1024</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
&nbsp;
http <span style="color: #7a0874; font-weight: bold;">&#123;</span>

    include       mime.types;
    default_type  application<span style="color: #000000; font-weight: bold;">/</span>octet-stream;
&nbsp;
    log_format  main  <span style="color: #ff0000;">'$remote_addr - $remote_user [$time_local] &quot;$request&quot; '</span>
                      <span style="color: #ff0000;">'$status $body_bytes_sent &quot;$http_referer&quot; '</span>

                      <span style="color: #ff0000;">'&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;'</span>;
&nbsp;
    access_log  logs<span style="color: #000000; font-weight: bold;">/</span>access.log  main;
    error_log  logs<span style="color: #000000; font-weight: bold;">/</span>error.log info;
&nbsp;
    sendfile        on;
    keepalive_timeout  <span style="color: #000000;">65</span>;

&nbsp;
    <b>upstream memcached_backend <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	server 127.0.0.1:<span style="color: #000000;">11211</span>;
    <span style="color: #7a0874; font-weight: bold;">&#125;</span></b>
&nbsp;
    upstream fcgi_www <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	server 127.0.0.1:<span style="color: #000000;">9000</span>;
    <span style="color: #7a0874; font-weight: bold;">&#125;</span>

&nbsp;
    server <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        listen       <span style="color: #000000;">80</span>;
        server_name  localhost;
&nbsp;
        error_page   <span style="color: #000000;">500</span> <span style="color: #000000;">502</span> <span style="color: #000000;">503</span> <span style="color: #000000;">504</span>  <span style="color: #000000; font-weight: bold;">/</span>50x.html;
        location = <span style="color: #000000; font-weight: bold;">/</span>50x.html <span style="color: #7a0874; font-weight: bold;">&#123;</span>

            root   html;
        <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	root <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>web; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/web</span>
&nbsp;

	location ~ <span style="color: #ff0000;">&quot;^(/css/|/images/|/js/|/uploads/)&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    expires 3d;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	location <span style="color: #000000; font-weight: bold;">/</span>sf<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    root <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>vendor<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>data<span style="color: #000000; font-weight: bold;">/</span>web; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/lib/vendor/symfony/data/web</span>

	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	location <span style="color: #000000; font-weight: bold;">/</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    fastcgi_param REQUEST_URI            <span style="color: #007800;">$request_uri</span>;
	    fastcgi_param DOCUMENT_URI           <span style="color: #007800;">$document_uri</span>;
	    fastcgi_param DOCUMENT_ROOT          <span style="color: #007800;">$document_root</span>;
	    fastcgi_param GATEWAY_INTERFACE      CGI<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.1</span>;
	    fastcgi_param SERVER_SOFTWARE        nginx<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$nginx_version</span>;
	    fastcgi_param REMOTE_ADDR            <span style="color: #007800;">$remote_addr</span>;
	    fastcgi_param REMOTE_PORT            <span style="color: #007800;">$remote_port</span>;
	    fastcgi_param SERVER_ADDR            <span style="color: #007800;">$server_addr</span>;
	    fastcgi_param SERVER_PORT            <span style="color: #007800;">$server_port</span>;
	    fastcgi_param SERVER_NAME            <span style="color: #007800;">$server_name</span>;
	    fastcgi_param SERVER_PROTOCOL        <span style="color: #007800;">$server_protocol</span>;
	    fastcgi_param CONTENT_TYPE           <span style="color: #007800;">$content_type</span>;
	    fastcgi_param CONTENT_LENGTH         <span style="color: #007800;">$content_length</span>;
	    fastcgi_param HTTP_ACCEPT_ENCODING   <span style="color: #c20cb9; font-weight: bold;">gzip</span>,deflate;
	    fastcgi_param QUERY_STRING           <span style="color: #007800;">$query_string</span>;
	    fastcgi_param REDIRECT_STATUS        <span style="color: #000000;">200</span>;
	    fastcgi_param REQUEST_METHOD         <span style="color: #007800;">$request_method</span>;
	    fastcgi_param SCRIPT_FILENAME        <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>web<span style="color: #000000; font-weight: bold;">/</span>index.php; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/web/index.php</span>

	    fastcgi_param SCRIPT_NAME            <span style="color: #000000; font-weight: bold;">/</span>index.php;
	    fastcgi_param PATH_INFO              <span style="color: #007800;">$request_uri</span>;
&nbsp;
            <b><span style="color: #666666; font-style: italic;"># Если это POST-запрос, то передаем обработку сразу в Symfony</span>
	    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">$request_method</span> = POST<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>

		fastcgi_pass  fcgi_www;
		<span style="color: #7a0874; font-weight: bold;">break</span>;
	    <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
           <span style="color: #666666; font-style: italic;"># Если на предыдущем шаге мы не вышли из location'а, то это GET-запрос.</span>
           <span style="color: #666666; font-style: italic;"># Устанавливаем ключ для memcached, по которому будем искать значение</span>
	    <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">$memcached_key</span> <span style="color: #ff0000;">&quot;http://<span style="color: #007800;">$host</span><span style="color: #007800;">$uri</span>&quot;</span>;
           <span style="color: #666666; font-style: italic;"># Задаем upstream для memcached</span>

	    memcached_pass  memcached_backend;
&nbsp;
           <span style="color: #666666; font-style: italic;"># Устанавливаем тип содержимого, полученного от memcached, у нас хранится HTML</span>
	    default_type text<span style="color: #000000; font-weight: bold;">/</span>html;
           <span style="color: #666666; font-style: italic;"># Указываем nginx'у переходить в именованный location @symfony в случае отсутствия ключа </span>
           <span style="color: #666666; font-style: italic;"># в memcached или в случае возникновении ошибки при запросе к memcached</span>
	    proxy_intercept_errors  on;
	    error_page <span style="color: #000000;">404</span> <span style="color: #000000;">502</span> = <span style="color: #000000; font-weight: bold;">@</span>symfony;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>

&nbsp;
       <span style="color: #666666; font-style: italic;"># Здесь описан именованный location, куда nginx переходит в случае отсутствия ключа или                                          </span>
       <span style="color: #666666; font-style: italic;"># возникновении ошибки при обращении к memcached. Здесь просто перечислены параметры </span>
       <span style="color: #666666; font-style: italic;"># fastcgi так же, как было сделано выше.</span>
	location <span style="color: #000000; font-weight: bold;">@</span>symfony <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	    fastcgi_param REQUEST_URI            <span style="color: #007800;">$request_uri</span>;
	    fastcgi_param DOCUMENT_URI           <span style="color: #007800;">$document_uri</span>;
	    fastcgi_param DOCUMENT_ROOT          <span style="color: #007800;">$document_root</span>;
	    fastcgi_param GATEWAY_INTERFACE      CGI<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.1</span>;
	    fastcgi_param SERVER_SOFTWARE        nginx<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$nginx_version</span>;
	    fastcgi_param REMOTE_ADDR            <span style="color: #007800;">$remote_addr</span>;
	    fastcgi_param REMOTE_PORT            <span style="color: #007800;">$remote_port</span>;
	    fastcgi_param SERVER_ADDR            <span style="color: #007800;">$server_addr</span>;
	    fastcgi_param SERVER_PORT            <span style="color: #007800;">$server_port</span>;
	    fastcgi_param SERVER_NAME            <span style="color: #007800;">$server_name</span>;
	    fastcgi_param SERVER_PROTOCOL        <span style="color: #007800;">$server_protocol</span>;
	    fastcgi_param CONTENT_TYPE           <span style="color: #007800;">$content_type</span>;
	    fastcgi_param CONTENT_LENGTH         <span style="color: #007800;">$content_length</span>;
	    fastcgi_param HTTP_ACCEPT_ENCODING   <span style="color: #c20cb9; font-weight: bold;">gzip</span>,deflate;
	    fastcgi_param QUERY_STRING           <span style="color: #007800;">$query_string</span>;
	    fastcgi_param REDIRECT_STATUS        <span style="color: #000000;">200</span>;
	    fastcgi_param REQUEST_METHOD         <span style="color: #007800;">$request_method</span>;
	    fastcgi_param SCRIPT_FILENAME        <span style="color: #000000; font-weight: bold;">/</span>srv<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>web<span style="color: #000000; font-weight: bold;">/</span>index.php; <span style="color: #666666; font-style: italic;">#%ПУТЬ_ДО_ВАШЕГО_ПРОЕКТА%/web/index.php</span>

	    fastcgi_param SCRIPT_NAME            <span style="color: #000000; font-weight: bold;">/</span>index.php;
	    fastcgi_param PATH_INFO              <span style="color: #007800;">$request_uri</span>;
	    fastcgi_pass  fcgi_www;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span></b>
    <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre>
</td>
</tr>
</table>
</div>
<p>
Теперь проверяем нет ли ошибок в конфигах Nginx после внесения изменений:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/nginx configtest</span>
the configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf syntax is ok
configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf <span style="color: #7a0874; font-weight: bold;">test</span> is successful</pre></div></div>

</p>
<p>
И говорим Nginx, чтобы он перечитал конфиг:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/nginx reload</span>
Reloading nginx:  reloaded</pre></div></div>

</p>
<p>
Проверяем! Заходим на страницу http://localhost/ , она у нас уже должна лежать в memcached. Лично я в своем браузере Mozilla Firefox даже на примере такой простой странички вижу, что она стала загружаться гораздо быстрее!
</p>
<p>
Но не будем доверять всему тому, что видим. Проведем небольшой бенчмарк, в этом нам поможет утилита <strong>ab2</strong> — инструмент от разработчиков <strong>web-сервера Apache</strong>.
</p>
<p>
Сначала закомментируем наши <strong>настройки в Nginx</strong>, чтобы он перенаправлял все на Symfony.
</p>
<p>
Вносим следующие изменения в наш конфиг для Nginx, начиная с 71-й строки:
</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
</pre>
</td>
<td class="code">
<pre class="bash" style="font-family:monospace;">	    fastcgi_param SCRIPT_NAME            <span style="color: #000000; font-weight: bold;">/</span>index.php;
	    fastcgi_param PATH_INFO              <span style="color: #007800;">$request_uri</span>;<b>
	    fastcgi_pass  fcgi_www;
&nbsp;
<span style="color: #666666; font-style: italic;">#	    if ($request_method = POST) {</span>

<span style="color: #666666; font-style: italic;">#		fastcgi_pass  fcgi_www;</span>
<span style="color: #666666; font-style: italic;">#		break;</span>
<span style="color: #666666; font-style: italic;">#	    }</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#	    set $memcached_key &quot;http://$host$uri&quot;;</span>
<span style="color: #666666; font-style: italic;">#	    memcached_pass  memcached_backend;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#	    default_type text/html;</span>
<span style="color: #666666; font-style: italic;">#	    proxy_intercept_errors  on;</span>

<span style="color: #666666; font-style: italic;">#	    error_page 404 502 = @symfony;</span></b>
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	location <span style="color: #000000; font-weight: bold;">@</span>symfony <span style="color: #7a0874; font-weight: bold;">&#123;</span></pre>
</td>
</tr>
</table>
</div>
</pre>
<p>
Затем стандартные команды:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/nginx configtest</span>
the configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf syntax is ok
configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf <span style="color: #7a0874; font-weight: bold;">test</span> is successful
<span style="color: #666666; font-style: italic;"># /etc/init.d/nginx reload</span>
Reloading nginx:  reloaded</pre></div></div>

</p>
<p>
И запускаем утилиту от Apache,  отправим на наш сайт 1000 запросов, причем 10 будем выполнять параллельно:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># ab2 -n 1000 -c 10 http://127.0.0.1:80/</span>
This is ApacheBench, Version <span style="color: #000000;">2.3</span> <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $<span style="color: #000000; font-weight: bold;">&gt;</span>
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http:<span style="color: #000000; font-weight: bold;">//</span>www.zeustech.net<span style="color: #000000; font-weight: bold;">/</span>
Licensed to The Apache Software Foundation, http:<span style="color: #000000; font-weight: bold;">//</span>www.apache.org<span style="color: #000000; font-weight: bold;">/</span>
&nbsp;
Benchmarking 127.0.0.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Completed <span style="color: #000000;">100</span> requests
Completed <span style="color: #000000;">200</span> requests
Completed <span style="color: #000000;">300</span> requests
Completed <span style="color: #000000;">400</span> requests
Completed <span style="color: #000000;">500</span> requests
Completed <span style="color: #000000;">600</span> requests
Completed <span style="color: #000000;">700</span> requests
Completed <span style="color: #000000;">800</span> requests
Completed <span style="color: #000000;">900</span> requests
Completed <span style="color: #000000;">1000</span> requests
Finished <span style="color: #000000;">1000</span> requests
&nbsp;
Server Software:        nginx<span style="color: #000000; font-weight: bold;">/</span>0.8.54
Server Hostname:        127.0.0.1
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          <span style="color: #000000; font-weight: bold;">/</span>
Document Length:        <span style="color: #000000;">2026</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">10</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">26.412</span> seconds
Complete requests:      <span style="color: #000000;">1000</span>
Failed requests:        <span style="color: #000000;">646</span>
   <span style="color: #7a0874; font-weight: bold;">&#40;</span>Connect: <span style="color: #000000;">0</span>, Receive: <span style="color: #000000;">0</span>, Length: <span style="color: #000000;">646</span>, Exceptions: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Write errors:           <span style="color: #000000;">0</span>
Non-2xx responses:      <span style="color: #000000;">646</span>
Total transferred:      <span style="color: #000000;">1142110</span> bytes
HTML transferred:       <span style="color: #000000;">964622</span> bytes
Requests per second:    <span style="color: #000000;">37.86</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #666666; font-style: italic;">#/sec] (mean)</span>
Time per request:       <span style="color: #000000;">264.116</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">26.412</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">42.23</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes<span style="color: #000000; font-weight: bold;">/</span>sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+<span style="color: #000000; font-weight: bold;">/</span>-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">0.1</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">1</span>
Processing:     <span style="color: #000000;">0</span>  <span style="color: #000000;">264</span> <span style="color: #000000;">349.9</span>      <span style="color: #000000;">3</span>     <span style="color: #000000;">827</span>
Waiting:        <span style="color: #000000;">0</span>  <span style="color: #000000;">264</span> <span style="color: #000000;">349.9</span>      <span style="color: #000000;">3</span>     <span style="color: #000000;">810</span>
Total:          <span style="color: #000000;">1</span>  <span style="color: #000000;">264</span> <span style="color: #000000;">349.9</span>      <span style="color: #000000;">3</span>     <span style="color: #000000;">827</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">3</span>
  <span style="color: #000000;">66</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">703</span>
  <span style="color: #000000;">75</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">713</span>
  <span style="color: #000000;">80</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">716</span>
  <span style="color: #000000;">90</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">748</span>
  <span style="color: #000000;">95</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">788</span>
  <span style="color: #000000;">98</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">790</span>
  <span style="color: #000000;">99</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">796</span>
 <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span>    <span style="color: #000000;">827</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

</p>
<p>
У меня после таких тестов отваливался через некоторое время <strong>fastcgi</strong>. Во время выполнения ab2 попробуйте проверить загрузку страницы в браузере — можно наблюдать постепенное нарастание тормозов при загрузке страницы.
</p>
<p>
Итак, если вас настигла беда с fastcgi, как и у меня, то запускаем его снова:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php-cgi <span style="color: #660033;">-a</span> <span style="color: #660033;">-b</span> 127.0.0.1:<span style="color: #000000;">9000</span> <span style="color: #660033;">-c</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>php5<span style="color: #000000; font-weight: bold;">/</span>fastcgi<span style="color: #000000; font-weight: bold;">/</span>php.ini</pre></div></div>

</p>
<p>
Далее убираем наши комментарии, сделанные перед запуском теста, релоадим nginx и запускаем ab2 с теми же параметрами:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /etc/init.d/nginx configtest</span>
the configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf syntax is ok
configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>conf<span style="color: #000000; font-weight: bold;">/</span>nginx.conf <span style="color: #7a0874; font-weight: bold;">test</span> is successful
<span style="color: #666666; font-style: italic;"># /etc/init.d/nginx reload</span>
Reloading nginx:  reloaded
<span style="color: #666666; font-style: italic;"># ab2 -n 1000 -c 10 http://127.0.0.1:80/</span>
This is ApacheBench, Version <span style="color: #000000;">2.3</span> <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #007800;">$Revision</span>: <span style="color: #000000;">655654</span> $<span style="color: #000000; font-weight: bold;">&gt;</span>
Copyright <span style="color: #000000;">1996</span> Adam Twiss, Zeus Technology Ltd, http:<span style="color: #000000; font-weight: bold;">//</span>www.zeustech.net<span style="color: #000000; font-weight: bold;">/</span>
Licensed to The Apache Software Foundation, http:<span style="color: #000000; font-weight: bold;">//</span>www.apache.org<span style="color: #000000; font-weight: bold;">/</span>
&nbsp;
Benchmarking 127.0.0.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>be patient<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Completed <span style="color: #000000;">100</span> requests
Completed <span style="color: #000000;">200</span> requests
Completed <span style="color: #000000;">300</span> requests
Completed <span style="color: #000000;">400</span> requests
Completed <span style="color: #000000;">500</span> requests
Completed <span style="color: #000000;">600</span> requests
Completed <span style="color: #000000;">700</span> requests
Completed <span style="color: #000000;">800</span> requests
Completed <span style="color: #000000;">900</span> requests
Completed <span style="color: #000000;">1000</span> requests
Finished <span style="color: #000000;">1000</span> requests
&nbsp;
Server Software:        nginx<span style="color: #000000; font-weight: bold;">/</span>0.8.54
Server Hostname:        127.0.0.1
Server Port:            <span style="color: #000000;">80</span>
&nbsp;
Document Path:          <span style="color: #000000; font-weight: bold;">/</span>
Document Length:        <span style="color: #000000;">2026</span> bytes
&nbsp;
Concurrency Level:      <span style="color: #000000;">10</span>
Time taken <span style="color: #000000; font-weight: bold;">for</span> tests:   <span style="color: #000000;">0.337</span> seconds
Complete requests:      <span style="color: #000000;">1000</span>
Failed requests:        <span style="color: #000000;">0</span>
Write errors:           <span style="color: #000000;">0</span>
Total transferred:      <span style="color: #000000;">2170000</span> bytes
HTML transferred:       <span style="color: #000000;">2026000</span> bytes
Requests per second:    <span style="color: #000000;">2971.65</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #666666; font-style: italic;">#/sec] (mean)</span>
Time per request:       <span style="color: #000000;">3.365</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Time per request:       <span style="color: #000000;">0.337</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>ms<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mean, across all concurrent requests<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Transfer rate:          <span style="color: #000000;">6297.35</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>Kbytes<span style="color: #000000; font-weight: bold;">/</span>sec<span style="color: #7a0874; font-weight: bold;">&#93;</span> received
&nbsp;
Connection Times <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              min  mean<span style="color: #7a0874; font-weight: bold;">&#91;</span>+<span style="color: #000000; font-weight: bold;">/</span>-sd<span style="color: #7a0874; font-weight: bold;">&#93;</span> median   max
Connect:        <span style="color: #000000;">0</span>    <span style="color: #000000;">0</span>   <span style="color: #000000;">0.4</span>      <span style="color: #000000;">0</span>       <span style="color: #000000;">3</span>
Processing:     <span style="color: #000000;">1</span>    <span style="color: #000000;">3</span>   <span style="color: #000000;">0.6</span>      <span style="color: #000000;">3</span>       <span style="color: #000000;">5</span>
Waiting:        <span style="color: #000000;">0</span>    <span style="color: #000000;">3</span>   <span style="color: #000000;">0.6</span>      <span style="color: #000000;">3</span>       <span style="color: #000000;">4</span>
Total:          <span style="color: #000000;">1</span>    <span style="color: #000000;">3</span>   <span style="color: #000000;">0.5</span>      <span style="color: #000000;">3</span>       <span style="color: #000000;">6</span>
&nbsp;
Percentage of the requests served within a certain <span style="color: #000000; font-weight: bold;">time</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  <span style="color: #000000;">50</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">3</span>
  <span style="color: #000000;">66</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">3</span>
  <span style="color: #000000;">75</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
  <span style="color: #000000;">80</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
  <span style="color: #000000;">90</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
  <span style="color: #000000;">95</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
  <span style="color: #000000;">98</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
  <span style="color: #000000;">99</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">4</span>
 <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span>      <span style="color: #000000;">6</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>longest request<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

</p>
<p>
Тут даже говорить нечего, все сказано в первом и втором выводах ab2. Достаточно взглянуть хотя бы на параметр «Time taken for tests», который показывает общее время проведения тестов. В первом случае он равен  26.412 секунд, во втором - 0.337 секунд. Прирост производительности почти в 80 раз!
</p>
<p>
Конечно, тестирование на локальном компьютере — это не есть тестирование в условиях, приближенных к реальным, однако какое-то представление оно все же дает.
</p>
<p>
А теперь вернемся к примеру, который был описан в самом начале статьи. Есть страница с постоянным контентом и есть блок с последними комментариями.
</p>
<p>
Как кэширование, которое мы только что внедрили в Symfony, поможет нам с кэшированием такой страницы? Пока никак. Наш кэш живет только какое-то определенное время, указанное в параметре lifetime, поэтому блок с комментариями будет обновляться только, когда истечет время жизни кэша. Но нас это не устраивает, нужно, чтобы страница обновлялась каждый раз после того, как добавился комментарий. Хорошо бы после добавления комментария удалять из кэша страницу.
</p>
<p>
Зададимся вопросом: «В какой момент у нас обычно должен обновляться кэш?». Обычно в момент, когда что-то меняется в базе данных. При чем, если изменения производятся в таблице, где хранятся комментарии, то обновляться должны страницы, где выводятся блоки, связанные с комментариями.
</p>
<p>
Для начала подключим к нашему проекту на Symfony <strong>базу данных</strong>. Не имеет значения какую базу данных использовать. Если вы знакомы с Symfony, то без труда сможете подключить свою базу данных. В своих же примерах я использую <em>MySQL</em>, <em>пользователь root</em> с паролем secretpass, имя базы данных — symfony.
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mysqladmin -uroot -psecretpass create symfony</span>
<span style="color: #666666; font-style: italic;"># php symfony configure:database &quot;mysql:host=localhost;dbname=symfony&quot; root secretpass</span></pre></div></div>

</p>
<p>
Теперь опишем нашу будущую базу данных в Symfony, для этого отредактируем файл config/doctrine/schema.yml:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">Comment:
  columns:
    text: <span style="">&#123;</span> type: string<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, notnull: true <span style="">&#125;</span></pre></div></div>

</p>
<p>
Далее воспользуемся готовыми инструментами Symfony и сгенерируем код для моделей, SQL для базы данных.
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># php symfony doctrine:build --model</span>
<span style="color: #666666; font-style: italic;"># php symfony doctrine:build --sql</span>
<span style="color: #666666; font-style: italic;"># php symfony doctrine:insert-sql</span></pre></div></div>

</p>
<p>
Последняя команда выполняет SQL, чтобы создать необходимые <em>таблицы в базе данных</em>. Вместо этих трех команд можно было бы выполнить php symfony doctrine:build —all, которая выполняет те же 3 действия, но за один раз.
</p>
<p>
Теперь сгенерируем стандартную функциональность для добавления, удаления, редактирования и просмотра списка объектов модели:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># php symfony doctrine:generate-module --with-show --non-verbose-templates frontend comment Comment</span></pre></div></div>

</p>
<p>
Здесь мы говорим сгенерировать код для нового модуля comment, код генерируется для существующей модели Comment.
</p>
<p>
Далее необходимо переопределить метод save() для моделей, участвующих в кэшировании. У нас это одна модель Comment, поэтому открываем файл lib/model/doctrine/Comment.class.php и добавляем в класс Comment метод save():
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Comment <span style="color: #000000; font-weight: bold;">extends</span> BaseComment
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span>Doctrine_Connection <span style="color: #000088;">$conn</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        sfHtmlCacheFilter<span style="color: #339933;">::</span><span style="color: #004000;">deleteCache</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</p>
<p>
Мы добавили метод save(), который переопределяет метод save() класса <strong>Doctrine_Record</strong>. В нашем методе мы вызываем метод save() родительского класса, которым и окажется Doctrine_Record::save().
</p>
<p>
Далее вызывается метод нашего класса-фильтра sfHtmlCacheFilter::deleteCache($this), которому в качестве параметра передается сохраняемый объект. Таким образом, этот новый метод не делает ничего нового, кроме как добавляется метод для очистки кэша при каждом сохранении объекта.
</p>
<p>
Удаляем кэш Symfony, чтобы наши изменения вступили в силу.
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># php symfony cache:clear</span></pre></div></div>

</p>
<p>
Все, теперь зайдем по адресу http://localhost/comment и увидим сгенерированную Symfony страницу. Нажимаем на ссылку «New», добавляем первую запись, возвращаемся назад к списку и видим только что добавленный комментарий.
</p>
<p>
Выше уже упоминалось, что в конфиге html_cache.yml можно прописывать зависимости страниц от моделей. Пришло время рассказать об этом подробнее.<br />
Настройки в файле html_cache.yml используется следующим образом.
</p>
<p>
Перед отдачей любой страницы клиенту проверяется наличие адреса этой страницы в конфиге. Если он есть, то происходит запись содержимого страницы в кэш.<br />
При сохранении модели вызывается метод класса-фильтра для удаления из кэша страниц, зависящих от текущей модели. Модели перечислены, как элементы первого уровня, на втором уровне перечислены зависящие от этих моделей адреса страниц.
</p>
<p>
Сейчас у нас в файле html_cache.yml на первом уровне прописана несуществующая модель Index, на втором уровне прописана главная страница. Т. к. модели Index у нас нет, то эта настройка просто говорит о том, что неоходимо записывать в кэш содержимое главной страницы, но никакого удаления ее из кэша не происходит.
</p>
<p>
Для такой главной страницы это и не нужно, т. к. там выводится всегда одна и та же информация. А вот со страницей списка комментариев ситуация иная — если для нее мы применяем кэширование, то необходимо удалять кэш этой страницы при каждом добавлении комментария.
</p>
<p>
Добавим такую настройку. Страница со списком комментариев располагается по адресу http://localhost/comment. Добавляем в файл config/html_cache.yml следующую запись:
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">Comment:
  /comment: <span style="">&#123;</span> lifetime: <span style="">86400</span> <span style="">&#125;</span></pre></div></div>

</p>
<p>
Теперь наша страница  http://localhost/comment будет отдаваться клиенту еще на стороне nginx при наличии ее в кэше. В противном случае nginx передаст управление Symfony, который сформирует и запишет содержимое страницы в кэш.
</p>
<p>
Таким образом, мы организовали зависимость страниц от изменяющихся моделей — при изменении определенных моделей очищается кэш зависящих от этих моделей страниц.
</p>
<p>
В файле html_cache.yml можно использовать <strong>регулярные выражения</strong>, а также подставлять в адреса страниц результаты выполнения методов объектов. Применим кэширование к детальным страницам комментариев, которые располагаются по адресам вида - http://localhost/comment/show/id/1 .
</p>
<p>
Добавим к модели Comment следующую зависимость:
</p>
<div class="geshi_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
</pre>
</td>
<td class="code">
<pre class="ini" style="font-family:monospace;">Comment:
  /comment: <span style="">&#123;</span> lifetime: <span style="">86400</span> <span style="">&#125;</span><b>
  /comment/show/id/<span style="">&#40;</span>\d+<span style="">&#41;</span>: <span style="">&#123;</span> lifetime: <span style="">86400</span>, attributes: <span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>Id<span style="">&#93;</span></span> <span style="">&#125;</span></pre>
<p></b></p>
</td>
</tr>
</table>
</div>
<p>
Здесь мы указали в адресе регулярное выражение, которое пропускает только числовые значения ID комментариев. Мы также указали новый параметр attributes, который является массивом. В этом массиве объявляются методы модели, возвращаемые значения которых будут подставлены по порядку вместо регулярных выражений, заключенных в скобки. Причем методы могут возвращать не только обычные значения, но и массивы, в этом случае для удаления из кэша будет сформирован массив адресов страниц.
</p>
<p>
В данном примере вместо регулярного выражения (\d+) будет подставлен результат вызова метода getId() для объекта модели Comment. Это справедливо только при сохранении объекта и <strong>удалении кэша</strong> для него. При добавлении страницы в кэш будет произведено лишь сравнение текущего адреса страницы с регулярным выражением /comment/show/id/(\d+) и, если адрес пройдет проверку, то страница добавится в кэш.
</p>
<p>
После произведенных изменений в файле html_cache.yml страницы вида  http://localhost/comment/show/id/1 постигнет участь предыдущих рассматриваемых страниц — они будут писаться в кэш.
</p>
<p>
Помимо параметров lifetime и attributes можно использовать параметр beforeDeleteCache, в который передается название метода модели (полное название). Этот метод должен возвращать true или false. При получении false кэш для записи с этим параметром удаляться не будет.
</p>
<p>
На этом все. Теперь наш проект на Symfony стал не просто быстрым, а мегабыстрым. Ответы клиент получает не от php-скриптов на сервере и даже не с диска, а из памяти сервера.
</p>
<p>
Спасибо за внимание! Чтобы ваши сайты всегда летали!
</p>
<p></p>
<p><b>UPD:</b> Спасибо Sergei за <a href="#350">найденную ошибку</a>. Все описанное работало только с латинскими буквами в url'е, но не работало с русскими. Внесены нужные изменения в класс-фильтр для Symfony, а также в конфиге nginx в качестве ключа для memcached теперь используется переменная $uri, а не $request_uri</p>
]]></content:encoded>
			<wfw:commentRss>http://job-interview.ru/articles/post/300/feed</wfw:commentRss>
		<slash:comments>557</slash:comments>
		</item>
	</channel>
</rss>
