<?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>SimpleCoding.org &#187; MySQL</title>
	<atom:link href="http://www.simplecoding.org/category/mysql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.simplecoding.org</link>
	<description>Блог о программировании</description>
	<lastBuildDate>Sun, 25 Jul 2010 20:00:16 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<link rel="http://api.friendfeed.com/2008/03#sup" xmlns="http://www.w3.org/2005/Atom" type="application/json" href="http://friendfeed.com/api/public-sup.json#d217526a2c"/>		<item>
		<title>Yii PHP framework: создание запросов с условием IN</title>
		<link>http://www.simplecoding.org/yii-php-framework-sozdanie-zaprosov-s-usloviem-in.html</link>
		<comments>http://www.simplecoding.org/yii-php-framework-sozdanie-zaprosov-s-usloviem-in.html#comments</comments>
		<pubDate>Sat, 03 Jul 2010 10:27:22 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1092</guid>
		<description><![CDATA[Последнее время мне довольно часто приходится работать с фреймворком Yii. И иногда возникают вопросы, ответы на которые не очевидны (во всяком случае для меня).
Попробую объяснить. Сам фреймворк, на мой взгляд, достаточно удобный и документация подробная. Но классов много, и формат передачи данных их методам часто сильно влияет на результат.
Рассмотрим небольшой пример – использование оператора IN.
Т.е. [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1093" class="wp-caption alignnone" style="width: 294px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/07/yii_in_statement.png" alt="yii in condition" title="yii in condition" width="284" height="148" style="float:left" class="size-full wp-image-1093" /><p class="wp-caption-text"> </p></div>
<p>Последнее время мне довольно часто приходится работать с <strong>фреймворком Yii</strong>. И иногда возникают вопросы, ответы на которые не очевидны (во всяком случае для меня).</p>
<p>Попробую объяснить. Сам фреймворк, на мой взгляд, достаточно удобный и документация подробная. Но классов много, и формат передачи данных их методам часто сильно влияет на результат.</p>
<p>Рассмотрим небольшой пример – <strong>использование оператора IN</strong>.</p>
<p>Т.е. нужно сформировать примерно такой запрос.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> * <span class="kw1">FROM</span> tbl_users <span class="kw1">WHERE</span> id <span class="kw1">IN</span> <span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p><span id="more-1092"></span><br />
В <a href="http://yiiframework.ru/doc/guide/ru/index">Полном руководстве</a> на эту тему информации я не нашел, а копаться в методах <a href="http://www.yiiframework.com/doc/api/CActiveRecord">CActiveRecord</a> времени не было.</p>
<p>Вообще, я очень не люблю такие ситуации. С одной стороны, понятно как нужно написать запрос, с другой – хочется сделать это красиво, используя встроенную библиотеку. Копаться в документации не хочется, ведь на это уходит время, а запрос можно составить за считанные минуты. Но не все так просто.</p>
<p>Сначала покажу <strong>решение «в лоб»</strong>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$ids</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>=<span class="kw2">new</span> CActiveDataProvider<span class="br0">&#40;</span><span class="st0">&#039;User&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;criteria&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;condition&#039;</span>=&gt;<span class="st0">&#039;id IN (&#039;</span>.<span class="kw3">implode</span><span class="br0">&#40;</span><span class="st0">&#039;,&#039;</span>, <span class="re0">$ids</span><span class="br0">&#41;</span>.<span class="st0">&#039;)&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;admin&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="st0">&#039;model&#039;</span>=&gt;<span class="re0">$dataProvider</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Тут мы формируем массив со значениями, которые будут перечислены после <code>IN</code>. А затем, с помощью функции <code>implode</code> преобразуем его в строку и просто вставляем в запрос.</p>
<p><strong>Недостатки</strong> такого подхода очевидны.</p>
<p><em>Во-первых</em>, выглядит код не очень красиво.</p>
<p><em>Во-вторых</em>, в реальном приложении значения для массива <code>$ids</code> будут откуда-то поступать, возможно, из параметров запроса. И если массив <code>$ids</code> окажется пустым, то при выполнении запроса возникнет ошибка. </p>
<p><em>В-третьих</em>, полученные значения нужно проверить. А написать что-то вроде</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="st0">&#039;params&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;:id&#039;</span>=&gt;implode<span class="br0">&#40;</span><span class="st0">&#039;, &#039;</span>, <span class="re0">$ids</span><span class="br0">&#41;</span><span class="br0">&#41;</span>,</div>
</li>
</ol>
</div>
<p>не получится, т.к. результат работы функции <code>implode</code> будет взят в кавычки. Т.е. проверку необходимо сделать предварительно.</p>
<p>Как видите, возникают проблемы практически на пустом месте. Нужно написать код проверок, решить, что делать с пустым массивом, затем протестировать этот код. И все ради решения тривиальной задачи.</p>
<p><strong>Решение с помощью библиотеки Yii.</strong></p>
<p>Оно выглядит гораздо проще.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$model</span> = User::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAllByAttributes</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;id&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>=<span class="kw2">new</span> CActiveDataProvider<span class="br0">&#40;</span><span class="st0">&#039;User&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>-&gt;<span class="me1">setData</span><span class="br0">&#40;</span><span class="re0">$model</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;index&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;dataProvider&#039;</span>=&gt;<span class="re0">$dataProvider</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Метод <code>findAllByAttributes</code> класса <code>CActiveRecord</code> позволяет искать записи в БД по названию поля и значению. При этом если значение является массивом, то используется оператор <code>IN</code>.</p>
<p>Этот же самый код можно записать немного иначе.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>=<span class="kw2">new</span> CActiveDataProvider<span class="br0">&#40;</span><span class="st0">&#039;User&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>-&gt;<span class="me1">criteria</span>-&gt;<span class="me1">addInCondition</span><span class="br0">&#40;</span><span class="st0">&#039;id&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">1</span>,<span class="nu0">2</span>,<span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;index&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="st0">&#039;dataProvider&#039;</span>=&gt;<span class="re0">$dataProvider</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Тут уже используется метод <code>addInCondition</code> класса <code>CDbCriteria</code>. Если вы работаете с <code>CActiveDataProvider</code>, то получить доступ к объекту <code>CDbCriteria</code> можно с помощью свойства <code>criteria</code>.</p>
<p>Теперь проведем несколько экспериментов.</p>
<p>Попробуем в массиве передать строку.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>-&gt;<span class="me1">criteria</span>-&gt;<span class="me1">addInCondition</span><span class="br0">&#40;</span><span class="st0">&#039;id&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">1</span>,<span class="nu0">2</span>,<span class="st0">&#039;test&#039;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>В результате будет выполнен следующий запрос.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> * <span class="kw1">FROM</span> <span class="st0">&#039;tbl_user&#039;</span> <span class="kw1">WHERE</span> <span class="st0">&quot;id&quot;</span> <span class="kw1">IN</span> <span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>Т.е. текстовое значение было заменено нулем, что вполне логично, т.к. поле <code>id</code> имеет тип <code>INT</code>.</p>
<p>Если запрос будет выполняться к полю текстового типа, то текстовые и числовые значения будут вставлены в кавычках.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>-&gt;<span class="me1">criteria</span>-&gt;<span class="me1">addInCondition</span><span class="br0">&#40;</span><span class="st0">&#039;id&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">1</span>, <span class="st0">&#039;admin&#039;</span>,<span class="st0">&#039;user&#039;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>сформирует такой запрос</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> * <span class="kw1">FROM</span> <span class="st0">&#039;tbl_user&#039;</span> <span class="kw1">WHERE</span> <span class="st0">&quot;id&quot;</span> <span class="kw1">IN</span> <span class="br0">&#40;</span><span class="st0">&#039;1&#039;</span>,<span class="st0">&#039;admin&#039;</span>, <span class="st0">&#039;user&#039;</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>А если массив окажется пуст, то фреймворк гарантирует, что из таблицы не будет выбрана ни одна запись.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>-&gt;<span class="me1">criteria</span>-&gt;<span class="me1">addInCondition</span><span class="br0">&#40;</span><span class="st0">&#039;id&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> * <span class="kw1">FROM</span> <span class="st0">&#039;tbl_user&#039;</span> <span class="kw1">WHERE</span> <span class="nu0">0</span>=<span class="nu0">1</span></div>
</li>
</ol>
</div>
<p>Как видите, использование встроенных библиотек всё-таки оправдывает время, потраченное на их изучение <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Только не забывайте при работе с документацией Yii учитывать один момент. Классы библиотеки тесно связаны между собой, поэтому искать нужно не только в методах класса, с которым вы непосредственно работаете, но и в методах объектов, которые использует этот класс.</p>
<p>Так <code>CActiveDataProvider</code> использует <code>CDbCriteria</code> для формирования условий, <code>CPagination</code> – для разбивки на страницы, CSort – для сортировки и т.д.</p>
<p>Вообще, я заметил, чем больше работаешь с фреймворком, тем логичнее кажутся решения разработчиков и тем проще ориентироваться в документации <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Удачи!</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=1092&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-php-framework-sozdanie-zaprosov-s-usloviem-in.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Yii PHP фреймворк: создаем поле с автозаполнением</title>
		<link>http://www.simplecoding.org/yii-php-frejmvork-sozdaem-pole-s-avtozapolneniem.html</link>
		<comments>http://www.simplecoding.org/yii-php-frejmvork-sozdaem-pole-s-avtozapolneniem.html#comments</comments>
		<pubDate>Sun, 16 May 2010 08:51:38 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1060</guid>
		<description><![CDATA[Приветствую всех!
Сегодня я покажу небольшой пример использования виджета CAutoComplete из фреймворка Yii. Как несложно догадаться, он создаёт текстовое поле, под которым может появляться список с вариантами подстановок.
Принцип создания такого поля довольно прост. На странице нужно поместить обычное текстовое поле и назначить событию onKeyUp обработчик, который будет отправлять AJAX запросы серверу. В этих запросах нужно передавать [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1061" class="wp-caption alignnone" style="width: 281px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/05/yii_php_framework_autocomplete.png" alt="yii php framework autocomplete" title="yii php framework autocomplete" width="271" height="166" class="size-full wp-image-1061" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>Сегодня я покажу небольшой пример использования виджета <a href="http://www.yiiframework.com/doc/api/CAutoComplete">CAutoComplete</a> из фреймворка <strong>Yii</strong>. Как несложно догадаться, он создаёт текстовое поле, под которым может появляться список с вариантами подстановок.</p>
<p>Принцип создания такого поля довольно прост. На странице нужно поместить обычное текстовое поле и назначить событию <code>onKeyUp</code> обработчик, который будет отправлять <strong><acronym title="Asynchronous JavaScript and XML">AJAX</acronym></strong> запросы серверу. В этих запросах нужно передавать введённый посетителем текст. Сервер ищет совпадения с этим текстом в БД и возвращает результат браузеру. JavaScript обработчик создаёт список с вариантами, полученными от сервера, и показывает его под полем.</p>
<p>Как видите, алгоритм несложный, но рутинной работы много.</p>
<p>Теперь, давайте разберёмся, что сделает за вас виджет, а что придётся делать вам.<br />
<span id="more-1060"></span><br />
Для работы виджет использует плагин <a href="http://plugins.jquery.com/project/autocompletex">Autocomplete</a> библиотеки <strong>jQuery</strong>, т.е. писать <acronym title="JavaScript">JS</acronym> код от вас не потребуется (если, конечно, вы не хотите изменить стандартное поведение плагина).</p>
<p>Кроме того, виджет создаст текстовое поле и подключит все необходимые <acronym title="JavaScript">JS</acronym> и <acronym title="Cascading Style Sheets">CSS</acronym> файлы. Вам нужно будет только указать некоторые настройки.</p>
<p>Основная часть вашей работы будет заключаться в написании метода, выполняющего обработку запросов и поиск данных в базе.</p>
<p>Теперь <strong>рассмотрим пример</strong>.</p>
<p>Допустим, у нас есть база данных с названиями стран. Таблица называется <code>countries</code>, а поле, в котором хранятся названия &#8211; <code>c_name</code>.</p>
<p>Создаём для этой таблицы модель.</p>
<p><code>yiic shell<br />
model countries</code></p>
<p><em>Примечание</em>. Тут я предполагаю, что у вас создано веб приложение и настроено подключение к базе данных.</p>
<p>Теперь нужно создать текстовое поле. <code>CAutoComplete</code> – это обычный виджет, поэтому поместить его можно где угодно. Если хотите, чтобы поле выводилось на отдельной странице – добавляйте его в соответствующее представление, хотите показывать на каждой странице – добавляйте в макет (layout).</p>
<p>Код вставки виджета выглядит так.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">widget</span><span class="br0">&#40;</span><span class="st0">&#039;CAutoComplete&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;model&#039;</span>=&gt;<span class="st0">&#039;countries&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;name&#039;</span>=&gt;<span class="st0">&#039;country&#039;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;url&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;countries/autocomplete&#039;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;minChars&#039;</span>=&gt;<span class="nu0">2</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Во втором параметре необходимо передать массив с параметрами. Обязательными являются первые два.<br />
<code>model</code> – имя модели.<br />
<code>name</code> – атрибут name текстового поля.<br />
<code>url</code> – адрес скрипта, который будет обрабатывать <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> запросы.<br />
<code>minChars</code> – минимальное количество символов, при котором выполняется отправка запроса.</p>
<p>Естественно, это не все параметры. Подробный их перечень вы найдете на странице <a href="http://www.yiiframework.com/doc/api/CAutoComplete">документации</a>.</p>
<p>По мере ввода текста серверному скрипту будут отправляться <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> запросы вида:</p>
<p><code>index.php?r=countries/autocomplete&#038;q=%D0%B0%D0%BB&#038;limit=10&#038;timestamp=1273944702297</code></p>
<p>В параметре <code>q</code> передаётся введённый посетителем текст, а в параметре <code>limit</code> – максимальное количество подстановок.</p>
<p>Рассмотрим метод, выполняющий обработку этого запроса.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> actionAutoComplete<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;q&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$criteria</span> = <span class="kw2">new</span> CDbCriteria;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$criteria</span>-&gt;<span class="me1">condition</span> = <span class="st0">&#039;c_name LIKE :country&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$criteria</span>-&gt;<span class="me1">params</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;:country&#039;</span>=&gt;<span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;q&#039;</span><span class="br0">&#93;</span>.<span class="st0">&#039;%&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;limit&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> &amp;&amp; <span class="kw3">is_numeric</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;limit&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$criteria</span>-&gt;<span class="me1">limit</span> = <span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;limit&#039;</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$countries</span> = countries::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$resStr</span> = <span class="st0">&#034;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$countries</span> <span class="kw1">as</span> <span class="re0">$country</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$resStr</span> .= <span class="re0">$country</span>-&gt;<span class="me1">c_name</span>.<span class="st0">&quot;<span class="es0">\n</span>&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="re0">$resStr</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Здесь мы проверяем, пришли ли параметры и формируем запрос.</p>
<p>Условие записываем с помощью класса <code>CDbCriteria</code>. В атрибуте <code>condition</code> указываем название поля и операцию сравнения (<code>LIKE</code>). В атрибуте <code>params</code> – текст, введенный пользователем. Обратите внимание, мы добавляем к нему знак <code>%</code>, т.е. найдены будут все страны, названия которых начинаются с указанных букв.</p>
<p>Затем добавляем параметр <code>limit</code> и выполняем запрос (<code>findAll</code>).</p>
<p>Из результатов поиска формируем строку с найденными названиями стран. Разделителем служит символ новой строки (это требование плагина). И отправляем результат браузеру.</p>
<p>Как видите, пользоваться виджетом совсем не сложно.</p>
<p>Все вопросы, советы и замечания пишите в комментариях.</p>
<p><strong>Удачи!</strong></p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=1060&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-php-frejmvork-sozdaem-pole-s-avtozapolneniem.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Yii PHP framework: связанные таблицы и limit</title>
		<link>http://www.simplecoding.org/yii-php-framework-svyazannye-tablicy-i-limit.html</link>
		<comments>http://www.simplecoding.org/yii-php-framework-svyazannye-tablicy-i-limit.html#comments</comments>
		<pubDate>Tue, 11 May 2010 09:04:32 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1057</guid>
		<description><![CDATA[Давно я собирался написать этот пост, практически сразу после выхода цикла о создании игрового сайта, но как-то всё время откладывал.
В новых версиях фреймворка Yii (1.1.х) немного изменился принцип использования встроенной библиотеки для работы с базой данных, точнее она стала по-другому формировать SQL запросы при использовании связанных таблиц.
Речь идет об этом изменении.


По умолчанию для всех отношений, [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1058" class="wp-caption alignnone" style="width: 280px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/05/yii_active_record_limit.png" alt="yii active record limit" title="yii active record limit" width="270" height="136" style="float:left" class="size-full wp-image-1058" /><p class="wp-caption-text"> </p></div>
<p>Давно я собирался написать этот пост, практически сразу после выхода цикла о создании <a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-1-postanovka-zadachi.html">игрового сайта</a>, но как-то всё время откладывал.</p>
<p>В новых версиях <strong>фреймворка Yii</strong> (1.1.х) немного изменился принцип использования встроенной библиотеки для работы с базой данных, точнее она стала по-другому формировать <acronym title="Structured Query Language">SQL</acronym> запросы при использовании связанных таблиц.</p>
<p>Речь идет об этом изменении.<br />
<span id="more-1057"></span><br />
<em><br />
<blockquote style="font-size:0.8em">По умолчанию для всех отношений, включенных в &#039;жадную&#039; загрузку, будет сгенерировано и выполнено одно выражение с использованием JOIN. Если в основной таблице есть опции запроса LIMIT или OFFSET, то сначала будет выполнен этот запрос, а затем другой <acronym title="Structured Query Language">SQL</acronym>-запрос, который возвращает все связанные объекты. Раньше, в версии 1.0.x, по умолчанию вызывалось N+1 <acronym title="Structured Query Language">SQL</acronym>-запросов, если &#039;жадная&#039; загрузка включала N отношений HAS_MANY или MANY_MANY.<br />
(перевод взят <a href="http://yiiframework.ru/doc/guide/ru/upgrade">отсюда</a>)</p></blockquote>
<p></em></p>
<p>В моем примере с игровым сайтом как раз возникла такая ситуация. Есть две таблицы, с играми (<code>ygs_games</code>) и их жанрами (<code>ygs_types</code>). Отношение между таблицами многие-ко-многим.</p>
<p>При этом необходимо выводить <strong>игры определённого жанра с разбивкой на страницы</strong> (пагинацией), т.е. использовать в запросе <code>limit</code> и <code>offset</code>.</p>
<p>Yii позволяет сформировать запросы на получение этих данных двумя способами, которые называются: <strong>&#034;жадная&#034; загрузка</strong> и <strong>&#034;ленивая&#034; загрузка</strong>. Первый предполагает формирование одного запроса, в котором будут получены все необходимые данные. В этом запросе будут использованы объединения (JOINs). Во втором случае используется несколько запросов. Сначала выбираются нужные записи из первой таблицы (первый запрос), затем &#8211; данные из связанной таблицы (для каждой записи из первой таблицы выполняется дополнительный запрос).</p>
<p><strong>Проблема</strong>, с которой я столкнулся.</p>
<p>В старых версиях для этих целей можно было использовать следующий код.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$criteria</span>=<span class="kw2">new</span> CDbCriteria;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$criteria</span>-&gt;<span class="me1">condition</span> = <span class="st0">&#039;t_id=:t_id&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$criteria</span>-&gt;<span class="me1">params</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;:t_id&#039;</span>=&gt;<span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$criteria</span>-&gt;<span class="me1">with</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;ygs_types&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;together&#039;</span>=&gt;true<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$pages</span>=<span class="kw2">new</span> CPagination<span class="br0">&#40;</span>Games::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">published</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">count</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$pages</span>-&gt;<span class="me1">pageSize</span>=self::<span class="me2">PAGE_SIZE</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//этот метод добавляет параметры limit и offset в объект $criteria, т.е. в запрос</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$pages</span>-&gt;<span class="me1">applyLimit</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$models</span>=Games::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>здесь <code>t_id</code> &#8211; первичный ключ в таблице жанров.<br />
<code>ygs_types</code> &#8211; название элемента в массиве, который возвращает метод <code>relations()</code> модели (этот элемент просто описывает отношение многие-к-многим).</p>
<p>При этом формировался один запрос по методу &#034;жадной&#034; загрузки, который возвращал все необходимые данные.</p>
<p>Но в новых версиях <strong>Yii</strong> этот код <strong>не работает</strong>.</p>
<p>Дело в том, что как только мы указываем <code>LIMIT</code> или <code>OFFSET</code> в запросе, который включает связанные таблицы, библиотека Yii разбивает запрос на два. Сначала выполняется запрос только к первой таблице и именно к нему применяется LIMIT.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> <span class="st0">`t`</span>.<span class="st0">`g_id`</span> <span class="kw1">AS</span> <span class="st0">`t0_c0`</span>, &#8230; <span class="kw1">FROM</span> <span class="st0">`ygs_games`</span> <span class="st0">`t`</span> &nbsp;<span class="kw1">WHERE</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>g_state=<span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">AND</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#40;</span>t_id=:t_id<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">LIMIT</span> <span class="nu0">10</span>. Bind <span class="kw1">WITH</span> parameter :t_id=<span class="st0">&#039;2&#039;</span></div>
</li>
</ol>
</div>
<p>И сразу же возникает ошибка.</p>
<p><code>Column not found: 1054 Unknown column 't_id' in 'where clause'</code></p>
<p>Причина ошибки в том, что yii пытается вставить параметр для поля <code>t_id</code>, которого нет в таблице <code>ygs_games</code>. Таблица <code>ygs_types</code> будет присоединена в следующем запросе (с помощью JOIN), но LIMIT применяется именно в первом запросе к первой таблице, а нужно, чтобы он применялся к результату объединённого запроса.</p>
<p>Отключить это поведение, судя по всему, нельзя.</p>
<p>Но можно использовать <strong>&#034;ленивую&#034; загрузку</strong>, и при этом будет выполняться также два запроса.</p>
<p>Первым запросом мы находим нужный жанр в таблице <code>ygs_types</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$type</span> = Types::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findByPk</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Тут выполняется следующий запрос</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> * <span class="kw1">FROM</span> <span class="st0">`ygs_types`</span> <span class="st0">`t`</span> <span class="kw1">WHERE</span> <span class="st0">`t`</span>.<span class="st0">`t_id`</span>=<span class="nu0">8</span> <span class="kw1">LIMIT</span> <span class="nu0">1</span></div>
</li>
</ol>
</div>
<p>Затем, получаем связанные с этим жанром игры.<br />
Здесь есть нюанс. Вызов</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$type</span>-&gt;<span class="me1">ygs_games</span></div>
</li>
</ol>
</div>
<p>нам не подходит, т.к. мы не сможем указать параметры, например тот же limit (если нужно его изменять).</p>
<p><em>Примечание</em>. Можно, конечно, указать параметры в массиве, который возвращает метод relations, но этот метод имеет свои недостатки. Например, чтобы изменить параметры (тот же <code>limit</code>), их придется хранить в отдельном массиве, и его нужно будет объединять с массивом, который возвращает <code>relations()</code>.</p>
<p>Поэтому, на мой взгляд, удобнее использовать метод <a href="http://www.yiiframework.com/doc/api/CActiveRecord#getRelated-detail">getRelated</a>, в его третьем  параметре можно передать массив с настройками.<br />
Код будет выглядеть так.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$params</span> = <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;limit&#039;</span>=&gt;self::<span class="me2">PAGE_SIZE</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;condition&#039;</span>=&gt;<span class="st0">&#039;g_state=&#039;</span>.Games::<span class="me2">PUBLISHED</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;order&#039;</span>=&gt;<span class="st0">&#039;g_added DESC&#039;</span>,</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$games</span> = <span class="re0">$type</span>-&gt;<span class="me1">getRelated</span><span class="br0">&#40;</span><span class="st0">&#039;ygs_games&#039;</span>,<span class="kw2">false</span>, <span class="re0">$params</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>При этом Yii формирует следующий запрос (self::PAGE_SIZE = 10)</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> <span class="st0">`ygs_games`</span>.<span class="st0">`g_id`</span> <span class="kw1">AS</span> <span class="st0">`t1_c0`</span>, &#8230; <span class="kw1">FROM</span> <span class="st0">`ygs_games`</span> <span class="st0">`ygs_games`</span> <span class="kw1">INNER</span> <span class="kw1">JOIN</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">`ygs_games_types`</span> <span class="st0">`ygs_games_ygs_games`</span> <span class="kw1">ON</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#40;</span><span class="st0">`ygs_games_ygs_games`</span>.<span class="st0">`gt_type_id`</span>=:ypl0<span class="br0">&#41;</span> <span class="kw1">AND</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#40;</span><span class="st0">`ygs_games`</span>.<span class="st0">`g_id`</span>=<span class="st0">`ygs_games_ygs_games`</span>.<span class="st0">`gt_game_id`</span><span class="br0">&#41;</span> <span class="kw1">WHERE</span> <span class="br0">&#40;</span>g_state=<span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">ORDER</span> <span class="kw1">BY</span> g_added <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">10</span>. Bind <span class="kw1">WITH</span> parameter :ypl0=<span class="st0">&#039;8&#039;</span></div>
</li>
</ol>
</div>
<p>Т.е. именно то, что нам нужно.</p>
<p>Тут есть один <strong>недостаток</strong> &#8211; усложняется код настройки пагинации. Мы должны вручную установить параметры <code>limit</code> и <code>offset</code>.</p>
<p>Полностью метод, формирующий страницу с играми одного жанра выглядит так.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> actionShowGames<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> &amp;&amp; <span class="kw3">is_numeric</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$criteria</span> = <span class="kw2">new</span> CDbCriteria;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$type</span> = Types::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findByPk</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//нужно использовать &quot;ленивую&quot; загрузку (не использовать with)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//иначе не получится указать limit для связанной таблицы</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$params</span> = <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;limit&#039;</span>=&gt;self::<span class="me2">PAGE_SIZE</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;condition&#039;</span>=&gt;<span class="st0">&#039;g_state=&#039;</span>.Games::<span class="me2">PUBLISHED</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;order&#039;</span>=&gt;<span class="st0">&#039;g_added DESC&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//настраиваем пагинацию</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;page&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> &amp;&amp; <span class="kw3">is_numeric</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;page&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$params</span><span class="br0">&#91;</span><span class="st0">&#039;offset&#039;</span><span class="br0">&#93;</span> = <span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;page&#039;</span><span class="br0">&#93;</span> &#8211; <span class="nu0">1</span><span class="br0">&#41;</span> * self::<span class="me2">PAGE_SIZE</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$pages</span>=<span class="kw2">new</span> CPagination<span class="br0">&#40;</span><span class="kw3">count</span><span class="br0">&#40;</span><span class="re0">$type</span>-&gt;<span class="me1">getRelated</span><span class="br0">&#40;</span><span class="st0">&#039;ygs_games&#039;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$pages</span>-&gt;<span class="me1">pageSize</span>=self::<span class="me2">PAGE_SIZE</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$games</span> = <span class="re0">$type</span>-&gt;<span class="me1">getRelated</span><span class="br0">&#40;</span><span class="st0">&#039;ygs_games&#039;</span>,<span class="kw2">false</span>, <span class="re0">$params</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;showGames&#039;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ,<span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;games&#039;</span>=&gt;<span class="re0">$games</span>, <span class="st0">&#039;pages&#039;</span>=&gt;<span class="re0">$pages</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">redirect</span><span class="br0">&#40;</span><span class="st0">&#039;/games/list&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Обратите внимание на строки 16 и 18. В них мы устанавливаем смещение (<code>offset</code>) и создаём объект <code>CPagination</code>. Последнему передаём количество всех игр данного жанра. Для этого просто используем функцию count.</p>
<p>Если кому-то захочется поэкспериментировать, выкладываю архив с изменённым примером.</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2010/05/yii_game_site_new.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p>Чтобы удобнее было сравнивать работу библиотеки, я не удалял старый код создания страниц с жанрами (GamesController.php метод <code>actionList</code>). Новый метод находится в контроллере TypesController.php (метод <code>actionShowGames</code>).</p>
<p>Если есть вопросы или замечания, пишите. Мне будет очень интересно обсудить эту тему <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=1057&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-php-framework-svyazannye-tablicy-i-limit.html/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Изменения в Yii 1.1: CActiveDataProvider</title>
		<link>http://www.simplecoding.org/izmeneniya-v-yii-1-1-cactivedataprovider.html</link>
		<comments>http://www.simplecoding.org/izmeneniya-v-yii-1-1-cactivedataprovider.html#comments</comments>
		<pubDate>Sat, 20 Feb 2010 08:55:13 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=999</guid>
		<description><![CDATA[Я всё-таки решил продолжить обсуждение фреймворка Yii. Но на этот раз затяжных циклов я не планирую   , просто хочу рассказать о некоторых нововведениях в версиии 1.1.
Как вы, наверное, знаете, версия 1.1 довольно сильно отличается от 1.0.х. Есть и инструкция по переходу на новую версию.
Но есть момент, который может вызвать вопросы у тех, кто [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1000" class="wp-caption alignnone" style="width: 286px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/02/yii_data_provider.png" alt="yii data provider" title="yii data provider" width="276" height="140" style="float:left" class="size-full wp-image-1000" /><p class="wp-caption-text"> </p></div>
<p>Я всё-таки решил продолжить обсуждение фреймворка <strong>Yii</strong>. Но на этот раз затяжных циклов я не планирую <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  , просто хочу рассказать о некоторых нововведениях в версиии 1.1.</p>
<p>Как вы, наверное, знаете, версия 1.1 довольно сильно <a href="http://yiiframework.ru/doc/guide/ru/changes">отличается</a> от 1.0.х. Есть и <a href="http://yiiframework.ru/doc/guide/ru/upgrade">инструкция по переходу</a> на новую версию.</p>
<p>Но есть момент, который может вызвать вопросы у тех, кто начинает знакомство с фреймворком с версии 1.1. Речь о классе <a href="http://www.yiiframework.com/doc/api/CActiveDataProvider">CActiveDataProvider</a>. Как несложно догадаться по названию, он предназначен для работы с базой данных. И если вы создадите сайт с помощью консольной утилиты <strong>yiic</strong>, то этот класс будет использован в методах <code>actionIndex</code> и <code>actionAdmin</code> контроллеров.</p>
<p>Класс очень удобный и позволяет сократить объём кода. Проблема в том, что <a href="http://yiiframework.ru/doc/guide/ru/index">документация</a> немного отстаёт от жизни. В разделе о работе с базой данных подробно рассказывается об использовании классов <code>CActiveRecord</code>, <code>CDbCriteria</code> и других, но информация о <code>CActiveDataProvider</code> есть только в <strong><acronym title="Application Programming Interface">API</acronym></strong>.</p>
<p>Итак, что представляет собой этот класс.<br />
<span id="more-999"></span><br />
По большому счёту это обёртка вокруг четырёх классов <code>CActiveRecord</code>, <code>CDbCriteria</code>, <code>CPagination</code> и <code>CSort</code>. Именно с их помощью выполняется основная работа с базой данных и очень часто все эти классы используются одновременно. Поэтому вполне логично, что разработчики решили создать общую оболочку для работы с ними.</p>
<p>Рассмотрим <strong>небольшой пример</strong>.</p>
<p>В версиях 1.0.х для вывода записей какой-нибудь таблицы с разбивкой на страницы (пагинацией) использовался следующий код.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$criteria</span>=<span class="kw2">new</span> CDbCriteria;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$pages</span>=<span class="kw2">new</span> CPagination<span class="br0">&#40;</span>Screenshots::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">count</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$pages</span>-&gt;<span class="me1">pageSize</span>=self::<span class="me2">PAGE_SIZE</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$pages</span>-&gt;<span class="me1">applyLimit</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$sort</span>=<span class="kw2">new</span> CSort<span class="br0">&#40;</span><span class="st0">&#039;Screenshots&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$sort</span>-&gt;<span class="me1">applyOrder</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$models</span>=Screenshots::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;admin&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;models&#039;</span>=&gt;<span class="re0">$models</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;pages&#039;</span>=&gt;<span class="re0">$pages</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="st0">&#039;sort&#039;</span>=&gt;<span class="re0">$sort</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Обратите внимание, что здесь создаются экземпляры <code>CDbCriteria</code>, <code>CPagination</code> и <code>CSort</code>. При этом с помощью <code>CDbCriteria</code> мы можем изменять <acronym title="Structured Query Language">SQL</acronym> запросы, которые создаёт модель (Screenshots). <code>CPagination</code> используется для настройки пагинации, а <code>CSort</code> – сортировки записей. Массив с объектами <code>CActiveRecord</code> возвращает метод <code>findAll</code> модели. Обратите внимание, что для настройки, которые хранятся в <code>CDbCriteria</code> используются всеми остальными классами. </p>
<p>Теперь взгляните на то, как решается эта же задача в версии 1.1.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>=<span class="kw2">new</span> CActiveDataProvider<span class="br0">&#40;</span><span class="st0">&#039;Screenshots&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;pagination&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;pageSize&#039;</span>=&gt;self::<span class="me2">PAGE_SIZE</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;admin&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;dataProvider&#039;</span>=&gt;<span class="re0">$dataProvider</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Правда, значительно лучше выглядит? <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Хотя, на самом деле, работает код точно также. Просто все экземпляры объектов <code>CPagination</code>, <code>CSort</code> и <code>CDbCriteria</code> находятся внутри <code>CActiveDataProvider</code>.</p>
<p>Обратите внимание, что в первом параметре конструктора мы передаём название модели, данные которой нужно получить. <code>CActiveDataProvider</code> сам вызовет соответствующие методы <code>find()</code> или <code>findAll()</code>.</p>
<p>Тут возникает вполне резонный вопрос: «Каким образом настраивать поиск, разбивку на страницы и т.п.?» Всё очень просто, нужно передать массив с соответствующими параметрами в конструкторе. Например.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dataProvider</span>=<span class="kw2">new</span> CActiveDataProvider<span class="br0">&#40;</span><span class="st0">&#039;Post&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;criteria&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;condition&#039;</span>=&gt;<span class="st0">&#039;status=1 AND tags LIKE :tags&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;params&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;:tags&#039;</span>=&gt;<span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;tags&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;with&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;author&#039;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;pagination&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;pageSize&#039;</span>=&gt;<span class="nu0">20</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Как видите, настройки указываются точно так же, как и в предыдущих версиях (по большому счёту это они и есть). Т.е. вы можете спокойно использовать документацию по <code>CDbCriteria</code> при настройке <code>CActiveDataProvider</code>.</p>
<p>Кроме того, если возникнет необходимость, можно использовать методы <code>getCriteria()</code>, <code>setCriteria()</code>, <code>getSort()</code>, <code>setSort()</code> для чтения и установки соответствующих объектов.</p>
<p><strong>Передача данных в представление.</strong></p>
<p>Как несложно заметить по листингам, в версиях 1.0.х необходимо было передавать три параметра: с данными, настройками пагинации и сортировки. В новом варианте передаётся только один – сам объект <code>CActiveDataProvider</code>.</p>
<p>При этом если вы будете вручную вытягивать из него данные, код получится довольно объёмным. Но в версию 1.1 входят компоненты <a href="http://code.google.com/p/zii/">zii</a>, один из которых (<code>zii.widgets.grid.CGridView</code>) специально разработан для использования вместе с <code>CActiveDataProvider</code>. Т.е. вы передаёте ему экземпляр <code>CActiveDataProvider</code> и заголовки столбцов, а он на основе этих данных формирует таблицу.</p>
<p>Как видите, <code>CActiveDataProvider</code> принципиально новых возможностей не добавляет, но количество кода, который вы должны написать, <strong>сокращается значительно</strong>. И при этом не нужно привыкать к новой библиотеке.</p>
<p><strong>Интересно почитать</strong></p>
<p><a href="http://bormaley.com/">Раскрутка сайта</a> занятие увлекательное, но ошибки обойдутся недёшево.</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=999&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/izmeneniya-v-yii-1-1-cactivedataprovider.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.</title>
		<link>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-poisk-oshibok.html</link>
		<comments>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-poisk-oshibok.html#comments</comments>
		<pubDate>Thu, 04 Feb 2010 11:12:15 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=992</guid>
		<description><![CDATA[В этой части цикла мы рассмотрим некоторые возможности, которые предоставляет нам Yii фреймворк для отладки приложения.
Сразу хочу предупредить, эта статья не претендует на полноту. Я расскажу только от тех инструментах, которые использовал при разработке игрового сайта. Более подробную информацию можно найти в разделе Журналирование и Обработка ошибок.
Включаем режим отладки

Для этого во входном скрипте (файл index.php, [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_993" class="wp-caption alignnone" style="width: 247px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/02/yii_game_site_bugs.png" alt="yii game site bugs" title="yii game site bugs" width="237" height="133" class="size-full wp-image-993" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>В этой части цикла мы рассмотрим некоторые возможности, которые предоставляет нам Yii фреймворк для отладки приложения.</p>
<p>Сразу хочу предупредить, эта статья не претендует на полноту. Я расскажу только от тех инструментах, которые использовал при разработке игрового сайта. Более подробную информацию можно найти в разделе <a href="http://www.yiiframework.ru/doc/guide/ru/topics.logging">Журналирование</a> и <a href="http://www.yiiframework.ru/doc/guide/ru/topics.error">Обработка ошибок</a>.</p>
<p><strong>Включаем режим отладки</strong><br />
<span id="more-992"></span><br />
Для этого во входном скрипте (файл <code>index.php</code>, который находится в корневой папки сайта) константе <code>YII_DEBUG</code> должно быть присвоено значение true.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw3">defined</span><span class="br0">&#40;</span><span class="st0">&#039;YII_DEBUG&#039;</span><span class="br0">&#41;</span> or <span class="kw3">define</span><span class="br0">&#40;</span><span class="st0">&#039;YII_DEBUG&#039;</span>,<span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Если для создания приложения вы использовали консольную утилиту <strong>yiic</strong>, то эта строка у вас уже есть. Важно удалить её при переносе на рабочий сервер. Иначе при возникновении ошибок, фреймворк будет показывать посетителям подробные их описания.</p>
<p>Кстати, эти описания сделаны очень неплохо. Вы увидите не только номер, название ошибки и содержимое стека, но и фрагмент кода в котором она возникла (нужная строка будет подсвечена).</p>
<p><strong>Включаем журналирование ошибок</strong></p>
<p>Тут все настройки выполняются в конфигурационном файле (<code>protected/config/main.php</code>). Фреймворк предлагает нам несколько вариантов ведения лога. Это запись в файл, вывод на экран, запись в базу данных, отправка по eMail.</p>
<p>За ведения лога отвечает компонент приложения <code>CLogRouter</code>. Подключаем и настраиваем его.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="st0">&#039;components&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">…</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;log&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;class&#039;</span>=&gt;<span class="st0">&#039;CLogRouter&#039;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;routes&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//выводим лог внизу страницы</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;class&#039;</span>=&gt;<span class="st0">&#039;CWebLogRoute&#039;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;levels&#039;</span>=&gt;<span class="st0">&#039;trace, info, profile&#039;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">…</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span>,</div>
</li>
</ol>
</div>
<p>В массиве <code>components</code> мы создали элемент под названием <code>log</code> и присвоили ему массив с настройками. В элементе <code>class</code> указываем название класса, который отвечает за работу компонента. В данном случае это <code>CLogRouter</code>.</p>
<p>Затем настраиваем маршрутизацию (<code>routes</code>). Именно здесь мы определяем куда какие сообщения будут выведены.</p>
<p>В данном случае использован класс <code>CWebLogRoute</code> это означает, что лог будет добавлен внизу страницы сайта.</p>
<p>Параметр <code>levels</code> определяет, что будут выведены сообщения имеющие уровень <code>trace</code>, <code>info</code> или <code>profile</code>. Всего существует пять уровней сообщений: <code>trace</code>, <code>info</code>, <code>profile</code>, <code>warning</code>, <code>error</code>. И с их помощью вы можете отфильтровать ненужную в данный момент информацию.</p>
<p>При переносе на рабочий сервер <strong>эти настройки очень желательно изменить</strong>. Например, можно использовать классы <code>CFileLogRoute</code> и <code>CEmailLogRoute</code> для записи сообщений в файл и одновременной отправки по eMail. Но во время отладки, лично мне удобнее просто прокрутить страницу и посмотреть сообщения, чем лезть в файл.</p>
<p>Для отправки своих сообщений можно использовать методы</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">Yii::<span class="kw3">log</span><span class="br0">&#40;</span><span class="re0">$message</span>, <span class="re0">$level</span>, <span class="re0">$category</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">Yii::<span class="me2">trace</span><span class="br0">&#40;</span><span class="re0">$message</span>, <span class="re0">$category</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Учтите, что метод trace работает только в режиме отладки. В параметре $message нужно указать текст сообщения, <code>$level</code> – уровень, <code>$category</code> – категория к которой относится сообщение (по-умолчанию равна <code>application</code>, но вы можете указать строку в формате <code>xxx.yyy.zzz</code>, например, <code>system.web.CController</code>, в результате сообщение будет добавляться в лог <code>CController</code>).</p>
<p>В нашем примере внизу страницы появится таблица с системными сообщениями. Вы сможете посмотреть какие компоненты и в каком порядке создавались при формировании страницы.</p>
<p><strong>Отладка запросов к БД</strong></p>
<p>В состав Yii фреймворка входит хорошая библиотека для работы с базой данных. Тем не менее, полезно знать какие именно <strong><acronym title="Structured Query Language">SQL</acronym> запросы</strong> она формирует. Особенно, если у вас нет предварительного опыта работы с ней.</p>
<p>Для того, чтобы включить вывод запросов в лог, необходимо указать параметр <code>'enableParamLogging'=&gt;true</code> в настройках базы.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="st0">&#039;db&#039;</span>=&gt;array<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">…</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;enableParamLogging&#039;</span>=&gt;true,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#039;enableProfiling&#039;</span>=&gt;true,</div>
</li>
<li class="li2">
<div class="de2">…</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span>,</div>
</li>
</ol>
</div>
<p>Кроме того, полезно тут же включить профайлинг работы с базой. Это позволит узнать сколько запросов было выполнено при формировании страницы и время их выполнения.</p>
<p>Для того, чтобы вывести результаты профайлинга открываем макет страницы (<code>protected/views/layouts/main.php</code>) и добавляем в хвостовик пару строчек</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$dbStats</span> = Yii::<span class="me2">app</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">db</span>-&gt;<span class="me1">getStats</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#039;Выполнено запросов: &#039;</span>.<span class="re0">$dbStats</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="st0">&#039; (за &#039;</span>.<span class="kw3">round</span><span class="br0">&#40;</span><span class="re0">$dbStats</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, <span class="nu0">5</span><span class="br0">&#41;</span>.<span class="st0">&#039; сек)&#039;</span>;</div>
</li>
</ol>
</div>
<p>Как видите, мы получили массив в первом элементе которого хранится общее количество запросов, а во втором – время их выполнения.</p>
<p><strong>Выводим информацию об использовании ресурсов</strong></p>
<p>Эти данные мы тоже выведем в хвостовике страницы</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$memory</span> = <span class="kw3">round</span><span class="br0">&#40;</span>Yii::<span class="me2">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">memoryUsage</span>/<span class="nu0">1024</span>/<span class="nu0">1024</span>, <span class="nu0">3</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$time</span> = <span class="kw3">round</span><span class="br0">&#40;</span>Yii::<span class="me2">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">executionTime</span>, <span class="nu0">3</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#039;&lt;br /&gt;Использовано памяти: &#039;</span>.<span class="re0">$memory</span>.<span class="st0">&#039; МБ&lt;br /&gt;&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#039;Время выполнения: &#039;</span>.<span class="re0">$time</span>.<span class="st0">&#039; с&lt;br /&gt;&#039;</span>;</div>
</li>
</ol>
</div>
<p>Для получения этой информации мы использовали класс <a href="http://www.yiiframework.com/doc/api/CLogger">CLogger</a>. Он содержит два нужных нам метода: <code>memoryUsage</code> (возвращает объём использованной памяти, в байтах) и <code>executionTime</code> – время создания страницы.</p>
<p>Как видите, ничего сложного. Если возникли вопросы или есть замечания, пишите, постараюсь ответить <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Все разделы цикла.</strong></p>
<ol style="font-size:80%">
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-1-postanovka-zadachi.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 1. Постановка задачи.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-2-baza-dannyx-i-ustanovka-frejmvorka.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-3-autentifikaciya.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 3. Аутентификация.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-4-rabota-s-zhanrami-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-5-import-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 5. Импорт игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-6-formiruem-stranicy-igr-i-zhanrov.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-7-rabota-s-javascript-i-stranicy-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-sozdayom-vidzhety.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 8. Создаём виджеты.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-poisk-oshibok.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 9. Поиск ошибок.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-10-panel-upravleniya.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 10. Панель управления.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-11-chelovekoponyatnye-url.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 11. Человекопонятные <acronym title="Uniform Resource Locator">URL</acronym>.</a></li>
<li><a href="http://www.simplecoding.org/wp-content/uploads/2010/01/yii_game_site.zip">Архив с исходниками</a></li>
</ol>
<p><strong>Интересно почитать</strong></p>
<p><a href="http://devicecollection.com/vybiraem-sistemu-oxlazhdeniya-dlya-pk.html">Выбираем систему охлаждения для ПК</a>.</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=992&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-poisk-oshibok.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.</title>
		<link>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-sozdayom-vidzhety.html</link>
		<comments>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-sozdayom-vidzhety.html#comments</comments>
		<pubDate>Sat, 30 Jan 2010 13:16:10 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=989</guid>
		<description><![CDATA[В этой части мы поговорим о том, какие средства предоставляет Yii для создания виджетов. Если верить википедии, виджет (widget) – это &#034;контент модуль, который встраивается в веб-страницу или браузер&#034; (вообще, это не совсем точно, в википедии есть несколько определений).
Правда здесь может возникнуть небольшая путаница в терминологии. Дело в том, что некоторые CMS (WordPress, например) используют [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_990" class="wp-caption alignnone" style="width: 272px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/01/yii_game_site_widgets.png" alt="yii_game_site_widgets" title="yii_game_site_widgets" width="262" height="134" style="float:left" class="size-full wp-image-990" /><p class="wp-caption-text"> </p></div>
<p>В этой части мы поговорим о том, какие средства предоставляет <strong>Yii</strong> для создания <strong>виджетов</strong>. Если верить википедии, <strong>виджет</strong> (<strong>widget</strong>) – это &#034;контент модуль, который встраивается в веб-страницу или браузер&#034; (вообще, это не совсем точно, в википедии есть несколько определений).</p>
<p>Правда здесь может возникнуть небольшая путаница в терминологии. Дело в том, что некоторые <acronym title="Content Management System">CMS</acronym> (<strong>WordPress</strong>, например) используют термин виджет для обозначения особых плагинов, которые предназначены для отображения блоков с информацией в сайдбаре. Но сейчас нас интересует <strong>Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework</strong>, поэтому мы будем считать виджетами объекты, которые наследуют класс <a href="http://www.yiiframework.com/doc/api/CWidget">CWidget</a>.</p>
<p>Обычно виджеты используют для отображения какого-нибудь контента, который не зависит от основного содержимого страницы. Например, это может быть форма входа, перечень жанров игр, блок со случайными скриншотами, ссылки на страницы архива и т.п.</p>
<p>Для нас важно, что <code>CWidget</code> имеет особенность. Он является потомком класса <code>CComponent</code>, и, следовательно, является компонентом.</p>
<p>Рассмотрим, как создаются компоненты в фреймворке <strong>Yii</strong>.<br />
<span id="more-989"></span><br />
<strong>Шаг 1. </strong>В папке <code>protected/components</code> создаём файл с классом компонента. Этот класс выполняет инициализацию компонента и подготовку данных (например, чтение из БД).</p>
<p><strong>Шаг 2.</strong> В папке <code>protected/components/views</code> создаём файл с представлением компонента. По-сути это шаблон, который используется для отображения содержимого компонента.</p>
<p><strong>Шаг 3.</strong> Добавляем компонент в макет (layout) нужных страниц сайта. Макеты находятся в папке <code>protected/views/layouts</code>.</p>
<p>Теперь рассмотрим конкретный пример. <strong>Создадим виджет, содержащий ссылки на страницы жанров игр.</strong></p>
<p>Назовём класс <code>TypesMenu</code>.</p>
<p>Создаём файл <code>protected/components/TypesMenu.php</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> TypesMenu <span class="kw2">extends</span> CWidget <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$types</span> = Types::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;typesMenu&#039;</span>,<span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;types&#039;</span>=&gt;<span class="re0">$types</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Как видите, класс содержит один метод (<code>run</code>), который будет вызван фреймворком при создании виджета.</p>
<p>В этом методе мы получаем список всех жанров игр (строка 3) и результат передаём представлению (строка 5).</p>
<p>Создаём представление (файл <code>protected/components/views/typesMenu.php</code>).</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">&lt;h2&gt;Жанры&lt;/h2&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;ul&gt;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$types</span> <span class="kw1">as</span> <span class="re0">$type</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="co1">//каждый пункт списка &#8211; ссылка на страницу с играми данного жанра</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">//жанр указывается с помощью параметра в get запросе &#8211; type_id</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;li&gt;&#039;</span>.CHtml::<span class="kw3">link</span><span class="br0">&#40;</span><span class="re0">$type</span>-&gt;<span class="me1">t_name</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;games/list&#039;</span>, <span class="st0">&#039;type_id&#039;</span>=&gt;<span class="re0">$type</span>-&gt;<span class="me1">t_id</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="st0">&#039;&lt;/li&gt;&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
<li class="li2">
<div class="de2">&lt;/ul&gt;</div>
</li>
</ol>
</div>
<p>Обратите внимание, у нас доступна переменная <code>$types</code>. (её название мы указали при загрузке представления, метод <code>render</code>).</p>
<p>Сами ссылки создаём с помощью метода <code>CHtml::link</code>. В первом параметре указываем текст ссылки, а во втором – массив с параметрами. В данном случае будут созданы url вида<br />
<code>http://yiigame.domen/index.php?r=games/list&#038;type_id=1</code><br />
где <code>type_id</code> – id соответствующего жанра.</p>
<p>Вставляем виджет в макет страницы. Для этого в файл <code>protected/views/layouts/main.php</code> добавляем следующий код.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">&lt;div <span class="kw2">class</span>=<span class="st0">&quot;menu&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="re0">$this</span>-&gt;<span class="me1">widget</span><span class="br0">&#40;</span><span class="st0">&#039;application.components.TypesMenu&#039;</span><span class="br0">&#41;</span>; <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&lt;/div&gt;&lt;!&#8211; menu &#8211;&gt;</div>
</li>
</ol>
</div>
<p>Посмотрите, как указано имя виджета. Перед названием файла виджета (без расширения) мы добавляем <code>application.components</code>, проще говоря, указываем путь к виджету.</p>
<p>Всё, <strong>мы получили работающий виджет</strong>, правда, самый примитивный. Давайте рассмотрим вариант немного посложнее.</p>
<p>На некоторых страницах сайта нам нужно выводить <strong>список с самыми популярными записями</strong>.</p>
<p>Популярность игры мы можем определить, используя поле <code>g_rate</code> (таблица <code>ygs_games</code>), т.е. нам нужно будет при поиске игр в базе просто отсортировать их по этому полю.</p>
<p>Показывать виджет нам нужно на страницах с общим перечнем игр и страницах отдельных жанров. И те, и другие страницы формирует метод <code>actionList</code> (класс <code>GamesController</code>). Но на страницах жанров мы будем показывать топ игр, которые относятся к данному жанру, а не все подряд, т.е. в наш запрос нужно будет добавить дополнительное условие.</p>
<p>Если задача ясна, приступаем.</p>
<p>Создаём файл виджета <code>protected/components/TopGames.php</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> TopGames <span class="kw2">extends</span> CWidget <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$title</span> = <span class="st0">&#039;Популярные игры&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$showOn</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$count</span> = <span class="nu0">10</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//определяем название контроллера и метода (action)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$controller</span> = Yii::<span class="me2">app</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">controller</span>-&gt;<span class="me1">id</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$action</span> = Yii::<span class="me2">app</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">controller</span>-&gt;<span class="me1">action</span>-&gt;<span class="me1">id</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//проверяем нужно ли показывать виджет</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re0">$controller</span>.<span class="st0">&#039;/&#039;</span>.<span class="re0">$action</span>, <span class="re0">$this</span>-&gt;<span class="me1">showOn</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//проверяем, нужно ли выводить игры только данного жанра</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$id</span> = <span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st0">&#039;type_id&#039;</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$params</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;limit&#039;</span>=&gt;<span class="re0">$this</span>-&gt;<span class="me1">count</span>,<span class="st0">&#039;order&#039;</span>=&gt;<span class="st0">&#039;g_rate DESC&#039;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ,<span class="st0">&#039;condition&#039;</span>=&gt;<span class="st0">&#039;t_id=:id&#039;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ,<span class="st0">&#039;params&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;:id&#039;</span>=&gt;<span class="re0">$id</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//ищем игры</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$games</span> = Games::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">getTopGames</span><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#41;</span>-&gt;<span class="me1">published</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">with</span><span class="br0">&#40;</span><span class="st0">&#039;ygs_types&#039;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$params</span> = <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;limit&#039;</span>=&gt;<span class="re0">$this</span>-&gt;<span class="me1">count</span>,<span class="st0">&#039;order&#039;</span>=&gt;<span class="st0">&#039;g_rate DESC&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//ищем игры</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$games</span> = Games::<span class="me2">model</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">getTopGames</span><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#41;</span>-&gt;<span class="me1">published</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">findAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//заполняем массивы с жанрами игр для каждой найденной игры</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//для этого раскодируем поле g_type</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$games</span> <span class="kw1">as</span> <span class="re0">$key</span>=&gt;<span class="re0">$game</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$games</span><span class="br0">&#91;</span><span class="re0">$key</span><span class="br0">&#93;</span>-&gt;<span class="me1">g_types</span> = Yii::<span class="me2">app</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">controller</span>-&gt;_decodeTypes<span class="br0">&#40;</span><span class="re0">$game</span>-&gt;<span class="me1">g_type</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//показываем виджет</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">render</span><span class="br0">&#40;</span><span class="st0">&#039;topGames&#039;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;title&#039;</span>=&gt;<span class="re0">$this</span>-&gt;<span class="me1">title</span>, <span class="st0">&#039;games&#039;</span>=&gt;<span class="re0">$games</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Прежде всего, обратите внимание на три свойства класса <code>$title</code>, <code>$showOn</code> и <code>$count</code>. Фреймворк позволяет указывать значения для всех отрытых (public) свойств виджета при его создании, т.е. в макете (layout) мы можем задать значения для этих свойств. Таким образом, появляется возможность изменять вид виджета, не трогая его код.</p>
<p>В данном случае в свойстве <code>$title</code> мы указываем заголовок виджета, в свойстве <code>$showOn</code> – массив с перечнем страниц, на которых он должен отображаться, а в свойстве <code>$count</code> – количество игр.</p>
<p>Рассмотрим метод <code>run</code>.</p>
<p>Прежде всего, определяем название контроллера и метода (action) (строки 9, 10). И проверяем, нужно ли показывать виджет. Страницы, на которых нужно отображать виджет указываются в формате «название_контроллера/название_метода». Если массив <code>$showOn</code> не содержит подходящего элемента, мы завершаем работу виджета.</p>
<p>В противном случае, мы:</p>
<p>1) Проверяем, является ли эта страница, страницей жанра (получен параметр <code>$_GET['type_id']</code> или нет). Если получен, формируем запрос, при этом в его параметрах мы указываем, что нам нужны игры только текущего жанра.</p>
<p>2) Если мы находимся на странице с общим перечнем игр, то просто получаем игры, отсортированные по полю <code>g_rate</code>.</p>
<p>Обратите внимание на метод <code>getTopGames($params)</code>. Он объявлен в модели (<code>Games</code>) и нужен только для того, чтобы немного сократить запись запроса.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> getTopGames<span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">getDbCriteria</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">mergeWith</span><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$this</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><em>Примечание</em>. Использовать его не обязательно. Можно было просто создать объект <code>CDbCriteria</code>, как мы и делали в предыдущих частях, но я хотел попробовать разные варианты работы.</p>
<p>3) Расшифровываем поле с перечнем жанров (эту операцию мы рассматривали в предыдущих частях).</p>
<p>4) Показываем представление при этом передаём ему заголовок виджета и данные игр.</p>
<p>Само представление выглядит так (файл <code>protected/components/view/topGames.php</code>).</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">&lt;h1&gt;&lt;?php <span class="kw3">echo</span> <span class="re0">$title</span>; ?&gt;&lt;/h1&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$i</span> = <span class="nu0">0</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$games</span> <span class="kw1">as</span> <span class="re0">$n</span>=&gt;<span class="re0">$model</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">//шаблон для вывода игры находится в views/games/_short_desc.php</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">controller</span>-&gt;<span class="me1">renderPartial</span><span class="br0">&#40;</span><span class="st0">&#039;_short_desc&#039;</span>, <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;game&#039;</span>=&gt;<span class="re0">$model</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$i</span> % <span class="nu0">2</span> !== <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&#039;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$i</span>++;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>Как видите, для вывода игры мы использовали представление, которое относится к контроллеру <code>Games</code> (<code>views/games/_short_desc.php</code>).</p>
<p>Последний шаг – подключение шаблона в макете (файл <code>protected/views/layouts/main.php</code>)</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">&lt;div id=<span class="st0">&quot;top_games&quot;</span> <span class="kw2">class</span>=<span class="st0">&quot;grid_9&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="re0">$this</span>-&gt;<span class="me1">widget</span><span class="br0">&#40;</span><span class="st0">&#039;application.components.TopGames&#039;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; , <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#039;title&#039;</span>=&gt;<span class="st0">&#039;Популярные игры&#039;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; ,<span class="st0">&#039;showOn&#039;</span>=&gt;array<span class="br0">&#40;</span><span class="st0">&#039;games/list&#039;</span>,<span class="st0">&#039;types/show&#039;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; ,<span class="st0">&#039;count&#039;</span>=&gt;<span class="nu0">4</span><span class="br0">&#41;</span><span class="br0">&#41;</span>; <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&lt;/div&gt;&lt;!&#8211; top_games &#8211;&gt;</div>
</li>
</ol>
</div>
<p>Тут стоит отметить <strong>передачу параметров виджету</strong>. Они должны быть записаны в виде массива. При этом, ключ элемента должен совпадать с именем соответствующего свойства класса.</p>
<p>На этом мы остановимся. Думаю, общее представление о виджетах у вас появилось. Но в этой статье рассмотрены далеко не все их возможности, поэтому очень советую почитать соответствующий <a href="http://yiiframework.ru/doc/guide/ru/basics.view">раздел справки</a>.</p>
<p>Продолжение следует <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Все разделы цикла.</strong></p>
<ol style="font-size:80%">
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-1-postanovka-zadachi.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 1. Постановка задачи.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-2-baza-dannyx-i-ustanovka-frejmvorka.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-3-autentifikaciya.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 3. Аутентификация.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-4-rabota-s-zhanrami-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-5-import-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 5. Импорт игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-6-formiruem-stranicy-igr-i-zhanrov.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-7-rabota-s-javascript-i-stranicy-igr.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-sozdayom-vidzhety.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 8. Создаём виджеты.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-poisk-oshibok.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 9. Поиск ошибок.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-10-panel-upravleniya.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 10. Панель управления.</a></li>
<li><a href="http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-11-chelovekoponyatnye-url.html" rel="bookmark" title="Ссылка на &quot;Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.&quot;">Yii <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> framework: создаём игровой сайт. Часть 11. Человекопонятные <acronym title="Uniform Resource Locator">URL</acronym>.</a></li>
<li><a href="http://www.simplecoding.org/wp-content/uploads/2010/01/yii_game_site.zip">Архив с исходниками</a></li>
</ol><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=989&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-php-framework-sozdayom-igrovoj-sajt-chast-8-sozdayom-vidzhety.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Управление jqGrid с помощью поля с автозавершением</title>
		<link>http://www.simplecoding.org/upravlenie-jqgrid-s-pomoshhyu-polya-s-avtozaversheniem.html</link>
		<comments>http://www.simplecoding.org/upravlenie-jqgrid-s-pomoshhyu-polya-s-avtozaversheniem.html#comments</comments>
		<pubDate>Tue, 17 Nov 2009 14:26:50 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=943</guid>
		<description><![CDATA[Сегодня я продолжу рассказывать о плагине jqGrid и покажу еще один пример его использования.
Если не ошибаюсь, это уже 5-ый пост об этом плагине, поэтому я не буду останавливаться на его установке и настройке. Лучше приведу ссылки на предыдущие части:
1) Query Grid Plugin – &#034;продвинутое&#034; решение для создания таблиц
2) jqGrid: редактирование табличных данных с помощью inline [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_944" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/11/jqGrid_autocomplete.png" alt="jqGrid_autocomplete" title="jqGrid_autocomplete" width="300" height="175" class="size-full wp-image-944" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Сегодня я продолжу рассказывать о плагине <strong>jqGrid</strong> и покажу еще один пример его использования.</p>
<p>Если не ошибаюсь, это уже 5-ый пост об этом плагине, поэтому я не буду останавливаться на его установке и настройке. Лучше приведу <strong>ссылки на предыдущие части</strong>:</p>
<p>1) <a href="http://www.simplecoding.org/jquery-grid-plugin-prodvinutoe-reshenie-dlya-sozdaniya-tablic.html">Query Grid Plugin – &#034;продвинутое&#034; решение для создания таблиц</a></p>
<p>2) <a href="http://www.simplecoding.org/jqgrid-redaktirovanie-tablichnyx-dannyx-s-pomoshhyu-inline-redaktorov.html">jqGrid: редактирование табличных данных с помощью inline редакторов</a></p>
<p>3) <a href="http://www.simplecoding.org/jqgrid-sozdanie-dopolnitelnyx-knopok.html">jqGrid – создание дополнительных кнопок</a></p>
<p>4) <a href="http://www.simplecoding.org/jqgrid-poisk-dannyx.html">jqGrid – поиск данных</a></p>
<p>Но для тех, кто их не читал, кратко поясню, о чем вообще речь.</p>
<p><strong>jqGrid</strong> – это плагин для библиотеки <strong>jQuery</strong>, предназначенный для работы с табличными данными. Он поддерживает кучу полезных возможностей вроде разбивки данных на страницы, поиска, добавления, удаления, редактирования записей и т.п.</p>
<p>Естественно, у плагина очень много настроек и вариантов использования, но это не означает, что их хватит на все случаи жизни <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Например, раньше я рассказывал об использовании <a href="http://www.simplecoding.org/jqgrid-poisk-dannyx.html">встроенной формы поиска jqGrid</a>. Но иногда удобнее использовать <strong>отдельную форму, содержащую поля с автозавершением</strong>. Под ними по мере набора слова будут появляться варианты, а когда посетитель выберет один из них, то автоматически обновиться таблица с данными.</p>
<p>Как это работает, вы можете посмотреть на демо-страничке</p>
<p><a href="http://demosites.org.ua/jqgridautocomplete/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a></p>
<p>либо скачать архив с примером и установить его на своем сервере</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2009/11/jqgrid_autocomplete.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p>Реализовать такую систему не сложно.<br />
<span id="more-943"></span><br />
Потребуются:</p>
<p>1) Библиотека <a href="http://jquery.com/">jQuery</a>.</p>
<p>2) Плагин <a href="http://www.trirand.com/blog/">jqGrid</a>.</p>
<p>3) Плагин для создания поля с автозаполением. Я выбрал <a href="http://www.devbridge.com/projects/autocomplete/jquery/">Ajax AutoComplete for jQuery</a>.</p>
<p>Теперь рассмотрим сам пример.</p>
<p><strong>1) Клиентская часть.</strong> Тут нам нужно создать только страничку с таблицей и формой, которая содержит поле с автозаполнением (index.html).</p>
<blockquote style="white-space: nowrap; overflow:auto; margin: 10px 0 10px 0; border: dotted 1px #aeaeae; background-color: #f0f0f0;"><p><code><font size="2" face="Courier New" color="black">
<ol>
<li><font color="#0000ff">&#60;!</font><font color="#800000">DOCTYPE</font> <font color="#ff0000">html</font> <font color="#ff0000">PUBLIC</font> <font color="#0000ff">"-//<acronym title="World Wide Web Consortium">W3C</acronym>//<acronym title="Document Type Definition">DTD</acronym> <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> 1.1//EN"</font> <font color="#0000ff">"http://www.w3.org/TR/xhtml11/<acronym title="Document Type Definition">DTD</acronym>/xhtml11.dtd"</font><font color="#0000ff">&#62;</font></li>
<li><font color="#0000ff">&#60;</font><font color="#800000">html</font> <font color="#ff0000">xmlns</font><font color="#0000ff">="http://www.w3.org/1999/xhtml"</font> <font color="#ff0000">xml:lang</font><font color="#0000ff">="en"</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;</li>
<li><font color="#0000ff">&#60;</font><font color="#800000">head</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">title</font><font color="#0000ff">&#62;</font>jqGrid + Autocomplete<font color="#0000ff">&#60;/</font><font color="#800000">title</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">meta</font> <font color="#ff0000">http-equiv</font><font color="#0000ff">="content-type"</font> <font color="#ff0000">content</font><font color="#0000ff">="text/html;charset=utf-8"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">meta</font> <font color="#ff0000">http-equiv</font><font color="#0000ff">="Content-Style-Type"</font> <font color="#ff0000">content</font><font color="#0000ff">="text/css"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">link</font> <font color="#ff0000">rel</font><font color="#0000ff">="stylesheet"</font> <font color="#ff0000">type</font><font color="#0000ff">="text/css"</font> <font color="#ff0000">media</font><font color="#0000ff">="screen"</font> <font color="#ff0000">href</font><font color="#0000ff">="css/reset.css"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">link</font> <font color="#ff0000">rel</font><font color="#0000ff">="stylesheet"</font> <font color="#ff0000">type</font><font color="#0000ff">="text/css"</font> <font color="#ff0000">media</font><font color="#0000ff">="screen"</font> <font color="#ff0000">href</font><font color="#0000ff">="css/smoothness/jquery-ui-1.7.2.custom.css"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">link</font> <font color="#ff0000">rel</font><font color="#0000ff">="stylesheet"</font> <font color="#ff0000">type</font><font color="#0000ff">="text/css"</font> <font color="#ff0000">media</font><font color="#0000ff">="screen"</font> <font color="#ff0000">href</font><font color="#0000ff">="css/ui.jqgrid.css"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">link</font> <font color="#ff0000">rel</font><font color="#0000ff">="stylesheet"</font> <font color="#ff0000">type</font><font color="#0000ff">="text/css"</font> <font color="#ff0000">media</font><font color="#0000ff">="screen"</font> <font color="#ff0000">href</font><font color="#0000ff">="css/styles.css"</font> <font color="#0000ff">/&#62;</font></li>
<li><font color="#0000ff">&#60;/</font><font color="#800000">head</font><font color="#0000ff">&#62;</font></li>
<li><font color="#0000ff">&#60;</font><font color="#800000">body</font><font color="#0000ff">&#62;</font></li>
<li><font color="#0000ff">&#60;</font><font color="#800000">div</font> <font color="#ff0000">id</font><font color="#0000ff">="container"</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">h1</font><font color="#0000ff">&#62;</font>jqGrid + Autocomplete<font color="#0000ff">&#60;/</font><font color="#800000">h1</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">table</font> <font color="#ff0000">id</font><font color="#0000ff">="list"</font><font color="#0000ff">&#62;&#60;/</font><font color="#800000">table</font><font color="#0000ff">&#62;</font> </li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">div</font> <font color="#ff0000">id</font><font color="#0000ff">="pager"</font><font color="#0000ff">&#62;&#60;/</font><font color="#800000">div</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">form</font> <font color="#ff0000">action</font><font color="#0000ff">="#"</font> <font color="#ff0000">method</font><font color="#0000ff">="post"</font> <font color="#ff0000">id</font><font color="#0000ff">="autocomplete_form"</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">p</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">label</font> <font color="#ff0000">for</font><font color="#0000ff">="city_field"</font><font color="#0000ff">&#62;</font>Название города<font color="#0000ff">&#60;/</font><font color="#800000">label</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&#60;</font><font color="#800000">input</font> <font color="#ff0000">type</font><font color="#0000ff">="text"</font> <font color="#ff0000">id</font><font color="#0000ff">="city_field"</font> <font color="#ff0000">name</font><font color="#0000ff">="city_field"</font> <font color="#ff0000">size</font><font color="#0000ff">="20"</font> <font color="#0000ff">/&#62;</font></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&#60;/</font><font color="#800000">p</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">&#60;/</font><font color="#800000">form</font><font color="#0000ff">&#62;</font></li>
<li>&nbsp;&nbsp;...</li>
<li><font color="#0000ff">&#60;/</font><font color="#800000">div</font><font color="#0000ff">&#62;</font></li>
<li><font color="#0000ff">&#60;/</font><font color="#800000">body</font><font color="#0000ff">&#62;</font></li>
<li><font color="#0000ff">&#60;/</font><font color="#800000">html</font><font color="#0000ff">&#62;</font></li>
<p></font></ol>
<p><font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font></code></p></blockquote>
<p><font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font></code></p></blockquote>
<p><strong>2) Подключение и настройка плагинов</strong>. Этот код добавляем в конец файла index.html перед закрывающим тегом body.</p>
<blockquote style="white-space: nowrap; overflow:auto; margin: 10px 0 10px 0; border: dotted 1px #aeaeae; background-color: #f0f0f0;"><p><code><font size="2" face="Courier New" color="black">
<ol>
<li>&#60;script src=<font color="#A31515">"js/jquery-1.3.2.min.js"</font> type=<font color="#A31515">"text/javascript"</font>&#62;&#60;/script&#62;</li>
<li>&#60;script src=<font color="#A31515">"js/jquery-ui-1.7.2.custom.min.js"</font> type=<font color="#A31515">"text/javascript"</font>&#62;&#60;/script&#62;</li>
<li>&#60;script src=<font color="#A31515">"js/i18n/grid.locale-ru.js"</font> type=<font color="#A31515">"text/javascript"</font>&#62;&#60;/script&#62;</li>
<li>&#60;script src=<font color="#A31515">"js/jquery.jqGrid.min.js"</font> type=<font color="#A31515">"text/javascript"</font>&#62;&#60;/script&#62;</li>
<li>&#60;script src=<font color="#A31515">"js/jquery.autocomplete-min.js"</font> type=<font color="#A31515">"text/javascript"</font>&#62;&#60;/script&#62;</li>
<li>&#60;script type=<font color="#A31515">"text/javascript"</font>&#62;</li>
<li>$(<font color="#0000ff">function</font>() {</li>
<li>&nbsp;&nbsp;<font color="#008000">//настройка плагина jqGrid</font></li>
<li>&nbsp;&nbsp;jQuery(<font color="#A31515">"#list"</font>).jqGrid({</li>
<li>&nbsp;&nbsp;&nbsp;url:<font color="#A31515">'getdata.php'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;datatype: <font color="#A31515">'json'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;mtype: <font color="#A31515">'POST'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;colNames:[<font color="#A31515">'Город'</font>,<font color="#A31515">'Страна'</font>],</li>
<li>&nbsp;&nbsp;&nbsp;colModel :[ </li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;{name:<font color="#A31515">'city'</font>, index:<font color="#A31515">'city'</font>, width:350}, </li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;{name:<font color="#A31515">'country'</font>, index:<font color="#A31515">'country'</font>, width:350}</li>
<li>&nbsp;&nbsp;&nbsp;],</li>
<li>&nbsp;&nbsp;&nbsp;pager: <font color="#A31515">'#pager'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;rowNum:10,</li>
<li>&nbsp;&nbsp;&nbsp;rowList:[10,20,30],</li>
<li>&nbsp;&nbsp;&nbsp;sortname: <font color="#A31515">'country'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;sortorder: <font color="#A31515">'desc'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;viewrecords: <font color="#0000ff">true</font>,</li>
<li>&nbsp;&nbsp;&nbsp;caption: <font color="#A31515">'Города Украины и России'</font></li>
<li>&nbsp;&nbsp;}).navGrid(<font color="#A31515">'#pager'</font>, {edit:<font color="#0000ff">false</font>,add:<font color="#0000ff">false</font>,del:<font color="#0000ff">false</font>,refresh:<font color="#0000ff">true</font>,search:<font color="#0000ff">false</font>});</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//эта функция добавляет GET параметр в запрос на получение</font></li>
<li>&nbsp;&nbsp;<font color="#008000">//данных для таблицы и обновляет её</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">function</font> updateTable(value) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;jQuery(<font color="#A31515">"#list"</font>)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setGridParam({url:<font color="#A31515">"getdata.php?sel_city="</font>+value, page:1})</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.trigger(<font color="#A31515">"reloadGrid"</font>); </li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//настройка плагина Autocomplete</font></li>
<li>&nbsp;&nbsp;<font color="#008000">//при возникновении события onSelect вызываем функцию updateTable</font></li>
<li>&nbsp;&nbsp;$(<font color="#A31515">'#city_field'</font>).autocomplete({</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;serviceUrl:<font color="#A31515">'search.php'</font>,</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;maxHeight:150,</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;onSelect: <font color="#0000ff">function</font>(value) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateTable(value);</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;});</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//этот обработчик используется если посетитель ввел название города</font></li>
<li>&nbsp;&nbsp;<font color="#008000">//и нажал Enter</font></li>
<li>&nbsp;&nbsp;$(<font color="#A31515">'#autocomplete_form'</font>).submit(<font color="#0000ff">function</font>() {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;updateTable($(<font color="#A31515">'#city_field'</font>).val());</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">return</font> <font color="#0000ff">false</font>;</li>
<li>&nbsp;&nbsp;});</li>
<li>});</li>
<li>&#60;/script&#62;</li>
<p></font></ol>
<p><font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font></code></p></blockquote>
<p>Для демонстрационных целей я использовал урезанную базу данных городов России и Украины, поэтому таблица содержит 2 поля: название города и название страны. На настройках отображения полей и таблицы я останавливаться не буду, т.к. уже об этом <a href="http://www.simplecoding.org/jquery-grid-plugin-prodvinutoe-reshenie-dlya-sozdaniya-tablic.html">рассказывал</a>.</p>
<p>Тут гораздо интереснее другой момент – источники данных.</p>
<p>И для поля, и для таблицы данные приходят в <strong>JSON</strong> формате, но для таблицы их формирует скрипт <code>getdata.php</code>, а для поля - <code>search.php</code>. Почему используются разные скрипты? Дело в том, что для плагина автозаполнения нужно меньше данных (только название города), чем для таблицы, и их структура отличается, а вводить какие-нибудь специальные параметры в запрос мне показалось не самым лучшим решением.</p>
<p><strong>3) Связываем плагины между собой.</strong> Тут нам нужно чтобы при выборе посетителем города из списка произошло обновление данных в таблице.</p>
<p>Для этого мы в обработчик события <code>onSelect</code> (строки 40-42) добавили вызов функции <code>updateTable</code> и передали ей название города.</p>
<p>Теперь нам нужно обновить таблицу, но при этом необходимо как-то указать, что мы хотим получить данные только для выбранного города. Т.к. таблица с данными формируется серверным php скриптом, то нам нужно создать дополнительный параметр и добавить его к запросу.</p>
<p>Для этого с помощью метода <code>setGridParam</code> изменяем параметр <code>url</code> на<br />
<code>getdata.php?sel_city="+value</code><br />
т.е. мы добавили GET параметр <code>sel_city</code>.<br />
Затем вызываем метод <code>trigger("reloadGrid")</code>, который запускает обновление таблицы.</p>
<p>Еще я добавил вызов функции <code>updateTable</code> в обработчик отправки формы (строки 47-50). На случай если пользователь введет название города и нажмет Enter.</p>
<p><strong>4) Создаем серверные скрипты.</strong></p>
<p>Для автозаполнения (<code>search.php</code>)</p>
<blockquote style="white-space: nowrap; overflow:auto; margin: 10px 0 10px 0; border: dotted 1px #aeaeae; background-color: #f0f0f0;"><p><code><font size="2" face="Courier New" color="black">
<ol>
<li>&#60;?php</li>
<li>require_once(<font color="#A31515">'dbdata.php'</font>);</li>
<li>&nbsp;</li>
<li><font color="#0000ff">try</font> {</li>
<li>&nbsp;&nbsp;<font color="#008000">//читаем параметры</font></li>
<li>&nbsp;&nbsp;$s_query = $_GET[<font color="#A31515">'query'</font>];</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//подключаемся к базе</font></li>
<li>&nbsp;&nbsp;$dbh = <font color="#0000ff">new</font> PDO(<font color="#A31515">'mysql:host='</font>.$dbHost.<font color="#A31515">';dbname='</font>.$dbName, $dbUser, $dbPass);</li>
<li>&nbsp;&nbsp;<font color="#008000">//указываем, что нужно использовать utf8</font></li>
<li>&nbsp;&nbsp;$dbh-&#62;exec(<font color="#A31515">'SET CHARACTER SET utf8'</font>);</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;$stmt = $dbh-&#62;prepare(<font color="#A31515">'SELECT city FROM cities WHERE city LIKE :query'</font>);</li>
<li>&nbsp;&nbsp;$search = $s_query.<font color="#A31515">'%'</font>;</li>
<li>&nbsp;&nbsp;$stmt-&#62;bindParam(<font color="#A31515">':query'</font>, $search);</li>
<li>&nbsp;&nbsp;$stmt-&#62;execute();</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;$i=0;</li>
<li>&nbsp;&nbsp;$response-&#62;query = $s_query;</li>
<li>&nbsp;&nbsp;$response-&#62;suggestions = array();</li>
<li>&nbsp;&nbsp;<font color="#0000ff">while</font>($row = $stmt-&#62;fetch(PDO::FETCH_ASSOC)) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$response-&#62;suggestions[]=$row[<font color="#A31515">'city'</font>];</li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;echo json_encode($response);</li>
<li>}</li>
<li><font color="#0000ff">catch</font> (PDOException $e) {</li>
<li>&nbsp;&nbsp;echo <font color="#A31515">'Database error: '</font>.$e-&#62;getMessage();</li>
<li>}</li>
<li>&nbsp;</li>
<li>// end of search.php</li>
<p></font></ol>
<p><font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font></code></p></blockquote>
<p>Тут, набранные пользователем буквы мы получаем в параметре <code>$_GET['query']</code>.</p>
<p>После этого выполняется один запрос к базе данных (строки 13-16), который находит список всех городов, начинающихся с этих букв.</p>
<p>Затем мы формируем массив с ответом (строки 19-23) и отправляем его браузеру.</p>
<p><em>Примечание</em>. Структура массива описана в документации к плагину, вам нужно только ее соблюдать.</p>
<p>Скрипт для заплнения таблицы (<code>getdata.php</code>).</p>
<blockquote style="white-space: nowrap; overflow:auto; margin: 10px 0 10px 0; border: dotted 1px #aeaeae; background-color: #f0f0f0;"><p><code><font size="2" face="Courier New" color="black">
<ol>
<li>&#60;?php</li>
<li>require_once(<font color="#A31515">'dbdata.php'</font>);</li>
<li>&nbsp;</li>
<li><font color="#0000ff">try</font> {</li>
<li>&nbsp;&nbsp;<font color="#008000">//читаем параметры</font></li>
<li>&nbsp;&nbsp;$curPage = $_POST[<font color="#A31515">'page'</font>];</li>
<li>&nbsp;&nbsp;$rowsPerPage = $_POST[<font color="#A31515">'rows'</font>];</li>
<li>&nbsp;&nbsp;$sortingField = $_POST[<font color="#A31515">'sidx'</font>];</li>
<li>&nbsp;&nbsp;$sortingOrder = $_POST[<font color="#A31515">'sord'</font>];</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;$selCity = <font color="#0000ff">null</font>;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">if</font> (isset($_GET[<font color="#A31515">'sel_city'</font>])) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$selCity = $_GET[<font color="#A31515">'sel_city'</font>];</li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//подключаемся к базе</font></li>
<li>&nbsp;&nbsp;$dbh = <font color="#0000ff">new</font> PDO(<font color="#A31515">'mysql:host='</font>.$dbHost.<font color="#A31515">';dbname='</font>.$dbName, $dbUser, $dbPass);</li>
<li>&nbsp;&nbsp;<font color="#008000">//указываем, что нужно использовать utf8</font></li>
<li>&nbsp;&nbsp;$dbh-&#62;exec(<font color="#A31515">'SET CHARACTER SET utf8'</font>);</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//определяем количество записей в таблице</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">if</font> (<font color="#0000ff">null</font> === $selCity) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$rows = $dbh-&#62;query(<font color="#A31515">'SELECT COUNT(id) AS count FROM cities'</font>);</li>
<li>&nbsp;&nbsp;} <font color="#0000ff">else</font> {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$rows = $dbh-&#62;query(<font color="#A31515">'SELECT COUNT(id) AS count FROM cities WHERE city='</font>.$dbh-&#62;quote($selCity));</li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;$totalRows = $rows-&#62;fetch(PDO::FETCH_ASSOC);</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;$firstRowIndex = $curPage * $rowsPerPage - $rowsPerPage;</li>
<li>&nbsp;&nbsp;<font color="#008000">//получаем список городов из базы</font></li>
<li>&nbsp;&nbsp;<font color="#0000ff">if</font> (<font color="#0000ff">null</font> === $selCity) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$res = $dbh-&#62;query(<font color="#A31515">'SELECT * FROM cities ORDER BY '</font>.$sortingField.<font color="#A31515">' '</font>.$sortingOrder.<font color="#A31515">' LIMIT '</font>.$firstRowIndex.<font color="#A31515">', '</font>.$rowsPerPage);</li>
<li>&nbsp;&nbsp;} <font color="#0000ff">else</font> {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$res = $dbh-&#62;query(<font color="#A31515">'SELECT * FROM cities WHERE city='</font>.$dbh-&#62;quote($selCity).<font color="#A31515">' ORDER BY '</font>.$sortingField.<font color="#A31515">' '</font>.$sortingOrder.<font color="#A31515">' LIMIT '</font>.$firstRowIndex.<font color="#A31515">', '</font>.$rowsPerPage);</li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;<font color="#008000">//сохраняем номер текущей страницы, общее количество страниц и общее количество записей</font></li>
<li>&nbsp;&nbsp;$response-&#62;page = $curPage;</li>
<li>&nbsp;&nbsp;$response-&#62;total = ceil($totalRows[<font color="#A31515">'count'</font>] / $rowsPerPage);</li>
<li>&nbsp;&nbsp;$response-&#62;records = $totalRows[<font color="#A31515">'count'</font>];</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;$i=0;</li>
<li>&nbsp;&nbsp;<font color="#0000ff">while</font>($row = $res-&#62;fetch(PDO::FETCH_ASSOC)) {</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$response-&#62;rows[$i][<font color="#A31515">'id'</font>]=$row[<font color="#A31515">'id'</font>];</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$response-&#62;rows[$i][<font color="#A31515">'cell'</font>]=array($row[<font color="#A31515">'city'</font>], $row[<font color="#A31515">'country'</font>]);</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$i++;</li>
<li>&nbsp;&nbsp;}</li>
<li>&nbsp;&nbsp;echo json_encode($response);</li>
<li>}</li>
<li><font color="#0000ff">catch</font> (PDOException $e) {</li>
<li>&nbsp;&nbsp;echo <font color="#A31515">'Database error: '</font>.$e-&#62;getMessage();</li>
<li>}</li>
<li>&nbsp;</li>
<li>// end of getdata.php</li>
<p></font></ol>
<p><font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font></code></p></blockquote>
<p>Тут код выглядит немного сложнее, но это только из-за использования пагинации (разбивки на страницы). На самом деле большую его часть я просто скопировал из документации к jqGrid (к тому же, он <a href="http://www.simplecoding.org/jquery-grid-plugin-prodvinutoe-reshenie-dlya-sozdaniya-tablic.html">уже обсуждался</a>).</p>
<p>Обратить внимание нужно на обработку параметра <code>sel_city</code> (строки 12, 22 и 31).</p>
<p>Если этот параметр получен, то в запрос на поиск данных мы добавляем условие <code>WHERE city=…</code>, если нет – берем из базы все города подряд.</p>
<p>Я надеюсь, что у вас не возникнет проблем с этим примером. Идея ведь достаточно простая: добавить параметр с нужными данными к запросу и обработать его в серверном скрипте.</p>
<p>Инструкции по установке и настройке примера есть в архиве.</p>
<p>И, конечно, я буду рад услышать ваше мнение <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>UPD 21.06.2010</strong> В этом примере обнаружилась недоработка. Оказалось, что <acronym title="Internet Explorer">IE</acronym> не хочет передавать название города в UTF-8 (название вставляется в <acronym title="Uniform Resource Locator">URL</acronym>, т.е. на сервер приходит в GET параметре). Для решения необходимо перед отправкой закодировать название города с помощью encodeURIComponent (в браузере) и раскодировать с помощью rawurldecode (на сервере).</p>
<p><strong>Интересно почитать</strong></p>
<p>Несколько способов о том <a href="http://blog-invest.ru/kak-zarabotat-studentu/" title="заработок для студента">как заработать студенту</a> в наше время.</p>
<p>Руководителям: <a href="http://busins.ru/uslugi_po_vedeniju_buhucheta">оказание услуг бухучета</a> позволяет сэкономить на штатном бухгалтере</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=943&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/upravlenie-jqgrid-s-pomoshhyu-polya-s-avtozaversheniem.html/feed</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>RedBean PHP ORM – за и против</title>
		<link>http://www.simplecoding.org/redbean-php-orm-za-i-protiv.html</link>
		<comments>http://www.simplecoding.org/redbean-php-orm-za-i-protiv.html#comments</comments>
		<pubDate>Thu, 08 Oct 2009 10:36:24 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=923</guid>
		<description><![CDATA[Приветствую всех!
Сегодня я хочу рассказать о небольшой ORM библиотеке под названием RedBean с которой я на днях экспериментировал.
Прежде всего, пару слов о ORM (англ. Object-relational mapping, русск. Объектно-реляционная проекция) вообще.
Основное назначение таких библиотек – преобразование объектов, которые используются в программах, в записи реляционных баз данных и обратно.
Дело в том, что все данные в БД хранятся [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_917" class="wp-caption alignnone" style="width: 288px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/redbean_logo.png" alt="redbean_logo" title="redbean_logo" width="278" height="143" style="float:left" class="size-full wp-image-917" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>Сегодня я хочу рассказать о небольшой <strong>ORM</strong> библиотеке под названием <a href="http://www.redbeanphp.com">RedBean</a> с которой я на днях экспериментировал.</p>
<p>Прежде всего, пару слов о <strong>ORM</strong> (англ. Object-relational mapping, русск. Объектно-реляционная проекция) вообще.</p>
<p>Основное назначение таких библиотек – преобразование объектов, которые используются в программах, в записи реляционных баз данных и обратно.</p>
<p>Дело в том, что все данные в БД хранятся в таблицах (аналог двумерных массивов), а объекты могут быть организованы в сложные иерархии (например, объект типа «Post» может содержать массив объектов типа «Comment»). И для того, чтобы сохранить такую структуру в БД нужно использовать несколько таблиц с дополнительными полями, которые устанавливают связи между записями.</p>
<p><strong>Все это увеличивает сложность <acronym title="Structured Query Language">SQL</acronym> запросов и время разработки.</strong></p>
<p>ORM библиотеки могут в таких ситуациях значительно упрощают жизнь разработчику. Но, естественно, за все нужно платить. В данном случае счет вы получите в виде повышенного потребления ресурсов.</p>
<p><strong>Вернемся к RedBean.</strong><br />
<span id="more-923"></span><br />
Проиллюстрировать работу любой библиотеки проще всего на примере. Поэтому я написал небольшой скрипт.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> </div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">include</span> <span class="st0">&#039;oodb.php&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//подключаемся к БД</span></div>
</li>
<li class="li2">
<div class="de2">RedBean_Setup::<span class="me2">kickstartDev</span><span class="br0">&#40;</span><span class="st0">&#039;Post,Comment&#039;</span>,<span class="st0">&#039;mysql:host=localhost;dbname=my_database&#039;</span>, <span class="st0">&#039;user_name&#039;</span>, <span class="st0">&#039;password&#039;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$post</span> = <span class="kw2">new</span> Post<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$post</span>-&gt;<span class="me1">title</span> = <span class="st0">&#039;Новая запись&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$post</span>-&gt;<span class="me1">content</span> = <span class="st0">&#039;Просто какой-то текст&#039;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$id</span> = <span class="re0">$post</span>-&gt;<span class="me1">save</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$comment</span> = <span class="kw2">new</span> Comment;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$comment</span>-&gt;<span class="me1">author</span> = <span class="st0">&#039;admin&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$comment</span>-&gt;<span class="me1">text</span> = <span class="st0">&#039;Очень простой комментарий&#039;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$comment</span>-&gt;<span class="me1">belongsTo</span><span class="br0">&#40;</span><span class="re0">$post</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&lt;!DOCTYPE html <span class="kw2">PUBLIC</span> <span class="st0">&quot;-//<acronym title="World Wide Web Consortium">W3C</acronym>//<acronym title="Document Type Definition">DTD</acronym> <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> 1.0 Transitional//EN&quot;</span> <span class="st0">&quot;http://www.w3.org/TR/xhtml1/<acronym title="Document Type Definition">DTD</acronym>/xhtml1-transitional.dtd&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;html xmlns=<span class="st0">&quot;http://www.w3.org/1999/xhtml&quot;</span> xml:lang=<span class="st0">&quot;en&quot;</span> lang=<span class="st0">&quot;en&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;head&gt;</div>
</li>
<li class="li2">
<div class="de2">&lt;meta http-equiv=<span class="st0">&quot;Content-Type&quot;</span> content=<span class="st0">&quot;text/html; charset=utf-8&quot;</span> /&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;meta name=<span class="st0">&quot;language&quot;</span> content=<span class="st0">&quot;en&quot;</span> /&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;title&gt;Test RedBean&lt;/title&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;/head&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&lt;body&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;ul&gt;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$posts</span> = Post::<span class="me2">listAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$posts</span> <span class="kw1">as</span> <span class="re0">$post</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$curPost</span> = <span class="kw2">new</span> Post<span class="br0">&#40;</span><span class="re0">$post</span><span class="br0">&#91;</span><span class="st0">&#039;id&#039;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;li&gt;&lt;strong&gt;&#039;</span>.<span class="re0">$curPost</span>-&gt;<span class="me1">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="st0">&#039;&lt;/strong&gt;&lt;br /&gt;&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="re0">$curPost</span>-&gt;<span class="me1">getContent</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$comments</span> = <span class="re0">$curPost</span>-&gt;<span class="me1">getRelatedComment</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;ol&gt;&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$comments</span> <span class="kw1">as</span> <span class="re0">$comment</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;li&gt;&#039;</span>.<span class="re0">$comment</span>-&gt;<span class="me1">text</span>.<span class="st0">&#039; (&#039;</span>.<span class="re0">$comment</span>-&gt;<span class="me1">author</span>.<span class="st0">&#039;)&lt;/li&gt;&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#039;&lt;/ol&gt;&lt;/li&gt;&#039;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&lt;/ul&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;/body&gt;</div>
</li>
<li class="li2">
<div class="de2">&lt;/html&gt;</div>
</li>
</ol>
</div>
<p>Посмотрим, что он делает.</p>
<p>1) <strong>Подключаем библиотеку</strong> (строка 2). Тут объяснять нечего, <strong>RedBean</strong> состоит всего из одного файла.</p>
<p>2) <strong>Подключаемся к базе данных и создаем объекты, которые будем в ней хранить</strong> (строка 5).<br />
Обе операции выполняются с помощью метода <code>kickstartDev</code>. В первом параметре мы указываем перечень нужных объектов (они будут создаваться динамически). В остальных параметрах – данные, необходимые для подключения к базе (dns, имя пользователя и пароль).</p>
<p>Предварительно от нас требуется только создать пустую БД. Созданием таблиц, сохранением и чтением данных будет заниматься RedBean.</p>
<p><em>Примечание</em>. Метод <code>kickstartDev</code> переводит библиотеку в т.н. <strong>fluid</strong> режим. При этом если вы измените, количество или названия свойств объектов, то RedBean автоматически изменит структуру таблиц в БД. Этот режим имеет смысл использовать во время разработки. После переноса приложения на «боевой» сервер <code>kickstartDev</code> лучше заменить на <code>kickstartFrozen</code>. Библиотека перейдет во frozen режим, при этом таблицы автоматически изменяться не будут, но и потребление ресурсов сократится.</p>
<p>3) <strong>Создаем данные и сохраняем их в БД</strong> (строки 7-15).</p>
<p>В данном случае создано два объекта типов <code>Post</code> и <code>Comment</code>, каждый из которых содержит несколько свойств.<br />
Обратите внимание, что свойства создаются автоматически. От нас требуется указать только название свойства и его значение.<br />
Мы просто присваиваем значения нужным свойствам и вызываем метод <code>save()</code>, который записывает объект в БД (строка 10).</p>
<p>Объект <code>Comment</code> принадлежит <code>Post</code>. Эту связь мы устанавливаем с помощью метода <code>belongsTo</code>. При этом использовать save не нужно. Сохранение в БД произойдет автоматически.</p>
<p>4) <strong>Читаем данные из базы</strong> (строки 29-40).<br />
Тут тоже все достаточно прозрачно. С помощью статического метода <code>listAll</code> мы получаем массив со всеми объектами типа <code>Post</code>, находящимися в БД.</p>
<p>Чтобы получить доступ к комментариям мы создаем объект типа <code>Post</code> (строка 31) и при этом в качестве параметра указываем <code>id</code>.</p>
<p>После этого мы можем использовать метод <code>getRelatedComment</code> для получения массива с комментариями.<br />
Примечание. Название метода <code>getRelatedComment</code> формируется следующим образом. К приставке <code>getRelated</code> добавляется имя объекта, который мы хотим получить.</p>
<p>Затем в цикле мы выводим комментарии.</p>
<p>В результате выполнения скрипта вы увидите такую страницу.</p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/pic1.png" alt="pic1" title="pic1" width="340" height="82" class="alignnone size-full wp-image-918" /></p>
<p><strong>Теперь посмотрим, что у нас делается с базой данных.</strong></p>
<p>Прежде всего, взгляните на перечень таблиц.</p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/pic2.png" alt="pic2" title="pic2" width="466" height="190" class="alignnone size-full wp-image-919" /></p>
<p>Как видите, RedBean создал 6 таблиц. Три из них (post, comment_post и comment) используются для хранения данных приложения, остальные – используются самой RedBean.</p>
<p>Теперь посмотрим, что сохранено в самих таблицах.</p>
<p><strong>post</strong></p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/pic3.png" alt="pic3" title="pic3" width="366" height="47" class="alignnone size-full wp-image-920" /></p>
<p><strong>comment_post</strong></p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/pic4.png" alt="pic4" title="pic4" width="280" height="48" class="alignnone size-full wp-image-921" /></p>
<p><strong>comment</strong></p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2009/10/pic5.png" alt="pic5" title="pic5" width="367" height="48" class="alignnone size-full wp-image-922" /></p>
<p>Думаю, вы уже догадались, в чем дело.</p>
<p>Между объектами Post и Comment отношение типа ОДИН-К-МНОГИМ и для его реализации не нужна промежуточная таблица. Т.е. если бы база создавалась вручную, мы бы обошлись всего двумя таблицами. Соответственно, упрощаются и <acronym title="Structured Query Language">SQL</acronym> запросы.</p>
<p><strong>Использовать или не использовать?</strong></p>
<p>Это вопрос философский <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  . RedBean не единственная ORM библиотека. Например, существуют более мощные <a href="http://propel.phpdb.org/trac/">Propel</a> и <a href="http://www.doctrine-project.org/">Doctrine</a>.</p>
<p>Ответ будет зависеть от требований к конкретному приложению. В общем случае при использовании ORM увеличивается скорость разработки и упрощается поддержка, но при этом растет потребление ресурсов.</p>
<p>К тому же стоит учесть время, необходимое на изучение библиотеки. В этом RedBean значительно превосходит библиотеки типа Doctrine. Вряд ли у вас уйдет больше пары дней на эксперименты с RedBean.</p>
<p>В общем, думаю, что в ряде случаев использование RedBean будет вполне оправданно.</p>
<p>В заключение хочу сказать, что это статью нельзя рассматривать как руководство по использованию библиотеки. Поэтому я очень рекомендую вам почитать документацию на сайте.</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=923&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/redbean-php-orm-za-i-protiv.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>PHP скрипт: ToDo с картинками</title>
		<link>http://www.simplecoding.org/php-skript-todo-s-kartinkami.html</link>
		<comments>http://www.simplecoding.org/php-skript-todo-s-kartinkami.html#comments</comments>
		<pubDate>Thu, 13 Aug 2009 19:01:21 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[htaccess]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=885</guid>
		<description><![CDATA[Уделяете ли вы внимание организации своей работы?
Много ли у вас &#034;мелких&#034; дел, о которых вы регулярно забываете?
Вроде бы простые вопросы, но для многих людей (и я не исключение) организация работы – это актуальная проблема.
Хуже всего, когда нужно сделать много «мелких» дел, которые не занимают много времени, но обязательно должны быть выполнены вовремя&#8230; и держать в [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_886" class="wp-caption alignnone" style="width: 320px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/08/simple_tasks.png" alt="simple tasks" title="simple tasks" width="310" height="129" class="size-full wp-image-886" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Уделяете ли вы внимание организации своей работы?<br />
Много ли у вас &#034;мелких&#034; дел, о которых вы регулярно забываете?</p>
<p>Вроде бы простые вопросы, но для многих людей (и я не исключение) <strong>организация работы</strong> – это актуальная проблема.</p>
<p>Хуже всего, когда нужно сделать много «мелких» дел, которые не занимают много времени, но обязательно должны быть выполнены вовремя&#8230; и держать в голове их все просто невозможно.</p>
<p>Естественно, разработчики реагируют на потребности рынка, и на сегодняшний день создано множество программ-органайзеров, различных напоминалок и т.п.<br />
Примеры создания ToDo списков часто приводят в учебниках по программированию.</p>
<p>Я решил не оставаться в стороне и сделал <strong>собственный вариант такого ToDo списка, естественно, с некоторыми дополнительными возможностями</strong>.</p>
<p>Кстати, скрипт называется <strong>SimpleTasks</strong>.</p>
<p>Главная особенность – <strong>возможность указывать состояние выполнения задач</strong>. При этом используется специальная система обозначений.<br />
<span id="more-885"></span></p>
<div id="attachment_887" class="wp-caption alignnone" style="width: 490px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/08/symbols_for_paper_notebook_with_description.png" alt="symbols for paper notebook with description" title="symbols for paper notebook with description" width="480" height="192" class="size-full wp-image-887" /><p class="wp-caption-text"> </p></div>
<p>Систему обозначений придумал не я. <del datetime="2009-08-14T13:47:28+00:00">Но, к сожалению, не могу найти первоисточник</del> (UPD. Огромное спасибо <a href="http://i-smarty.com">Smarty</a> за ссылку на <a href="http://font.is/?p=790">оригинал</a>). Предназначена она для использования с бумажным блокнотом и довольно удобная. Во всяком случае, читать такой список задач становится намного легче. Взгляд сразу отбрасывает выполненные задачи.</p>
<p>Но <strong>возможности web приложений намного шире</strong>, чем у обычного ежедневника. Например, можно сделать систему фильтров и легко работать с большими списками задач.</p>
<p>В общем, я написал небольшое web приложение, использующее эту систему обозначений.</p>
<p>Если есть желание, можете поиграться с ним (логин admin@todo.loc, пароль password).</p>
<p><a href="http://demosites.org.ua/simpletasks/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a></p>
<p>Или скачать архив и установить на своем сервере (инструкция в архиве).</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2009/08/simpletasks.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p><strong>Принцип работы.</strong></p>
<p><strong>Создание новой записи.</strong><br />
Кликаем по ссылке &#034;Новая запись&#034; (справа в верхней части страницы) и в открывшемся окне вводим данные записи.<br />
При клике по полю &#034;Дата&#034; будет открыт календарь. Т.е. ввести дату в неправильном формате довольно проблематично.</p>
<p><strong>Редактирование.</strong><br />
Клик или двойной клик на соответствующем поле позволяет изменить его. Открываетеся либо диалог, либо inline редактор.</p>
<p><strong>Удаление.</strong><br />
Кликните по картинке с изображением крестика в соответствующей строке и подтвердите удаление.</p>
<p><strong>Фильтры.</strong><br />
Позволяют выбрать задачи с определенным состоянием в указанном диапазоне дат.</p>
<p>Ссылки в верхнем меню дублируют наиболее распространенные (на мой взгляд) фильтры.</p>
<p><strong>Состояние работ.</strong><br />
На данный момент это только бета версия.<br />
Еще не доделана локализация. Доступен только один вариант &#8211; русский.<br />
Возможно, отсутствуют некоторые сообщения об ошибках.</p>
<p>Скорее всего, некоторые функции будут дорабатываться.</p>
<p><strong>И я очень хочу услышать ваше мнение!<br />
</strong><br />
Прежде всего, меня интересуют такие вопросы.</p>
<p>1) Есть ли смысл делать подобное приложение многопользовательским? Т.е. технически это совсем не сложно, вопрос в том будет ли кто-то в рамках небольшой организации использовать такое приложение для хранения заметок сотрудников?</p>
<p>2) Какие еще функии вы бы добавили?</p>
<p>3) Может кто-то видел хороший тьюториал о локализации <acronym title="JavaScript">JS</acronym> приложений? (Сейчас я ориентируюсь на то, как сделана локализация в jQuery UI).</p>
<p><strong>P.S.</strong> На этих выходных я уезжаю догуливать остатки отпуска, поэтому прошу прощения, если не сразу отвечу на ваши комментарии. Я обязательно их прочитаю&#8230; даже спаммерские <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=885&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/php-skript-todo-s-kartinkami.html/feed</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
		<item>
		<title>Phing: backup и сохранение в Subversion базы данных</title>
		<link>http://www.simplecoding.org/phing-backup-i-soxranenie-v-subversion-bazy-dannyx.html</link>
		<comments>http://www.simplecoding.org/phing-backup-i-soxranenie-v-subversion-bazy-dannyx.html#comments</comments>
		<pubDate>Mon, 29 Jun 2009 13:47:29 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Phing]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=859</guid>
		<description><![CDATA[В этой заметке я хочу показать несложный пример использования Phing для создания резервных копий базы данных (MySQL) и их отправки в репозиторий Subversion.
Ни для одной из этих операций готовых задач для Phing я не нашел. Но, если подумать, они и не очень нужны. Ведь с помощью Phing можно выполнить любую команду. Т.е. если вы знаете [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_861" class="wp-caption alignnone" style="width: 258px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/06/phing_mysql_subversion.png" alt="phing mysql subversion" title="phing mysql subversion" width="248" height="141" class="size-full wp-image-861" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>В этой заметке я хочу показать несложный пример использования <a href="http://phing.info/trac/">Phing</a> для создания резервных копий базы данных (<strong>MySQL</strong>) и их отправки в репозиторий <strong>Subversion</strong>.</p>
<p>Ни для одной из этих операций готовых задач для <strong>Phing</strong> я не нашел. Но, если подумать, они и не очень нужны. Ведь с помощью Phing можно выполнить любую команду. Т.е. если вы знаете как решить задачу с помощью консоли, значит вы можете автоматизировать решение с помощью Phing.</p>
<p><em>Примечание</em>. Если вы слышите слово Phing впервые, то, думаю, вам будет интересно почитать статью <a href="http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html">Программирование на <acronym title="PHP: Hypertext Preprocessor">PHP</acronym>. Избавляемся от рутинных операций с помощью Phing</a>, а может быть и весь раздел <a href="http://www.simplecoding.org/category/phing">Phing</a> этого блога <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Возвращаемся к нашей задаче.</strong></p>
<p>Для создания резервной копии базы можно использовать утилиту <strong>mysqldump</strong>. В её параметрах нужно указать имя пользователя базы, его пароль и название базы. Дополнительно нужно задать имя файла в который мы сохраняем дамп.</p>
<p>Например, так<br />
<span id="more-859"></span></p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">mysqldump -uпользователь -pпароль название_базы &gt; dump.sql</div>
</li>
</ol>
</div>
<p>Для сохранения файла в <strong>Subversion</strong> используется команда <strong>commit</strong>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">svn.exe commit -m “db_backup” &#8211;username имя &#8211;password пароль имя_файла</div>
</li>
</ol>
</div>
<p>Здесь мы указываем текст сообщения (после параметра -m), имя пользователя Subversion, его пароль и имя файла, который нужно сохранить.</p>
<p><em>Примечание</em>. Подробнее об этой системе контроля версий можно почитать в разделе <a href="http://www.simplecoding.org/category/sv">Subversion</a>.</p>
<p>Теперь рассмотрим build-файл.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;UTF-8&quot;</span><span class="re2">?&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;project</span> <span class="re0">name</span>=<span class="st0">&quot;DbBackup&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;commit&quot;</span> <span class="re0">basedir</span>=<span class="st0">&quot;.&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;DUMP_FILE&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;dump.sql&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;MYSQL_PATH&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;путь_к_mysql&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;DB_NAME&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;имя_базы_данных&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;DB_HOST&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;localhost&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;DB_USER&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;имя_пользователя_mysql&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;DB_PASS&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;пароль_mysql&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;SVN_USER&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;имя_пользователя_subversion&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;SVN_PASS&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;пароль_subversion&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;backup&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;exec</span> <span class="re0">command</span>=<span class="st0">&quot;${MYSQL_PATH}mysqldump -u${DB_USER} -p${DB_PASS} ${DB_NAME} &gt;</span> ${DUMP_FILE}&quot; dir=&quot;.&quot; /&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3">&lt;/target&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3">&lt;target name=&quot;</span>commit<span class="st0">&quot; depends=&quot;</span>backup<span class="st0">&quot;&gt;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3">&lt;exec command=&quot;</span>svn.exe commit -m <span class="st0">&quot;db_backup&quot;</span> &#8211;username $<span class="br0">&#123;</span>SVN_USER<span class="br0">&#125;</span> &#8211;password $<span class="br0">&#123;</span>SVN_PASS<span class="br0">&#125;</span> $<span class="br0">&#123;</span>DUMP_FILE<span class="br0">&#125;</span><span class="st0">&quot; dir=&quot;</span>.<span class="st0">&quot; /&gt;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3">&lt;/target&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3">&lt;/project&gt;</span></span></div>
</li>
</ol>
</div>
<p>Как видите, большую часть файла занимают свойства (имена, пароли, адрес сервера, размещение mysqldump).</p>
<p>В принципе, их можно было указать прямо в командах, но в большинстве случаев build-файлы гораздо сложнее. И сложно сказать заранее, что какое-то значение будет использован только один раз. Поэтому удобнее задать их один раз в начале файла.</p>
<p>Для выполнение наших команд мы использовали стандартную задачу <strong>exec</strong>. Как несложно догадаться она просто выполняет указанную команду.</p>
<p>Обратите внимание, что внутри команды использовать кавычки нельзя. Их заменяют эскейп последовательностью <code>&quot;</code>.</p>
<p>Думаю, вы догадались, что используя такие build-файлы можно автоматизировать работу с любыми консольными программами.</p>
<p>Конечно, создание самого build-файла отнимает немного времени, но вы быстро его вернете и, кроме того, будете делать меньше ошибок (особенно если нужно выполнять длинные последовательности операций).</p>
<p>И в заключение, небольшой совет. По-умолчанию Phing <strong>не</strong> выводит результат выполнения команды. Т.е. вы не знаете выполнилась на самом деле команда или нет.</p>
<p>Например, если в данном примере написать <code>sbn.exe</code> вместо <code>svn.exe</code> и запустить этот build-файл, то в результате вы увидите обычное сообщение <code>BUILD FINISHED</code>. Естественно, новая версия файла в репозитории сохранена не будет.</p>
<p>Поэтому на этапе тестирования очень полезно запускать phing с параметром -verbose.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">phing -verbose</div>
</li>
</ol>
</div>
<p>В этом случае вы увидите множество интересных сообщений и в том числе</p>
<p>“sbn.exe” не является внутренней или внешней командой …</p>
<p>После того, как вы убедитесь, что всё работает правильно, можно перейти обычный режим.</p>
<p>Время – деньги. Цените его! <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=859&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/phing-backup-i-soxranenie-v-subversion-bazy-dannyx.html/feed</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>
