<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="http://feedproxy.google.com/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feedproxy.google.com/~d/styles/itemcontent.css"?><rss 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:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">

<channel>
	<title>WEB рукоделие</title>
	
	<link>http://www.handmadesite.net</link>
	<description>Какой механизм?! Все вручную!</description>
	<pubDate>Sun, 28 Dec 2008 01:53:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<geo:lat>55.778552</geo:lat><geo:long>37.548244</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feedproxy.google.com/handmadesite" type="application/rss+xml" /><item>
		<title>Рождественский пирог: долгожданный релиз CakePHP 1.2</title>
		<link>http://www.handmadesite.net/2008/12/christmas-cake-cakephp-12-release/</link>
		<comments>http://www.handmadesite.net/2008/12/christmas-cake-cakephp-12-release/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 01:53:20 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=154</guid>
		<description><![CDATA[К Рождеству разработчики CakePHP выпустили долгожданный релиз фреймворка версии 1.2. Разработка этой версии длилась почти 2 года и, надо сказать, пирог получился отменный! Что больше всего нравится лично мне:
	Behaviors &#8212; расширение функционала моделей. PHP досих пор страдает отсутствием множественного наследования и behaviors в CakePHP очень технично эту проблему решают.<br />	Тесты &#8212; CakePHP интегрируется с пакетом SimpleTest [...]]]></description>
			<content:encoded><![CDATA[<p>К Рождеству разработчики CakePHP выпустили долгожданный релиз фреймворка версии 1.2. Разработка этой версии длилась почти 2 года и, надо сказать, пирог получился отменный! Что больше всего нравится лично мне:
<ul><br />	<li>Behaviors &mdash; расширение функционала моделей. PHP досих пор страдает отсутствием множественного наследования и behaviors в CakePHP очень технично эту проблему решают.</li>
	<li>Тесты &mdash; CakePHP интегрируется с <a href="http://www.simpletest.org/">пакетом SimpleTest</a> и позволяет создавать тесты для всех методов контроллеров и моделей. Это очень важно при разработке</li>
	<li>Консольная утилита, позволяющая создавать типичные модели, контроллеры, каркас приложения и т.д. Очень удобная, на мой взгляд.</li>
	<li>Законченная и понятная концепция плагинов. Части приложения, более-менее самостоятельные, можно изготавливать в виде плагинов и использовать в разных проектах.</li>
</ul>
Это, конечно, не полный список &laquo;вкусностей&raquo;, а только то, что сразу вспомнилось. В целом, по сравнению с версией 1.1 фреймворк сильно изменился в лучшую сторону. Стал более понятным и удобным.</p><span id="more-154"></span>
<p>Авторы не удержались от добавления новых возможностей и, по сравнению с <a href="http://www.handmadesite.net/2008/12/lastest-lastest-cakephp-release-candidate/">недавно вышедшим RC4</a>, немного расширили функционал валидаторов у моделей. Теперь данные для поля, содержащего URL, можно проверять в режиме &#8217;strict&#8217;: тогда ошибка проверки будет возникать, если не указан протокол. Т.е. &#8216;http://example.com&#8217; &mdash; правильно, а &#8216;example.com&#8217; &mdash; ошибочно. Чтобы воспользоваться этой возможностью надо указать примерно такое правило проверки:</p>
<pre><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #000088;">$validate</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'website'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'rule'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'url'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
</pre></pre></pre><p>Т.е. поле &#8216;<em>website</em>&#8216; должно содержать правильный URL, а второй параметр (<em>true</em>) как раз и указывает на обязательность наличия протокола (http://, ftp:// и т.п.)</p><p>Увы, <a href="http://book.cakephp.org/">документацию на версию 1.2</a>, нельзя назвать всеобъемлющей. Это скорее обзор для начинающих, то, что по-английски называют <em>User&#8217;s Guide</em>. <a href="http://api.cakephp.org/">Документация для разработчика, Developer&#8217;s Guide</a>, доступна только на языке PHP.</p><p>Очень неудобно отсутствие исключений (exceptions). Это, видимо, плата за совместимость с PHP4. Работу с исключениями можно дописать самостоятельно, но хочется, чтоб поддержка их была и в ядре. Будем надеятся, что в 2.0 они появятся, потому как поддержки PHP4 в следующей версии уже не будет.</p><p style="color:white">34fb6db9-e173-400b-9ad4-ac8c0fa45e49</p>
<p><a href="http://feedads.googleadservices.com/~a/2BZMxd-yr2mULLPDq5iJqK6P2bY/a"><img src="http://feedads.googleadservices.com/~a/2BZMxd-yr2mULLPDq5iJqK6P2bY/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=sYvnNqCA"><img src="http://feedproxy.google.com/~f/handmadesite?i=sYvnNqCA" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=SWSfwpnE"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=iN0MuHPI"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=Hr3eG3qc"><img src="http://feedproxy.google.com/~f/handmadesite?i=Hr3eG3qc" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/christmas-cake-cakephp-12-release/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Производительность фреймворков — CodeIgniter уходит в отрыв</title>
		<link>http://www.handmadesite.net/2008/12/php-frameworks-perfomance-test/</link>
		<comments>http://www.handmadesite.net/2008/12/php-frameworks-perfomance-test/#comments</comments>
		<pubDate>Fri, 26 Dec 2008 00:48:54 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[codeigniter]]></category>

		<category><![CDATA[symfony]]></category>

		<category><![CDATA[yii]]></category>

		<category><![CDATA[zendframework]]></category>

		<category><![CDATA[zf]]></category>

		<category><![CDATA[производительность]]></category>

		<category><![CDATA[сравнение]]></category>

		<category><![CDATA[тест]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=129</guid>
		<description><![CDATA[Хуан Бассо протестировал несколько современных версий популярных PHP-фреймворков. Увы, оба два моих предпочитаемых: CakePHP и ZendFramework слили CodeIgniter&#8217;у по полной программе. В лидерах оказался и неизвестный мне Yii.Автор тестировал производительность 3-х приложений: стандартного &#8216;Hello, world&#8217;, запрос к базе данных на выборку 10 записей и запрос на выборку 1000 записей. Для тестирования использовался, как я понял, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.cakephp-brasil.org/2008/12/25/benchmarks-entre-frameworks-php/">Хуан Бассо протестировал несколько современных версий популярных PHP-фреймворков</a>. Увы, оба два моих предпочитаемых: CakePHP и ZendFramework слили CodeIgniter&#8217;у по полной программе. В лидерах оказался и неизвестный мне Yii.</p><p>Автор тестировал производительность 3-х приложений: стандартного &#8216;Hello, world&#8217;, запрос к базе данных на выборку 10 записей и запрос на выборку 1000 записей. Для тестирования использовался, как я понял, массовый бразильский сервер: Debian, PHP 5.2.0, MySQL 5.0, Apache 2.2.3, процессор Xeon 2.66G и 256 мегабайт оперативки. Всяческие хитрости типа Memcache были отключены и не использовались, все приложения запускались, как принято говорить, в production режиме, т.е. с отключенной отладочной информацией и тому подобное.</p><p>Тестовые приложения для каждого фреймворка были разработаны на основе документации, а не взяты из готовых примеров. Это, конечно, может наложить некоторый отпечаток, поскольку вряд-ли Хуан одинаково хорошо разбирается во всех пакетах, зато такой подход наглядно демонстрирует то, что можно получить, если завтра принять решение о смене фреймворка. :-)</p><p>В тесте принимали участие самые свежие версии:
<ul>	<li>CakePHP 1.1.20 &mdash; самый свежий релиз версии 1.1</li>
	<li><a href="http://www.handmadesite.net/2008/12/lastest-lastest-cakephp-release-candidate/">CakePHP 1.2 RC4 &mdash; недавно вышедший наипоследнийший Release Candidate</a></li>	<li>CodeIgniter 1.7.0</li>
	<li>Symfony 1.2.1</li>
	<li>Yii 1.0.0</li>
	<li>ZendFramework 1.7.2</li>
</ul>
</p><span id="more-129"></span>
<p>Для тестирования использовалась стандартная апачевская утилита <a href="http://httpd.apache.org/docs/1.3/programs/ab.html"><em>ab</em></a>, измерялось общее количество обработанных запросов за 30 секунд работы. Испытание выполнялось для каждого приложения в двух режимах: с 10 одновременными запросами и со 100 одновременными запросами. т.е. <em>&#8220;ab -c 30 -t 10&#8243;</em> и <em>&#8220;ab -c 30 -t 100&#8243;</em>.</p><p><strong>Тест первый</strong>: Hello, world!. По горизонтали &mdash; количество успешно обработанных запросов.</p>
<div id="attachment_137" class="wp-caption aligncenter" style="width: 508px"><img src="http://www.handmadesite.net/wp-content/uploads/2008/12/fw-chart-1.png" alt="Производительность приложения Hello, world!" title="Производительность приложения Hello, world!" width="498" height="260" class="size-full wp-image-137" /><p class="wp-caption-text">Производительность приложения Hello, world!</p></div>
<p>CI и Yii очень быстро обрабатывают обращения к сайту. Диспетчеризация, роутинг, подгрузка нужных контроллера и вида. Что касается ZF &mdash; я не удивлен, с его обширной файловой системой и количеством файлов это немудрено. Там за один include системе приходится просмотреть пару десятков, а то и больше, директорий. Cake &mdash; вот кто удивил. Возможно, время тратится на всяческие преобразования Inflector&#8217;ом и обработку умолчаний. Отговорки о том, что CkePHP совместим с PHP4 не помогут. CodeIgniter тоже поддерживает PHP4.</p><p><strong>Тест второй</strong>: 10 запросов к базе данных</p>
<div id="attachment_142" class="wp-caption aligncenter" style="width: 508px"><img src="http://www.handmadesite.net/wp-content/uploads/2008/12/fw-chart-2.png" alt="10 запросов к базе данных" title="10 запросов к базе данных" width="498" height="260" class="size-full wp-image-142" /><p class="wp-caption-text">10 запросов к базе данных</p></div>
<p>Здесь отрыв немного сократился, но все равно, лидеры вдвое опережают остальных. Обратите внимание, что производительность практически не меняется в зависимости от нагрузки. Что 10 человек одновременно, что 100. CodeIgniter так даже улучшил производительность при большей нагрузке. Здесь, конечно, сказывается кэширование самого MySQL, если 100 человек одновременно будут открывать разные страницы и генерировать разные запросы к БД, то картина вполне может и поменяться.</p><p><strong>Тест третий</strong>: 1000 запросов к базе данных. Тест достаточно искусственный, выборка 1000 записей для генерации одной страницы чрезвычайно редкое явление. Этим тестом Хуан решил подтвердить тезис о том, что у всех фреймворков очень большие накладные расходы на обслуживание запросов: составление, выборку результатов, превращение результатов в структуры и т.д. Странно, что ему памяти на машине хватило. Cake, например, выбирает все результаты сразу.</p>
<div id="attachment_145" class="wp-caption aligncenter" style="width: 511px"><img src="http://www.handmadesite.net/wp-content/uploads/2008/12/fw-chart-3.png" alt="1000 запросов к базе данных" title="Тест 1000 запросов к базе данных" width="501" height="260" class="size-full wp-image-145" /><p class="wp-caption-text">1000 запросов к базе данных</p></div>
<p>CodeIgniter подтвердил свое лидерство. Но вот, что интересно: ZF практически не сдвинулся с места! Все верно, в ZF можно выбирать результаты построчно. CakePHP, по сравнению с ZF, просел прилично, но все-таки у 1.2 RC4 потеря производительности, относительно теста с 10 запросами, меньше, чем у предыдущей версии 1.1.20. Это вселяет некоторую надежду.</p><p><a href="http://www.cakephp-brasil.org/benchmarks/resultados/final.html">Результаты тестов доступны отдельно здесь.</a></p>

<p><a href="http://feedads.googleadservices.com/~a/ey6xBkDaruntcxVurLVLUZYkz4w/a"><img src="http://feedads.googleadservices.com/~a/ey6xBkDaruntcxVurLVLUZYkz4w/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=zRTnopOK"><img src="http://feedproxy.google.com/~f/handmadesite?i=zRTnopOK" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=uox3n9ug"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=Z6ZtRfLq"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=v4nqpuxA"><img src="http://feedproxy.google.com/~f/handmadesite?i=v4nqpuxA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/php-frameworks-perfomance-test/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Табличная верстка</title>
		<link>http://www.handmadesite.net/2008/12/tablichnaya-verstka/</link>
		<comments>http://www.handmadesite.net/2008/12/tablichnaya-verstka/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 10:08:30 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[Без рубрики]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[yandex]]></category>

		<category><![CDATA[верстка]]></category>

		<category><![CDATA[таблицы]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=122</guid>
		<description><![CDATA[Вот все морщат нос и ругают табличную верстку. А вот тем тем не менее кое-кто ее вполне себе использует. Это я не к тому, что надо срочно все переверстывать в таблицы. Скажем так, просто информация к размышлению ;-)На самом деле просто решил посмотреть, как люди делают список в несколько колонок. Теория есть на A List [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_123" class="wp-caption alignnone" style="width: 310px"><a href="http://www.handmadesite.net/wp-content/uploads/2008/12/yandex-glagne.png"><img src="http://www.handmadesite.net/wp-content/uploads/2008/12/yandex-glagne-300x207.png" alt="ГЛАГНЕ Яндекс и Firebug. Кликабельно." title="ГЛАГНЕ Яндекс и Firebug" width="300" height="207" class="size-medium wp-image-123" /></a><p class="wp-caption-text">ГЛАГНЕ Яндекс и Firebug. Кликабельно.</p></div><p>Вот все морщат нос и ругают табличную верстку. А вот тем тем не менее кое-кто ее вполне себе использует. Это я не к тому, что надо срочно все переверстывать в таблицы. Скажем так, просто информация к размышлению ;-)</p><p>На самом деле просто решил посмотреть, как люди делают список в несколько колонок. <a href="http://www.alistapart.com/articles/multicolumnlists">Теория есть на A List Apart</a>, а вот как оно в реальности, стало интересно.</p>
<p><a href="http://feedads.googleadservices.com/~a/FOY4LUVx58WHR0vxQfQppgIzvJM/a"><img src="http://feedads.googleadservices.com/~a/FOY4LUVx58WHR0vxQfQppgIzvJM/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=KekdBzmK"><img src="http://feedproxy.google.com/~f/handmadesite?i=KekdBzmK" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=gQgj7hEy"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=AQY33j8M"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=hGVluxSZ"><img src="http://feedproxy.google.com/~f/handmadesite?i=hGVluxSZ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/tablichnaya-verstka/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Самый последний CakePHP Release Candidate</title>
		<link>http://www.handmadesite.net/2008/12/lastest-lastest-cakephp-release-candidate/</link>
		<comments>http://www.handmadesite.net/2008/12/lastest-lastest-cakephp-release-candidate/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 17:02:39 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[rc4]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=118</guid>
		<description><![CDATA[Поскольку &#171;последний перед финальный релизом&#187; Candidate был RC3, то сегодня вышел вышел &#171;последний-последний RC4&#187;. Авторы Cake, видимо, тоже подвержены приступам перфекционизма. Изменений, по сравнению с RC3 немного и моих проектов, они, кажется, не коснулись. Не то, что RC3. 	Из компонента AclComponent убрали методы setAro(), setAco(), getAro() и getAco()<br />	Убран метод Model::normalizeFindParams()<br />	Из параметров метода JavascriptHelper::codeBlock() убран $safe, [...]]]></description>
			<content:encoded><![CDATA[<p>Поскольку <a href="http://bakery.cakephp.org/articles/view/release-cakephp-rc3-the-rc-of-triumph">&laquo;последний перед финальный релизом&raquo; Candidate был RC3</a>, то сегодня вышел <a href="http://bakery.cakephp.org/articles/view/rc4-close">вышел &laquo;последний-последний RC4&raquo;</a>. Авторы Cake, видимо, тоже подвержены приступам перфекционизма. Изменений, по сравнению с RC3 немного и моих проектов, они, кажется, не коснулись. Не то, что RC3. </p><ul><br />	<li>Из компонента AclComponent убрали методы setAro(), setAco(), getAro() и getAco()</li>
	<li>Убран метод Model::normalizeFindParams()</li>
	<li>Из параметров метода JavascriptHelper::codeBlock() убран $safe, ранее отмеченный как deprecated</li>
	<li>Изменен параметр вызова метода XmlNode::toArray(). Вместо $object (=null) теперь $camelize (= true)</li>
	<li>Исправлены какие-то стили, скорее всего для вывода тестов или scaffold views. В общем, если пользуетесь стандартным файлом со стилями, сake.css, обновите его.</li>
	<li>Методы ClassRegistry::_duplicate() и Router::matchRoute() теперь private, переименованы в ClassRegistry::__duplicate() и Router::__matchRoute() соответственно</li>
</ul>

<p><a href="http://feedads.googleadservices.com/~a/FXw5cxM1hILkHpxyVpdP3J5KZv0/a"><img src="http://feedads.googleadservices.com/~a/FXw5cxM1hILkHpxyVpdP3J5KZv0/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=gMPbtDAS"><img src="http://feedproxy.google.com/~f/handmadesite?i=gMPbtDAS" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=QSS0ceBC"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=kVNcxcyX"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=P2837oD3"><img src="http://feedproxy.google.com/~f/handmadesite?i=P2837oD3" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/lastest-lastest-cakephp-release-candidate/feed/</wfw:commentRss>
		</item>
		<item>
		<title>M - for model</title>
		<link>http://www.handmadesite.net/2008/12/m-for-model/</link>
		<comments>http://www.handmadesite.net/2008/12/m-for-model/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 22:39:17 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[tips and tricks]]></category>

		<category><![CDATA[Модель]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=108</guid>
		<description><![CDATA[Очень-очень редко, но бывает нужно использовать в каком-нибудь методе контроллера несколько несвязанных между собой моделей. Еще раз, ключевые слова: &#171;редко-редко&#187; и &#171;несвязанных&#187;.Можно такие модели перечислить в переменной класса $uses &#8212; тогда, они, правда, будут загружаться для любого метода контроллера.В версии 1.1 фреймворка была функция loadModel(), которая теперь отменена.Есть еще метод requestAction(), но он объявлен &#171;плохим&#187;. [...]]]></description>
			<content:encoded><![CDATA[<p>Очень-очень редко, но бывает нужно использовать в каком-нибудь методе контроллера несколько <strong>несвязанных</strong> между собой моделей. Еще раз, ключевые слова: &laquo;редко-редко&raquo; и &laquo;несвязанных&raquo;.</p><p>Можно такие модели перечислить в переменной класса $uses &mdash; тогда, они, правда, будут загружаться для любого метода контроллера.</p><p>В версии 1.1 фреймворка была функция <em>loadModel()</em>, которая теперь отменена.</p><p>Есть еще метод <em>requestAction()</em>, но он объявлен &laquo;плохим&raquo;. И правда, это, по сути, еще один запрос к приложению по полной программе, с диспетчеризацией, роутингом, стартом и инициализацией всех сопутствующих классов. В общем, путь неоптимальный и пользоваться им можно лишь от полной безысходности.</p><p>Можно воспользоваться методом <em>App::import()</em> &mdash; это хороший метод для многих классов. Но загруженная модель будет неполной. Т.е. это будет просто загруженный класс модели, без всех предварительных инициализаций самой модели и т.п. Этим методом лучше пользоваться для подгрузки своих классов или библиотек сторонних разработчиков.</p><p>В общем, я лично чаще всего в Cake 1.2 использовал именно App::import(), мирясь с некоторыми ограничениями. Но, оказывается есть еще один метод, позволяющий полностью загрузить модель, со всем ее &laquo;обвесом&raquo;</p><span id="more-108"></span>
<p><a href="http://teknoid.wordpress.com/2008/12/16/how-to-build-a-dashboard-for-your-application-in-cakephp/">teknoid в своем блоге описал</a> пример создания dashboard, ну примерно как в wordpress 2.7 :-) . Мне полезность самой dashboard как-то сомнительна, но не в ней дело. А дело в том, что это тот редкий случай, когда в одном отдельно взятом методе нужно вызывать методы нескольких совершенно неотносящихся друг к другу моделей. teknoid приводит пример с вызовами методов для извлечения самых активных пользователей, самых посещаемых страниц, свежих новостей и т.д.</p><p>Для этого он использует ускользнувший от моего внимания :-) метод <em>ClassRegistry::init()</em>. Вот как выглядит написанный им метод контроллер Dashboard:</p>
<pre><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"> <span style="color: #000000; font-weight: bold;">&lt;?php</span>  
     <span style="color: #000000; font-weight: bold;">class</span> DashboardController <span style="color: #000000; font-weight: bold;">extends</span> AppController <span style="color: #009900;">&#123;</span>  
&nbsp;
           <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Dashboard'</span><span style="color: #339933;">;</span>  
           <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$uses</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: #000000; font-weight: bold;">function</span> index <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>  
                <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'topPosts'</span><span style="color: #339933;">,</span> ClassRegistry<span style="color: #339933;">::</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Post'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTop</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'recentNews'</span><span style="color: #339933;">,</span> ClassRegistry<span style="color: #339933;">::</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'News'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRecent</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'topEmployees'</span><span style="color: #339933;">,</span> ClassRegistry<span style="color: #339933;">::</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Employee'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTopPerformers</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'topSellingProducts'</span><span style="color: #339933;">,</span> ClassRegistry<span style="color: #339933;">::</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTopSellers</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: #009900;">&#125;</span>  
     <span style="color: #009900;">&#125;</span>  
 <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></pre></pre><p>Этот метод позволяет загрузить только нужные модели, и только тогда, когда они нужны. Это, на мой взгляд, гораздо интереснее перечисления моделей в переменной $uses и принудительной их загрузки вне зависимости от необходимости их использования.</p><p>В общем, на мой взгляд, очень полезная вещь. Надо запомнить, может пригодится. Thanks to teknoid :-) </p>
<p><a href="http://feedads.googleadservices.com/~a/NVZFS2CI7u8fuarBcHAFvvVaDJ4/a"><img src="http://feedads.googleadservices.com/~a/NVZFS2CI7u8fuarBcHAFvvVaDJ4/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=cJDKGTlA"><img src="http://feedproxy.google.com/~f/handmadesite?i=cJDKGTlA" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=iNhgHL13"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=Win1HVlQ"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=WoQtXjX7"><img src="http://feedproxy.google.com/~f/handmadesite?i=WoQtXjX7" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/m-for-model/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Показ товаров в категории Shop-Script</title>
		<link>http://www.handmadesite.net/2008/12/ss-products-in-category/</link>
		<comments>http://www.handmadesite.net/2008/12/ss-products-in-category/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 14:56:50 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[Shop-Script]]></category>

		<category><![CDATA[сортировка]]></category>

		<category><![CDATA[товар]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=77</guid>
		<description><![CDATA[Во всех магазинах товар имеет свойство заканчиваться. Однако мы все надеемся на лучшее и временно отсутствующий товар с сайта не убираем.В ShopScript есть 2 пути не дать заказать пользователю отсутствующий товар &#8212; включить в разделе «Настройки -&#62;Корзина и оформление заказов» опцию «Вести учет товаров на складе» и тогда в свойствах товара надо будет вести количество [...]]]></description>
			<content:encoded><![CDATA[Во всех магазинах товар имеет свойство заканчиваться. Однако мы все надеемся на лучшее и временно отсутствующий товар с сайта не убираем.<br /><br />В ShopScript есть 2 пути не дать заказать пользователю отсутствующий товар &#8212; включить в разделе <em>«Настройки -&gt;Корзина и оформление заказов»</em> опцию <strong>«Вести учет товаров на складе»</strong> и тогда в свойствах товара надо будет вести количество по каждой позиции. Второй путь проще: установить товару нулевую цену, тогда ShopScript не будет показывать для этого товара ссылку на добавление в корзину.<br /><br />Лично я предпочитаю второй путь, он для меня немного проще.<br /><br />Однако, при показе товаров в категории <strong>ShopScript</strong> сортирует их по полям <em>sort_order</em> (порядок сортировки) и <em>name</em> (название). Из-за этого отсутствующие товары идут вперемешку с наличиствующими. Хотелось бы наоборот, чтобы те товары, которых в данный момент нет в наличии отображались бы в конце списка и на это не влиял выбор порядка сортировки (по имени, по цене и т.п.). То есть, чтобы все типы сортировок, которые науказывал посетитель применялись к тем товарам, которые можно заказать, а отсутствующие были все равно в конце списка.<span id="more-77"></span><br /><br />Соседи вчера попросили сделать для них такой тип отображения. Чтобы не мучиться, я решил его сделать неотключаемым, просто добавить в запрос к базе данных на выборку товаров из категории еще одно правило. Оно должно быть первым, чтоб было самым главным :-) Вероятно я мог что-то упустить, но, с виду все работает как ожидается. Для сортировки по условию «поле Price равно нулю или нет» я использовал <a href="http://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html#function_if">функцию MySQL IF()</a>. Должен получаться вот такой запрос:<br /><pre><pre class="devcodeblock" title="SQL"><input type="hidden" value=""><pre class="devcode">
<span style="color: #993333; font-weight: bold;">SELECT</span>
	categoryID<span style="color: #66cc66;">,</span> name<span style="color: #66cc66;">,</span> brief_description<span style="color: #66cc66;">,</span>
	customers_rating<span style="color: #66cc66;">,</span> Price<span style="color: #66cc66;">,</span> in_stock<span style="color: #66cc66;">,</span>
	customer_votes<span style="color: #66cc66;">,</span> list_price<span style="color: #66cc66;">,</span> productID<span style="color: #66cc66;">,</span>
	default_picture<span style="color: #66cc66;">,</span> sort_order<span style="color: #66cc66;">,</span> items_sold<span style="color: #66cc66;">,</span>
	enabled<span style="color: #66cc66;">,</span> product_code<span style="color: #66cc66;">,</span> description<span style="color: #66cc66;">,</span>
	shipping_freight
<span style="color: #993333; font-weight: bold;">FROM</span> SS_products
<span style="color: #993333; font-weight: bold;">WHERE</span> enabled<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AND</span> categoryID<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">3</span>
<span style="color: #808080; font-style: italic;">/* Здесь может быть много категорий */</span>
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span>
	<span style="color: #993333; font-weight: bold;">IF</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`Price`</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">ASC</span><span style="color: #66cc66;">,</span>
	sort_order<span style="color: #66cc66;">,</span> name;
</pre></pre></pre><p>Если используется учет количества товаров, то вместо поля `Price` надо использовать поле `in_stock`, как я понимаю.</p><p>За получение списка товаров для показа отвечает функция <strong>prdSearchProductByTemplate</strong> в файле <em>core_functions/product_functions.php</em>. Функция здоровая, из нее нам нужен кусок, который начинается с:</p><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #000088;">$order_by_clause</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;order by sort_order, name&quot;</span><span style="color: #339933;">;</span>
</pre></pre><p>Вот эту строчку и всю ересь далее удаляем, вплоть до строчки<p><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #000088;">$sqlQueryCount</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;select count(*) from &quot;</span><span style="color: #339933;">.</span>PRODUCTS_TABLE<span style="color: #339933;">.</span>
</pre></pre><p>Строка выше должна остаться. ;-) Перед ней вставляем вот такой код:</p>
<pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #000088;">$order_by_clause</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;order by IF(`Price`,1,0) DESC, &quot;</span><span style="color: #339933;">;</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;">$callBackParam</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;sort&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span>
	<span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$callBackParam</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;sort&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">&quot;categoryID&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;brief_description&quot;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">&quot;in_stock&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;Price&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;customer_votes&quot;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">&quot;customers_rating&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;list_price&quot;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">&quot;sort_order&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;items_sold&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;product_code&quot;</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">&quot;shipping_freight&quot;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$order_by_clause</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$callBackParam</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;sort&quot;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$callBackParam</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;direction&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$callBackParam</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;direction&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;DESC&quot;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$order_by_clause</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot; DESC&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$order_by_clause</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;sort_order, name&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></pre><p>Не идеально, но на скорую руку сойдет. Вот и все, собственно. Теперь все товары с нулевой ценой будут в конце списка. Как сделать различие по другоу полю я уже написал.</p><p><strong>Attention please</strong>. Не успел достаточно это протестировать, возможно эта функция вызывается еще откуда-нибудь. Перед внесением изменений сделайте себе про запас копию оригинальных файлов, которые собираетесь изменить. ;-)</p>
<p><a href="http://feedads.googleadservices.com/~a/BlHSEIKPwuVQAy-eiQPbEdbNHrc/a"><img src="http://feedads.googleadservices.com/~a/BlHSEIKPwuVQAy-eiQPbEdbNHrc/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=fBfdbl8P"><img src="http://feedproxy.google.com/~f/handmadesite?i=fBfdbl8P" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=X5fzel62"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=jwnxNSLw"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=4VVOsxiu"><img src="http://feedproxy.google.com/~f/handmadesite?i=4VVOsxiu" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/ss-products-in-category/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Исходные тексты CakeBook</title>
		<link>http://www.handmadesite.net/2008/12/cakebook-source-code/</link>
		<comments>http://www.handmadesite.net/2008/12/cakebook-source-code/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 21:26:50 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[source]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=73</guid>
		<description><![CDATA[Что интересного можно увидеть в чужом коде? Конечно приемы программирования и подход к реализации. Обсудим исходники CakeBook?]]></description>
			<content:encoded><![CDATA[Это, конечно, уже не новость &#8212; некоторое время назад на всеобщее обозрение были <a href="http://thechaw.com/cakebook/" target="_blank">выложены исходные тексты CakeBook</a>. Это то самое приложение, которое работает на сайте <a href="http://book.cakephp.org">http://book.cakephp.org</a> &#8212; сайте с официальной документацией на CakePHP.<br /><br />Мне было очень интересно посмотреть на различные приемы, использованные при написании этого приложения. Вдруг какая-нибудь идея пригодится? Похоже, что приложение написано на версии 1.1 фреймворка, поэтому не все вещи полезны, и кое-какие куски кода могут и не работать. Тем не менее, есть несколько вещей, на которые я обратил внимание.<span id="more-73"></span>
<ol><br />	<li>В AppController реализованы методы <em>admin_index()</em>, <em>admin_view()</em>, <em>admin_add()</em> и.т.д. И как же это я сам не сообразил? :-) Пять баллов.</li>
	<li>В AppModel очень, на мой взгляд, интересный метод <em>searchConditions()</em> для составления параметров запроса к модели и связанным с ней моделям для поиска по строковым и текстовым полям. Еще не пробовал, надо будет проверить, как этот метод работает совместно с ContainableBehaviour.</li>
	<li>Плагин &#8216;Users&#8217;, как мне кажется, хорошо демонстрирует тактику работы с плагинами: что можно сделать плагином, как с ним взаимодействовать. Есть над чем подумать: &#8220;Пользователь&#8221; со всеми его &#8220;профайлами&#8221; и прочим &#8212; действительно отдельная часть приложения, но не независимая.</li>
	<li>Один из очень часто задаваемых вопросов на форуме и гугловской группе &#8212; как сделать боковое меню, меняющееся в зависимости от действия, контроллера и т.д. В CakeBook можно посмотреть один из вариантов реализации. Не бесспорный, но интересный.</li>
	<li>Работа с &#8216;Vendors&#8217; типа Zend_Search_Lucene. Лично мне было не очень интересно, т.к. я Lucene не использую, но отметить надо. :-)</li>
</ol>
Но, кое-что вызвало некоторое удивление. Например RedirectController. Перенаправляет пользователя на соответствующий узел в зависимости от slug&#8217;а. При этом номера узлов жестко заданы. Возможно, это сделано для улучшения производительности, но все-равно &#8212; мне не нравится.<br /><br />AD7six использовал свой <a href="http://www.ad7six.com/MiBlog/GenericFileUploadBehavior" target="_blank">behavior для хранения картинок и файлов</a>. Сам подход, теоретически, хорош, но конкретная реализация, на мой взгляд, не лучшая.<br /><br />Я что-то упустил? Кто на что еще обратил внимание?
<p><a href="http://feedads.googleadservices.com/~a/6UdzTt-yfxngv9zOrNEUsoBJcoc/a"><img src="http://feedads.googleadservices.com/~a/6UdzTt-yfxngv9zOrNEUsoBJcoc/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=n28Xvtrm"><img src="http://feedproxy.google.com/~f/handmadesite?i=n28Xvtrm" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=ZIM1oH9F"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=6XJIQVOT"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=N8wrHuSh"><img src="http://feedproxy.google.com/~f/handmadesite?i=N8wrHuSh" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/12/cakebook-source-code/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Где ID?</title>
		<link>http://www.handmadesite.net/2008/11/gde-id/</link>
		<comments>http://www.handmadesite.net/2008/11/gde-id/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 21:26:10 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[Controller]]></category>

		<category><![CDATA[Controller methods]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=60</guid>
		<description><![CDATA[Маленький метод, автоматизирующий проверку переданного параметра, который Cake распознает как ID]]></description>
			<content:encoded><![CDATA[Надоело мне писать в начале каждого метода контроллера, требующего для работы ID записи, проверку на наличие этого самого ID.<br /><br />Ну вот например для вызовы методов /controller/view без ID записи смысла не имеют. Я в таких случаях делаю redirect на метод index. Примерно так:<br /><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #000000; font-weight: bold;">function</span> view<span style="color: #009900;">&#40;</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: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'controller'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'mycontroller'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'action'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">/*
 * Ну тут код дальше
 */</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></pre>
Один раз это написать можно, два раза - начинает раздражать. В итоге задумываешься об автоматизации этой проверки. Что я и сделал. <span id="more-60"></span><br /><br />Маленький метод, который можно добавить в <em>AppController</em>. Работу с PHP4 не тестировал. И работу с контроллером, у которого несколько моделей тоже ;-)<br /><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode">protected <span style="color: #000000; font-weight: bold;">function</span> redirect_if_no_id<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</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: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">// Значения по умолчанию</span>
   <span style="color: #000088;">$defaults</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'flash'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">modelNames</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'index'</span>
   <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #990000;">extract</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Если ID есть, то ничего не делаем</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Если передана переменная flash -- отдадим ее</span>
<span style="color: #666666; font-style: italic;">// SessionComponent'у</span>
<span style="color: #666666; font-style: italic;">// Здесь хорошо бы проверку, загружен-ли</span>
<span style="color: #666666; font-style: italic;">// SessionComponent вообще</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$flash</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFlash</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$flash</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'controller'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'controller'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'action'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></pre>
Как видно, можно передавать (но не обязательно), массив с параметрами:
<ul><br />	<li>ключ <em>id</em> - значение, которое надо проверить. Если не указано, используем id от первой загруженной модели</li>
	<li>ключ <em>flash</em> - сообщение для пользователя. Если не указано, значит все делаем молча</li>
	<li>ключ <em>action</em> - действие, на которое надо редирект сделать. Если не указано, то <em>index</em>.</li>
</ul>
Все это будет работать в пределах одного контроллера, т.е. редирект будет на действие того-же контроллера. Желающие могут доработать напильником.
<p><a href="http://feedads.googleadservices.com/~a/W2w5E9vXlBLTVcASseipQA9DGf0/a"><img src="http://feedads.googleadservices.com/~a/W2w5E9vXlBLTVcASseipQA9DGf0/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=geh0Mqhn"><img src="http://feedproxy.google.com/~f/handmadesite?i=geh0Mqhn" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=fNCd8ZDn"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=aY0IWpLD"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=3qvvRU7m"><img src="http://feedproxy.google.com/~f/handmadesite?i=3qvvRU7m" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/11/gde-id/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Многие ко многим - опасные связи</title>
		<link>http://www.handmadesite.net/2008/11/mnogie-ko-mnogim-opasnyie-svyazi/</link>
		<comments>http://www.handmadesite.net/2008/11/mnogie-ko-mnogim-opasnyie-svyazi/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 22:27:48 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[HABTM]]></category>

		<category><![CDATA[hasAndBelongsToMany]]></category>

		<category><![CDATA[Модель]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=50</guid>
		<description><![CDATA[Более простое и понятное связей "многие-ко-многим", хоть и ценой отказа от автоматизма и "магии".]]></description>
			<content:encoded><![CDATA[На этой неделе обновил CakePHP из SVN и тут же перестало работать добавление связей &#8220;многие-ко-многим&#8221; (<em>hasAndBelongsToMany</em>, <em>HABTM</em>). Небольшое расследование, сравнение изменений в коде и вопросы в гугл группе дали неутешительные результаты.<br /><br />Во-первых у меня сложилось впечатление, что разработчики, несмотря на статус ReleaseCandidate (RC3) все еще не пришли к единому мнению относительно структуры данных, которую надо скармливать методу <em>save()</em>. :-/<br /><br />Во-вторых <a href="http://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B2%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BB%D1%8E%D1%87" target="_blank">естественные ключи</a> в CakePHP практически &#8220;вне закона&#8221;. Вот непонятно мне это - чем с точки зрения методов <em>find()</em>, <em>save()</em> и др. так сильно отличаются естественные ключи от синтетических? Тем более, что нечисловые первичные ключи все-таки поддерживаются. Это я про поля с <a href="http://ru.wikipedia.org/wiki/UUID" target="_blank">UUID</a>.<br /><br />Проанализировав ситуацию, пришел к выводу, что на жанном этапе отказываться от естественных ключей пока неразумно и надо, видимо, добавлять такие связи самостоятельно. Тем более, что выборка по прежнему работает отлично. Т.е. нужно только реализовать добавление и удаление связей. <span id="more-50"></span><br /><br />Как обычно, начал с поиска уже готовых решений и <a href="http://com.spweb.ru/archives/108" target="_blank">в блоге &#8220;Программируем на CakePHP&#8221; нашел код нужных методов</a>. Работает даже лучше прежнего - передаем id записи из модели, массив id записей другой модели и все добавляется в связующую таблицу. Это, конечно, не &#8220;автомагия&#8221;, но зато просто и понятно. :-)<br /><br />Обратил внимание на некоторую неоптимальность в работе кода. Алгоритм метода добавления примерно такой:
<ol><br />	<li>Как уже написал, получаем id записи и массив id связанных записей</li>
	<li>Проверяем есть-ли уже какие-нибудь пары id-id и удаляем их</li>
	<li>Добавляем связи</li>
</ol>
Мне это не очень понравилось - считаю, что один SELECT, лучше, чем 5 DELETE. :-) Поэтому немного переписал метод. Во-первых отказался от принудительного удаления уже существующих связей, просто удаляю из массива те id связанных записей, отношение с которыми уже есть. Во-вторых заменил серию INSERT&#8217;ов, по одному на каждую связь, на один общий INSERT. Получился вот такой код:<br /><pre><pre class="devcodeblock" title="PHP"><input type="hidden" value=""><pre class="devcode"><span style="color: #009933; font-style: italic;">/**
 * Добавляет связь между двумя записями
 *
 * @param mixed $assoc С какой моделью установлена HABTM связь
 * @param mixed $assoc_ids Идентификатор или массив идентификаторов записей, привязываемых к выбранной записи
 * @param integer $id Идентификатор выбранной записи в этой модели
 * @return boolean Success
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> addAssoc<span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc</span><span style="color: #339933;">,</span> <span style="color: #000088;">$assoc_ids</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">null</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: #000088;">$id</span> <span style="color: #339933;">!=</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</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: #009900;">&#125;</span>
&nbsp;
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #339933;">!==</span> <span style="color: #000000; font-weight: bold;">null</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #339933;">!==</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
      <span style="color: #000088;">$db</span> <span style="color: #339933;">=&amp;</span> ConnectionManager<span style="color: #339933;">::</span><span style="color: #004000;">getDataSource</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">useDbConfig</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$joinTable</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasAndBelongsToMany</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$assoc</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'joinTable'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$table</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fullTableName</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$joinTable</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$keys</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasAndBelongsToMany</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$assoc</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'foreignKey'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$keys</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasAndBelongsToMany</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$assoc</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'associationForeignKey'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$keys</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <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: #000088;">$assoc_ids</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
         <span style="color: #000088;">$assoc_ids</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc_ids</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #000088;">$found_assoc</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span>
         <span style="color: #0000ff;">&quot;SELECT `<span style="color: #006699; font-weight: bold;">{$keys[1]}</span>` FROM <span style="color: #006699; font-weight: bold;">$table</span> WHERE `<span style="color: #006699; font-weight: bold;">{$keys[0]}</span>` = &quot;</span> <span style="color: #339933;">.</span>
         <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getColumnType</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">primaryKey</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span>
         <span style="color: #0000ff;">&quot; AND `<span style="color: #006699; font-weight: bold;">{$keys[1]}</span>` IN (&quot;</span> <span style="color: #339933;">.</span>
         <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc_ids</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span>
         <span style="color: #0000ff;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$found_assoc</span> <span style="color: #339933;">=</span> Set<span style="color: #339933;">::</span><span style="color: #004000;">classicExtract</span><span style="color: #009900;">&#40;</span>
         <span style="color: #000088;">$found_assoc</span><span style="color: #339933;">,</span>
         <span style="color: #0000ff;">'{n}.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fullTableName</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$joinTable</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">false</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: #000088;">$keys</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$assoc_ids</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_diff</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc_ids</span><span style="color: #339933;">,</span> <span style="color: #000088;">$found_assoc</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc_ids</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;">$assoc_ids</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$assoc_id</span><span style="color: #009900;">&#41;</span>
         <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$insert_values</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>
               <span style="color: #0000ff;">'('</span> <span style="color: #339933;">.</span>
               <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getColumnType</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">primaryKey</span><span style="color: #009900;">&#41;</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: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$assoc_id</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span>
&nbsp;
               <span style="color: #0000ff;">')'</span><span style="color: #339933;">;</span>
         <span style="color: #009900;">&#125;</span>
&nbsp;
         <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;INSERT INTO <span style="color: #006699; font-weight: bold;">{$table}</span> (<span style="color: #006699; font-weight: bold;">{$fields}</span>) VALUES &quot;</span> <span style="color: #339933;">.</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$insert_values</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #990000;">unset</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</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: #000000; font-weight: bold;">true</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: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
</pre></pre></pre>
Метод удаления связей переделал похожим образом.
<p><a href="http://feedads.googleadservices.com/~a/tFPsJcSEBjMNH0dys9W6FpOC0jY/a"><img src="http://feedads.googleadservices.com/~a/tFPsJcSEBjMNH0dys9W6FpOC0jY/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=fCoFKA6A"><img src="http://feedproxy.google.com/~f/handmadesite?i=fCoFKA6A" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=98WPuSu1"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=4XsKx7Nz"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=mrmq26ST"><img src="http://feedproxy.google.com/~f/handmadesite?i=mrmq26ST" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/11/mnogie-ko-mnogim-opasnyie-svyazi/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Гарантированный способ потерять сессию в CakePHP 1.2RC3</title>
		<link>http://www.handmadesite.net/2008/11/how-to-lost-session-in-cakephp-12rc3/</link>
		<comments>http://www.handmadesite.net/2008/11/how-to-lost-session-in-cakephp-12rc3/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 18:23:37 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
		
		<category><![CDATA[CakePHP]]></category>

		<category><![CDATA[особенности]]></category>

		<category><![CDATA[ошибки]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=44</guid>
		<description><![CDATA[Рецепт гарантированной утери сессии в CakePHP 1.2RC3. Увы, без решения.]]></description>
			<content:encoded><![CDATA[Как исправить ситуацию я пока не придумал. Видимо, связано с желанием разработчиков улучшить защищенность системы.<br /><br />Для воспроизведения потребуется либо не очень быстрый сервер, либо сильно нагруженный сервер (хорошо бы еще добавить какой-нибудь хитрый запрос к Модели на выборку с JOIN&#8217;ами из большой таблицы - чтоб времени на запрос ощутимо уходило), или клиент на достаточно медленном канале.<br /><br />Алгоритм следующий:
<ol><br />	<li>Запускаем сессию и отдаем пользователю Вид (View) с двумя ссылками, например, на Controller1/action1 и на Controller2/action2</li>
	<li>Кликаем по первой ссылке</li>
	<li>Не дожидаясь загрузки страницы с видом Controller1/action1, кликаем по второй ссылке</li>
	<li>Сессия потеряна</li>
</ol>
Досконально я не проверял, но по результатам рассмотра файлов с сессиями в директории /tmp, думаю, что AuthComponent или еще какой, например RequestHandler виноваты.<br /><br /><strong>Update</strong>: Как и предполагалось, это не бага, а фича для секьюрности. Лечится [вроде бы] сменой установки <em>Security.level</em> (в конфигурационном файле) с &#8216;<em>high</em>&#8216; на &#8216;<em>medium</em>&#8216;.
<p><a href="http://feedads.googleadservices.com/~a/Y5V2uBXPP-JStSVmcom9MRLOOxw/a"><img src="http://feedads.googleadservices.com/~a/Y5V2uBXPP-JStSVmcom9MRLOOxw/i" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feedproxy.google.com/~f/handmadesite?a=syelKFzg"><img src="http://feedproxy.google.com/~f/handmadesite?i=syelKFzg" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=x2fdsvOn"><img src="http://feedproxy.google.com/~f/handmadesite?d=41" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=3Skjnj2P"><img src="http://feedproxy.google.com/~f/handmadesite?d=52" border="0"></img></a> <a href="http://feedproxy.google.com/~f/handmadesite?a=Quk2m8Cx"><img src="http://feedproxy.google.com/~f/handmadesite?i=Quk2m8Cx" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2008/11/how-to-lost-session-in-cakephp-12rc3/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
