<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2russianfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0">

<channel>
	<title>WEB рукоделие</title>
	
	<link>http://www.handmadesite.net</link>
	<description>Какой механизм?! Все вручную!</description>
	<lastBuildDate>Mon, 14 Jun 2010 10:27:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/handmadesite" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="handmadesite" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>55.778552</geo:lat><geo:long>37.548244</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by/3.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://lenta.yandex.ru/settings.xml?name=feed&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fhandmadesite" src="http://lenta.yandex.ru/i/addfeed.gif">?????? ? ??????.?????</feedburner:feedFlare><item>
		<title>Множественные уязвимости Shop-Script</title>
		<link>http://www.handmadesite.net/2010/06/mnozhestvennyie-uyazvimosti-shop-script/</link>
		<comments>http://www.handmadesite.net/2010/06/mnozhestvennyie-uyazvimosti-shop-script/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 10:27:37 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[Shop-Script]]></category>
		<category><![CDATA[безопасность]]></category>
		<category><![CDATA[уязвимость]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=365</guid>
		<description><![CDATA[По привычке, время от времени, просматриваю сообщения об уязвимости скрипта Shop-Script. Компания Артикус, автор этого скрипта, уже давно перестала его поддерживать и продает теперь новую версию, более навороченную и красивую. Тем не менее этот скрипт разошелся по сети в миллионах копий, как легальных, так и нелегальных. А также породил великое множество продолжений и улучшений. Поэтому [...]]]></description>
			<content:encoded><![CDATA[<p>По привычке, время от времени, просматриваю сообщения об уязвимости скрипта Shop-Script. <a href="http://www.articus.ru/" target="_blank">Компания Артикус</a>, автор этого скрипта, уже давно перестала его поддерживать и продает теперь новую версию, более навороченную и красивую. Тем не менее этот скрипт разошелся по сети в миллионах копий, как легальных, так и нелегальных. А также породил великое множество продолжений и улучшений. Поэтому обнаруженный мною отчет, несмотря на то, что ему уже 2 месяца, будет интересен многим.</p>
<p>В отчете рассматривался Shop-Script Free &#8212; это как раз бесплатная версия того, что ходит по интернету огромным тиражом. На Free версии основана <a href="http://lego.piconline.ru/" target="_blank">наиболее цельная и популярная доработка под названием &laquo;Shop-Script Free Lego Edition&raquo;</a>.</p>
<p>Вывод неутешительный. На 14 апреля в скрипте имелось <a href="http://www.vupen.com/english/advisories/2010/0882" target="_blank">27 уязвимостей, позволяющих атакующему получить доступ к базе данных, манипулировать данными и скомпрометировать систему</a>.</p>
<p>В частности ошибки, позволяющие выполнять команды SQL, в обработке параметров, передаваемых в скрипт: (1) add2cart, (2) c_id, (3) categoryID, (4)  list_price, (5) name, (6) new_offer, (7) price, (8) product_code, (9)  productID, (10) rating, and (11) save_product. <a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-1463" target="_blank">Пруфлинк</a>.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/w-wmAXgXyh5IKYbCOP9tlpQ5tyw/0/da"><img src="http://feedads.g.doubleclick.net/~a/w-wmAXgXyh5IKYbCOP9tlpQ5tyw/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/w-wmAXgXyh5IKYbCOP9tlpQ5tyw/1/da"><img src="http://feedads.g.doubleclick.net/~a/w-wmAXgXyh5IKYbCOP9tlpQ5tyw/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=DgmyzXKyEUo:6kJfwUYaPac:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=DgmyzXKyEUo:6kJfwUYaPac:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=DgmyzXKyEUo:6kJfwUYaPac:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=DgmyzXKyEUo:6kJfwUYaPac:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=DgmyzXKyEUo:6kJfwUYaPac:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=DgmyzXKyEUo:6kJfwUYaPac:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/DgmyzXKyEUo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2010/06/mnozhestvennyie-uyazvimosti-shop-script/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Тот же контент, только в профиль</title>
		<link>http://www.handmadesite.net/2010/04/tot-zhe-kontent-tolko-v-profil/</link>
		<comments>http://www.handmadesite.net/2010/04/tot-zhe-kontent-tolko-v-profil/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 11:18:55 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[Поисковики]]></category>
		<category><![CDATA[canonical]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=354</guid>
		<description><![CDATA[Давно думал над проблемой одинаковых страниц. Ну, почти одинаковых &#8212; где один и тот же контент по-разному представлен. Обычно это индексные страницы, типа прайслистов, списков статей, постов или чего-то такого. На большинстве таких страниц есть возможность получить список, скажем, отсортированный по каком-либо критерию &#8212; цене, дате публикации и т.д. Таким образом на сайте получаются фактически [...]]]></description>
			<content:encoded><![CDATA[<p>Давно думал над проблемой одинаковых страниц. Ну, почти одинаковых &#8212; где один и тот же контент по-разному представлен. Обычно это индексные страницы, типа прайслистов, списков статей, постов или чего-то такого. На большинстве таких страниц есть возможность получить список, скажем, отсортированный по каком-либо критерию &#8212; цене, дате публикации и т.д. Таким образом на сайте получаются фактически одинаковые страницы, с одним и те-же или похожим содержанием, но разными URL. Например с сортировкой по-умолчанию, по цене и по названию:</p>
<pre>http://www.example.com/products/prices

http://www.example.com/products/prices/index/order:price

http://www.example.com/products/prices/index/order:title
</pre>
<p>Мне кажется, что поисковому роботу такое может и не понравится, уж больно это смахивает на попытку заспамить поисковик. Я раздумывал о том, что,наверное, такие страницы, в URL которых указаны подобные параметры неплохо бы, наверное, закрывать от индексирования. Обычными директивами meta в заголовке страницы.<span id="more-354"></span></p>
<p>Поскольку никаких санкций в отношении таких страниц от поисковиков не наблюдалось, все эти раздумья относились к теории, нигде я эту идею не применял. Просто держал в голове, что, когда буду менять в коде надо позаботиться и об этом вопросе. Не профиту ради, а для чистоты веба вообще :)</p>
<p>Совсем небольшая заковыка в разрезе CakePHP состояла в том, что для кейка без разницы URL http://www.example.com/products/prices и http://www.example.com/products/prices/index &#8212; надо было бы как-то эту ситуацию обрабатывать.</p>
<p>Совсем недавно наткнулся на решение этой <a href="http://www.google.com/support/blogger/bin/answer.py?hl=ru&amp;answer=139394" target="_blank">проблемы &laquo;похожих страниц&raquo; в гугловской документации к платформе Blogger</a>. Не совсем понятно, почему они именно там это разместили, поскольку это было бы полезно всем владельцам сайтов, а не только авторам блогов на платформе Blogger.</p>
<p>Оказывается Google отлично понимает атрибут rel=&quot;canonical&quot;. Т.е. в заголовке (в разделе &lt;head&gt;) страниц размещаем элемент:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;canonical&quot; href=&quot;http://www.example.com/prices&quot; /&gt;</pre></div></div>

<p>и больше не паримся. В атрибуте href этого элемента указан адрес &laquo;основной&raquo; (&laquo;канонической&raquo; в терминах Google) страницы. Поисковик обещает учитывать такие ссылки и стараться выдавать клиентам адрес именно этой страницы.</p>
<p>Ссылка может быть как относительной, так и абсолютной. Но Google рекомендует ставить абсолютную. Можно, кстати, попробовать указать страницу на другом домене &#8212; это тоже не возбраняется.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/rkYCgXB79HCsTgdkFbC4LxQF3lo/0/da"><img src="http://feedads.g.doubleclick.net/~a/rkYCgXB79HCsTgdkFbC4LxQF3lo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/rkYCgXB79HCsTgdkFbC4LxQF3lo/1/da"><img src="http://feedads.g.doubleclick.net/~a/rkYCgXB79HCsTgdkFbC4LxQF3lo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=dchOzZzdWkg:PNwCoMTuMs8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=dchOzZzdWkg:PNwCoMTuMs8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=dchOzZzdWkg:PNwCoMTuMs8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=dchOzZzdWkg:PNwCoMTuMs8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=dchOzZzdWkg:PNwCoMTuMs8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=dchOzZzdWkg:PNwCoMTuMs8:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/dchOzZzdWkg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2010/04/tot-zhe-kontent-tolko-v-profil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Список всех-всех контроллеров</title>
		<link>http://www.handmadesite.net/2009/11/all-controllers-of-app/</link>
		<comments>http://www.handmadesite.net/2009/11/all-controllers-of-app/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 10:58:38 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[CakePHP]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=344</guid>
		<description><![CDATA[Понадобилось мне получить список всех контроллеров приложения, включая контроллеры плагинов. Configure::listObjects, увы, такого не умеет. Этот метод выдает только все контроллеры приложения, но без контроллеров плагинов. Пришлось немного адаптировать метод, предложенный Rob Weaver в гуглогруппе CakePHP. На выходе у моего метода получается объединенный список контроллеров. Основные &#8212; как отдает метод listObjects, а принадлежащие плагинам в [...]]]></description>
			<content:encoded><![CDATA[<p>Понадобилось мне получить список всех контроллеров приложения, включая контроллеры плагинов. Configure::listObjects, увы, такого не умеет. Этот метод выдает только все контроллеры приложения, но без контроллеров плагинов. Пришлось немного адаптировать метод, <a href="http://groups.google.com/group/cake-php/browse_thread/thread/ba66cb8ff0d60957/0f7a7d48ac988c32?lnk=gst&amp;q=listobjects+plugin+controller#0f7a7d48ac988c32" target="_blank">предложенный</a> <a href="http://groups.google.com/groups/profile?enc_user=aYwLfxIAAAAlIZ7IWf4E4HkoLpEPQXFa8rhlH0Pnl47z4AZhN98BFg" target="_blank">Rob Weaver</a> в <a href="http://groups.google.com/group/cake-php" target="_blank">гуглогруппе CakePHP</a>. На выходе у моего метода получается объединенный список контроллеров. Основные &#8212; как отдает метод listObjects, а принадлежащие плагинам в виде &laquo;Plugin.Controller&raquo;. Можно их поочередно скармливать сразу в App::import. Разве что выбрость те, названия которых на &laquo;App&raquo; заканчивается, если они не нужны. Будете загружать, помните, что <a href="http://www.handmadesite.net/2009/11/loding-controllers/">класс &laquo;Controller&raquo; уже должен быть загружен</a>.</p>
<p><span id="more-344"></span>
<p><strong>Update.</strong> Метод Folder::findRecursive возвращал слишком много файлов, в том числе и ненужных. Переписал немного, теперь опрашиваем только директорию с плагином и его контроллерами.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Lists the names of controllers including plugin controllers
 * 
 * @return array
 */</span>
static <span style="color: #000000; font-weight: bold;">function</span> listControllers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Core'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'File'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Folder'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$controllers</span> <span style="color: #339933;">=</span> Configure<span style="color: #339933;">::</span><span style="color: #004000;">listObjects</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'controller'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> Configure<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pluginPaths</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$pluginPath</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$folder</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Folder<span style="color: #009900;">&#40;</span><span style="color: #000088;">$pluginPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$plugin_dirs</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">read</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$plugin_dirs</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$plugin_dir</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$pluginName</span> <span style="color: #339933;">=</span> Inflector<span style="color: #339933;">::</span><span style="color: #004000;">camelize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$plugin_dir</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cd</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pluginPath</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$plugin_dir</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$controllerFiles</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'.*_controller\.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cd</span><span style="color: #009900;">&#40;</span>Folder<span style="color: #339933;">::</span><span style="color: #004000;">addPathElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">path</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'controllers'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$controllerFiles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controllerFiles</span><span style="color: #339933;">,</span><span style="color: #000088;">$folder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'.*_controller\.php'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$controllerFiles</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$controllers</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$pluginName</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'.'</span> <span style="color: #339933;">.</span>
                    Inflector<span style="color: #339933;">::</span><span style="color: #004000;">camelize</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span>
                    <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'_controller.php'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$controllers</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p><a href="http://feedads.g.doubleclick.net/~a/m99QDOWN9nXf_ESSaYjMj7RHMiA/0/da"><img src="http://feedads.g.doubleclick.net/~a/m99QDOWN9nXf_ESSaYjMj7RHMiA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/m99QDOWN9nXf_ESSaYjMj7RHMiA/1/da"><img src="http://feedads.g.doubleclick.net/~a/m99QDOWN9nXf_ESSaYjMj7RHMiA/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=hS65vaP9ZLU:YfavyuIKskU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=hS65vaP9ZLU:YfavyuIKskU:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=hS65vaP9ZLU:YfavyuIKskU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=hS65vaP9ZLU:YfavyuIKskU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=hS65vaP9ZLU:YfavyuIKskU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=hS65vaP9ZLU:YfavyuIKskU:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/hS65vaP9ZLU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/11/all-controllers-of-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Попробуем почитать между строк</title>
		<link>http://www.handmadesite.net/2009/11/lets-try-to-read-between-lines/</link>
		<comments>http://www.handmadesite.net/2009/11/lets-try-to-read-between-lines/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 17:22:03 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[Поисковики]]></category>
		<category><![CDATA[yandex]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=337</guid>
		<description><![CDATA[Очередное интервью с представителями Яндекса, на этот раз на Roem.Ru. Никаких особенных откровений, конечно, нет. Что же вы хотели, чтоб яндексоиды всем бесплатно раздали рекомендации, как выбраться на первое место в выдаче по любому запросу? Но все-таки что-то надо говорить и из обтекаемых формулировок можно выстраивать разные забавные предположения. Лично я не завсегдатай SEO-форумов, возможно, [...]]]></description>
			<content:encoded><![CDATA[<p>Очередное <a href="http://roem.ru/2009/11/23/shestnadtsat_voprosov_yandexu/" target="_blank">интервью с представителями Яндекса</a>, на этот раз на Roem.Ru. Никаких особенных откровений, конечно, нет. Что же вы хотели, чтоб яндексоиды всем бесплатно раздали рекомендации, как выбраться на первое место в выдаче по любому запросу? Но все-таки что-то надо говорить и из обтекаемых формулировок можно выстраивать разные забавные предположения. Лично я не завсегдатай SEO-форумов, возможно, все это уже где-то обсуждалось &#8212; если баян, извините.<span id="more-337"></span></p>
<p><strong>Сегалович</strong>:</p>
<blockquote><p>Ровно в этих рамках (борьба с «глупостью») мы относительно недавно реализовали алгоритм определения запросов и ответов, которые можно трактовать двояко: и как поиск эротического и порнографического содержания, и как невинный информационный запрос. Например, запрос [девочки] может быть поиском повести Людмилы Улицкой, а вовсе не «девочек по вызову». Для человека, ищущего Улицкую, ответ с порнографией не просто нерелевантен, он «явная глупость».</p>
<p>Опираясь на классификаторы запросов и сайтов по порнографическому и непорнографическому содержанию, и построив соответствующие метрики, отражающие долю резко нерелевантного поведения нашей системы по «двояким» запросам, мы смогли реализовать механизм понижения в выдаче сайтов порнографического содержания.</p></blockquote>
<p>Было бы логично, если бы Яндекс подсовывал разным посетителям разные варианты выдачи, основываясь на данных предыдущих запросов, статистики из Метрики и т.д. Не специально для каждого пользователя, а для каких-то условных групп, типа &laquo;любитель клубнички&raquo;, &laquo;книжный червь&raquo; или каких-то таких. А что? Статистика по запросам есть, статистика посещенных сайтов и проведенного на них времени &#8212; то же (Метрика, различные кнопки ТИЦ, блогов и т.д.) &#8212; нарисовать схему интересов пользователя можно. И потом соотнести с какой-то своей внутренней классификацией. А вот слова о том, что ответ не подвергается модификации &#8212; это, возможно, и временно. На паре &laquo;порно/непорно&raquo; алгоритм просто обкатывается.</p>
<p>Если Яндекс все-таки реализует модификацию выдачи в зависимости от вычесленных предпочтений пользователя &#8212; вот будет головная боль оптимизаторам! Почистил куки, походил по сайтам с пластиковыми окнами &#8211; получи выдачи про строительство и остекление балконов, почистил куки, походил по сайтам с программным обеспечением &#8212; получи выдачу про Windows. И все в ответ на один и тот же запрос &laquo;окошки&raquo;.</p>
<p><strong>Сегалович</strong>:</p>
<blockquote><p>по ряду запросов мы мониторим выдачу других поисковых машин, всех, кто хоть как-то ищет по-русски, включая все версии самого Яндекса &#8211; рабочую версию и внутренние, экспериментальные (у Яндекса много версий). И складываем все результаты в один котел. Если какой-то сайт присутствует в этом «котле», если он там имеет достаточно хорошие оценки, и при этом отсутствует в Яндексе, мы начинаем разбираться – почему</p></blockquote>
<p><strong>Садовский</strong>:</p>
<blockquote><p>Чтобы было понятно, «котел» какого объема оценивается, подчеркну, что это речь идет о десятках тысяч запросов, которые мы проверяем таким образом. Мы проверяем первые 30 позиций по каждому запросу. Считайте: десятки тысяч запросов, умножить на 30 первых позиций, умножить на количество версий, &#8211; это десятки миллионов URL.</p></blockquote>
<p>Мониторят конкурентов. Очевидно, Google, Bing и Рамблер. Наверное и Yahoo. Об остальных можно только догадываться. Составляют множество сайтов, попадающих в выдачу всех или бОльшей части конкурентов. Потом сравнивают со своими результатами. Конкретная позиция, наверное, не очень важна &#8212; главное присутствие в первых 30-ти результатах. Смотрят, какие сайты попали к ним &#8212; если различие сильное, это повод задуматься. Т.е. если после получения результатов от конкурентов оказывается, например, что 22 сайта присутствуют у всех, а у Яндекса только 5 из этих сайтов &#8212; это повод побеспокоиться.</p>
<p>Сразу возникает интересная идея &#8212; путь к первой странице выдачи Яндекса может лежать и через результаты выдачи его конкурентов.</p>
<p><strong>Сегалович</strong>:</p>
<blockquote><p>Так вот, практически все обращения в службу техподдержки &#8211; я думаю, в цифрах это будет более 90% &#8211; касаются именно таких сайтов из «серой зоны». Пишут грамотные аргументированные письма: «А вот смотрите, почему вы этот сайт выбросили, он качественный, контент уникальный, ссылки по теме. Объясните почему.» Цель таких писем – методом перебора уточнить безопасные границы в этой «серой зоне». Предприняли какое-то действие – смотрят результат. Если результат отрицательный, сайт попал под санкции, они пытаются получить от нас обратную связь, проанализировать причины.</p></blockquote>
<p><strong>Певцов</strong>:</p>
<blockquote><p>&#8230;как показывает практика, большинство сайтов, по поводу отсутствия которых в выдаче к нам обращаюся вебмастера, создавались специально с целью обмана поисковой системы и манипуляции результатами поиска&#8230;</p></blockquote>
<p><strong>Садовский</strong>:</p>
<blockquote><p>Я хочу заметить, что если мы видим, что имела место ошибка с нашей стороны, то в алгоритмы вносятся изменения, улучшающие работу системы в целом, и это касается других сайтов, которые тоже могли бы пострадать в аналогичной ситуации.</p></blockquote>
<p>Ну все уже догадались? Жаловаться на то, что сайт выпал из индекса, хотя соответствует &laquo;техническим параметрам&raquo; &#8211; ссылки, качество контента и т.д. &#8211; не надо. Ищите другую аргументацию. Вам же не робот отвечает, человек. И он понимает, что вебмастер беспокоящийся о технической стороне вопроса &#8212; не их союзник. И еще. Удалось убедить, что &laquo;сателлит&raquo; белый и пушистый? Будьте готовы к тому, что из под санкций могут выползти и &laquo;сателлиты&raquo; конкурентов. Любите жаловаться на &laquo;сателлиты&raquo; конкурентов, присутствующие в выдаче? Будьте готовы к тому, что вместе с ними пойдут ко дну и ваши такие-же.</p>
<p><strong>Певцов</strong>:</p>
<blockquote><p>уникальность контента совсем не определяющая вещь. О ней много говорят, но более важная характеристика &#8211; не уникальность, а полезность контента <em>[и далее по тексту]</em></p></blockquote>
<p>&laquo;У вас на сайте неуникальный текст! Ужас-ужас-ужас!&raquo; &#8211; страшилка. То есть, если скопировать все подряд, санкции будут. Но умеренное разбавление своих статей статьями, взятыми из других источников, может не повлечь никаких санкций. Таким образом, если где-то в интернетах нашлась удачная статья, подходящая сайту и автор не против ее распространения, можно спокойно скопировать ее к себе или процитировать. Ссылка на оригинал, как мне кажется, в данном случае будет лишним подтверждением &laquo;добрых намерений&raquo;.</p>
<p>Четвертая часть о воровстве контента. Авторам стОит отдавать свои статьи в RSS. Не жмотитесь, отдавайте всю статью. Роботы, сканирующие блогосферу быстрее и чаще забирают контент. Если статья у кого-то скопирована, не надо расстраиваться, страница с этим текстом не первая в выдаче. Еще не факт, что посетителя заинтересует первый сайт. 2-5 место тоже хороши. И до конца первой страницы &#8211; нормально. Кроме того, скопированная страница может придать общий тематический вес сайту, подняв его по другим, похожим, низкочастотным запросам.</p>
<p>Торговля и обмен ссылками яндексоидов раздражают. Но, если уж они научились находить &laquo;продажные ссылки&raquo;, то зачем банить всю страницу, она может оказаться вполне нормальной, а ссылки &#8211; результатом баловства наемного вебмастера. Ну неучитывали-бы тихонько эти самые ссылки молча. Дятлы бы продолжали бы заниматься бесполезным трудом и не искали бы каких-то иных методов воздействия на поисковик.</p>
<p>Ну вот как-то вот так. Спасибо, что дочитали до конца. :)</p>

<p><a href="http://feedads.g.doubleclick.net/~a/_gW2c63IMDz4JdqsYFLn9DvOYlU/0/da"><img src="http://feedads.g.doubleclick.net/~a/_gW2c63IMDz4JdqsYFLn9DvOYlU/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/_gW2c63IMDz4JdqsYFLn9DvOYlU/1/da"><img src="http://feedads.g.doubleclick.net/~a/_gW2c63IMDz4JdqsYFLn9DvOYlU/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=qYOr9YbFdyM:Jd4zxGrtZ_I:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=qYOr9YbFdyM:Jd4zxGrtZ_I:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=qYOr9YbFdyM:Jd4zxGrtZ_I:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=qYOr9YbFdyM:Jd4zxGrtZ_I:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=qYOr9YbFdyM:Jd4zxGrtZ_I:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=qYOr9YbFdyM:Jd4zxGrtZ_I:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/qYOr9YbFdyM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/11/lets-try-to-read-between-lines/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Контроллеры: загрузка</title>
		<link>http://www.handmadesite.net/2009/11/loding-controllers/</link>
		<comments>http://www.handmadesite.net/2009/11/loding-controllers/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 17:50:02 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Controller]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=332</guid>
		<description><![CDATA[Удивительно но факт. Если из консольного, например, приложения нужно попользоваться моделью, то, само собой, надо загрузить класс модели.

App::import&#40;'Model', 'MyModel'&#41;;

Но загрузить контроллер так не получится. Получим сообщение об ошибке из-за невозможности найти базовый класс Controller. Вот найти класс Model кейк может, а Controller &#8211; нет. Во всяком случае 1.2.5. В версии 1.3 не пробовал.
Поэтому приходится загружать [...]]]></description>
			<content:encoded><![CDATA[<p>Удивительно но факт. Если из консольного, например, приложения нужно попользоваться моделью, то, само собой, надо загрузить класс модели.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Model'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'MyModel'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Но загрузить контроллер так не получится. Получим сообщение об ошибке из-за невозможности найти базовый класс Controller. Вот найти класс Model кейк может, а Controller &#8211; нет. Во всяком случае 1.2.5. В версии 1.3 не пробовал.</p>
<p>Поэтому приходится загружать его явно и напрямую:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Core'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Controller'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Controller'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'MyController'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p><a href="http://feedads.g.doubleclick.net/~a/rzCahmhwzkCxJR3e5-b_7QYTHeY/0/da"><img src="http://feedads.g.doubleclick.net/~a/rzCahmhwzkCxJR3e5-b_7QYTHeY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/rzCahmhwzkCxJR3e5-b_7QYTHeY/1/da"><img src="http://feedads.g.doubleclick.net/~a/rzCahmhwzkCxJR3e5-b_7QYTHeY/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=oP7xPiDsP8M:04qu1B2EA-U:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=oP7xPiDsP8M:04qu1B2EA-U:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=oP7xPiDsP8M:04qu1B2EA-U:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=oP7xPiDsP8M:04qu1B2EA-U:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=oP7xPiDsP8M:04qu1B2EA-U:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=oP7xPiDsP8M:04qu1B2EA-U:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/oP7xPiDsP8M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/11/loding-controllers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Компоненты: перезагрузка</title>
		<link>http://www.handmadesite.net/2009/10/reload-components/</link>
		<comments>http://www.handmadesite.net/2009/10/reload-components/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 22:02:40 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Component]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=324</guid>
		<description><![CDATA[Не знаю, такую-ли ситуацию имел в виду BorisPlus в своем комментарии. Ну, чем богаты. Вообще не хотел это все описывать, потому как код довольно халтурно написан.
Этот код приложения, изначально крутившийся по Cake 1.1, был переписан для какой-то беты Cake 1.2. С текущей версией, 1.2.5, он работает без проблем, но, возможно, нуждается в чистке.
Эта часть программы [...]]]></description>
			<content:encoded><![CDATA[<p>Не знаю, такую-ли ситуацию имел в виду <a href="/2008/12/m-for-model/comment-page-1/#comment-794">BorisPlus в своем комментарии</a>. Ну, чем богаты. Вообще не хотел это все описывать, потому как код довольно халтурно написан.</p>
<p>Этот код приложения, изначально крутившийся по Cake 1.1, был переписан для какой-то беты Cake 1.2. С текущей версией, 1.2.5, он работает без проблем, но, возможно, нуждается в чистке.</p>
<p>Эта часть программы выполняющий импорт данных от поставщиков. Поставщики предоставляют данные в CSV формате, но порядок колонок, некоторые значения и т.д., конечно разные. Для осмысленной обработки эти полученные данные надо привести к единообразному виду.</p>
<p>Данные поступают из написанного куцего <em>Datasource</em>, скармливанются компоненту, который и выполняет разбор и приведение к общему виду, потом записываются в нашу таблицу.</p>
<p><span id="more-324"></span></p>
<p>Компонент подгружается динамически, в зависимости от поставщика. Все компоненты являются наследниками базового и реализуют метод <strong>parse</strong>. Этот метод базового компонента, если не перегружен, возвращает <em>NULL</em> &#8212; в этом случае в нашу таблицу ничего не записываем, переходим к следующей порции данных. Соответственно методы наследников тоже могут возвращать <em>NULL</em> при ошибке разбора, например, при отсутствии какого-либо ключевого поля.</p>
<p>Еще базовый компонент содержит некоторое количество служебных методов, общих для всех, с целью унифицировать данные.</p>
<p>Увы, все файлы с компонентами находятся в каталоге <em>components</em>. Зато после перегрузки можно к загруженному компоненту обращаться по имени базового:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">SupplierCsv</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">parse</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>В коде контроллера загружается базовый компонент. Так как он нужен только в одном методе контроллера, в нем я его и загружаю:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Component'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'SupplierCsv'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cannot load SupplierCsv component'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Еще у базового компонента есть метод <strong>factory</strong>. Я не помню, почему я его статическим объявил, честно. :-) Он получает в качестве параметра ссылку на контроллер и название компонента для обработки данных от конкретного поставщика:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">SupplierCsvComponent<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'CsvComponentName'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$component_name</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Теперь методы базового компонента, <em>SupplierCsvComponent</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> startup<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">SupplierCsv</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
static <span style="color: #000000; font-weight: bold;">function</span> factory<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$controller</span><span style="color: #339933;">,</span> <span style="color: #000088;">$supplier</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Component'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$supplier</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'CsvComponentName'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$componentclass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$supplier</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'CsvComponentName'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'Component'</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">SupplierCsv</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000088;">$componentclass</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">SupplierCsv</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">startup</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ну и код метода <strong>startup</strong> дочерних классов:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> startup<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">startup</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">init</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Решение неидельное, наверняка можно соптимизировать. Мне, честно говоря, заниматься этим не хочется. Просто потому, что я в итоге начну вообще все с нуля переделывать и менять логику. :)</p>
<p>Откровенно говоря, огород можно было бы и не городить. Можно через App::import() загрузить класс компонента, а потом какой-нибудь переменной контроллера присвоить экземпляр этого класса.</p>
<p>Наверное, я раньше грузил компонент, указывая его в массиве $components, потому и сделал такую навернутую схему.</p>
<p>А может мне не хотелось require_once использовать&#8230; Ну не помню. :)</p>
<p><em>Update:</em> Если соберусь переписывать, надо будет рефлексию попробовать использовать. :)</p>

<p><a href="http://feedads.g.doubleclick.net/~a/t84WUblTmkl1bflcemVvkE6T5iM/0/da"><img src="http://feedads.g.doubleclick.net/~a/t84WUblTmkl1bflcemVvkE6T5iM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/t84WUblTmkl1bflcemVvkE6T5iM/1/da"><img src="http://feedads.g.doubleclick.net/~a/t84WUblTmkl1bflcemVvkE6T5iM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=uQ4y5AoxfNE:ZWZTZC0OYJw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=uQ4y5AoxfNE:ZWZTZC0OYJw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=uQ4y5AoxfNE:ZWZTZC0OYJw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=uQ4y5AoxfNE:ZWZTZC0OYJw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=uQ4y5AoxfNE:ZWZTZC0OYJw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=uQ4y5AoxfNE:ZWZTZC0OYJw:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/uQ4y5AoxfNE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/10/reload-components/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Кэш и консоль</title>
		<link>http://www.handmadesite.net/2009/09/cache-and-console/</link>
		<comments>http://www.handmadesite.net/2009/09/cache-and-console/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 16:41:48 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[XCache]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=321</guid>
		<description><![CDATA[За полноценный пост не считается. Так, узелок на память.
В качестве кэша байткода и переменных я использую XCache. Но при запуске консольных приложений, он у меня не работает. Должен или нет, не знаю, не разбирался. Наверное, не должен, если подумать. :-) Просто отметил, что консольные приложения Cake, включая &#8216;cake bake&#8216; высыпают кучу ошибок, если XCache используется, [...]]]></description>
			<content:encoded><![CDATA[<p>За полноценный пост не считается. Так, узелок на память.</p>
<p>В качестве кэша байткода и переменных я использую <a href="http://xcache.lighttpd.net/">XCache</a>. Но при запуске консольных приложений, он у меня не работает. Должен или нет, не знаю, не разбирался. Наверное, не должен, если подумать. :-) Просто отметил, что консольные приложения Cake, включая &#8216;<em>cake bake</em>&#8216; высыпают кучу ошибок, если XCache используется, как кэш по умолчанию. Поэтому в конфигурации кэша приложения (APP/config/core.php) на CakePHP добавляю маленькую проверку на тип API.</p>
<p>Вот как-то так:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>PHP_SAPI <span style="color: #339933;">==</span> <span style="color: #0000ff;">'cli'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  Cache<span style="color: #339933;">::</span><span style="color: #004000;">config</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'default'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'engine'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'File'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
  Cache<span style="color: #339933;">::</span><span style="color: #004000;">config</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'default'</span><span style="color: #339933;">,</span>
    <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'engine'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Xcache'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'prefix'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mypfx_'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'user'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'IamAdmin'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'password'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'c00leztPass'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Можно пользоваться константой <a href="http://php.net/manual/en/reserved.constants.php#reserved.constants.core">PHP_SAPI</a> или функцией <a href="http://php.net/php_sapi_name">php_sapi_name()</a>, не важно.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/lhRVDZTLNfaKsclhmxskUPfXLKk/0/da"><img src="http://feedads.g.doubleclick.net/~a/lhRVDZTLNfaKsclhmxskUPfXLKk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/lhRVDZTLNfaKsclhmxskUPfXLKk/1/da"><img src="http://feedads.g.doubleclick.net/~a/lhRVDZTLNfaKsclhmxskUPfXLKk/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=r326Qf4BvAU:mZX8aJ8Y-mc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=r326Qf4BvAU:mZX8aJ8Y-mc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=r326Qf4BvAU:mZX8aJ8Y-mc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=r326Qf4BvAU:mZX8aJ8Y-mc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=r326Qf4BvAU:mZX8aJ8Y-mc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=r326Qf4BvAU:mZX8aJ8Y-mc:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/r326Qf4BvAU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/09/cache-and-console/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CakePHP 1.2, Content-type, debug, RequestHandler и все-все-все</title>
		<link>http://www.handmadesite.net/2009/09/cakephp-1-2-content-type-debug-requesthandler-ftd-so-on/</link>
		<comments>http://www.handmadesite.net/2009/09/cakephp-1-2-content-type-debug-requesthandler-ftd-so-on/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 12:46:16 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[parseExtensions]]></category>
		<category><![CDATA[RequestHandler]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=305</guid>
		<description><![CDATA[Как правильно, с точки зрения CakePHP, отвечать на запросы, если ответ требуется не html, а, например, json? Я считаю, что для получения ответа в нужном формате надо воспользоваться компонентом RequestHandler и указать в запросе расширение, в нашем случае &#8216;.json&#8217;. URL для запроса получится какой-то такой:
http://www.oursite.com/controller/action.json
Чтобы Cake не пугался этого расширения и вызывал правильное действие (action), [...]]]></description>
			<content:encoded><![CDATA[<p>Как правильно, с точки зрения CakePHP, отвечать на запросы, если ответ требуется не html, а, например, json? Я считаю, что для получения ответа в нужном формате надо воспользоваться компонентом <em>RequestHandler</em> и указать в запросе расширение, в нашем случае &#8216;.json&#8217;. URL для запроса получится какой-то такой:</p>
<pre>http://www.oursite.com/controller/action.json</pre>
<p>Чтобы Cake не пугался этого расширения и вызывал правильное действие (action), в файл APP/config/routes.php добавим строку:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Router<span style="color: #339933;">::</span><span style="color: #004000;">parseExtensions</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><span id="more-305"></span>Теперь надо разобраться с разными представлениями наших данных, чтобы по запросам к /action и /action.json возвращались разные виды. Для этого нужен компонент <em>RequestHandler</em>. Подключим его либо в самом контроллере, либо в родительском AppController:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$components</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'RequestHandler'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Теперь шаблоны для view и layout Cake будет искать в поддиректориях /json. Т.е для layout надо будет создать файл /views/layout/json/default.ctp:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$content_for_layout</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>и файл для действия /views/controller/json/action.ctp. Какой-то такой:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$javascript</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Это все и без меня все знают, ничего нового тут нет. Разве что <a href="http://cakebaker.42dh.com/2009/07/02/default-views-for-extensions/">cakebaker советует воспользоваться Zend::Json вместо стандартного помощника Javascript</a>, дескать Zend&#8217;овская библиотека автоматом кодирует некоторые спецсимволы.</p>
<p>Но есть одна тонкость, недостаточно отраженная в документации &#8212; заголовок ответа Content-type. По всем ожиданиям он должен быть &#8216;application/json&#8217;, как это определено в коде компонента <em>RequestHandler</em>.</p>
<p>Однако, если включен режим отладки, т.е. <em>Configure.debug &gt; 0</em>, то <em>RequestHandler</em> устанавливает Сontent-Type в text/html без вариантов. Это, в общем-то описано в документации и докопаться до этого можно.</p>
<p>Но совершенно неочевидно, что если режим отладки выключить в коде самого action, написав</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Configure<span style="color: #339933;">::</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'debug'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>то это ничего уже не изменит! <em>RequestHandler</em> устанавливает заголовок во время загрузки компонента. Его метод <em>startup()</em> вызывает метод <em>renderAs()</em>, который вызывает метод <em>respondAs()</em>. Таким образом шаблоны подключаются нужные, те, которые из директорий /json, а Content-Type неправильный.</p>
<p>Лично я, пока, в acton, который должен отдавать данные в json, явно вызывываю <em>RequestHandler-&gt;respondAs()</em> повторно:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Configure<span style="color: #339933;">::</span><span style="color: #004000;">read</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    Configure<span style="color: #339933;">::</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'debug'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">RequestHandler</span><span style="color: #339933;">-&gt;</span>__responseTypeSet <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">RequestHandler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderAs</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Это заставляет <em>RequestHandler</em> изменить заголовок Content-type еще раз. Можно похожий код, с проверкой типа запроса и установкой режима отладки и заголовков попробовать запихнуть, скажем, в <em>beforeRender</em>. Обратите внимание на грязный хак с установкой свойства __responseTypeSet в NULL. Метод respondAs сохраняет в эту переменную тип ответа и повторно не будет срабатывать, если он уже был вызван.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/ue9ZDTvvly5PvVlFFKRc8gvWfX8/0/da"><img src="http://feedads.g.doubleclick.net/~a/ue9ZDTvvly5PvVlFFKRc8gvWfX8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ue9ZDTvvly5PvVlFFKRc8gvWfX8/1/da"><img src="http://feedads.g.doubleclick.net/~a/ue9ZDTvvly5PvVlFFKRc8gvWfX8/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=zIYWOAye2G0:bJo8Mds-ZR0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=zIYWOAye2G0:bJo8Mds-ZR0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=zIYWOAye2G0:bJo8Mds-ZR0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=zIYWOAye2G0:bJo8Mds-ZR0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=zIYWOAye2G0:bJo8Mds-ZR0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=zIYWOAye2G0:bJo8Mds-ZR0:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/zIYWOAye2G0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/09/cakephp-1-2-content-type-debug-requesthandler-ftd-so-on/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Метрическая аналитика</title>
		<link>http://www.handmadesite.net/2009/05/metricheskaya-analitika/</link>
		<comments>http://www.handmadesite.net/2009/05/metricheskaya-analitika/#comments</comments>
		<pubDate>Fri, 01 May 2009 21:01:29 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[Поисковики]]></category>
		<category><![CDATA[Аналитика]]></category>
		<category><![CDATA[Статистика]]></category>
		<category><![CDATA[Яндекс]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=301</guid>
		<description><![CDATA[У Яндекса есть полезная система статистики, похожая частью на Google Analytics, частью -- на счетчик Liveinternet]]></description>
			<content:encoded><![CDATA[<p>У Яндекса есть полезная система статистики, похожая частью на Google Analytics, частью &#8212; на счетчик Liveinternet. Называется <a href="http://metrika.yandex.ru/" target="_blank">Яндекс.Метрика</a>.</p>
<div id="attachment_300" class="wp-caption alignnone" style="width: 455px"><img class="size-full wp-image-300" title="Яндекс.Метрика" src="http://www.handmadesite.net/wp-content/uploads/2009/05/ya-metrics.jpg" alt="Яндекс.Метрика" width="445" height="102" /><p class="wp-caption-text">Яндекс.Метрика</p></div>
<p>Все как обычно &#8212; устанавливаете код на страницы своего сайта и наблюдаете статистику по посетителям. В отличие от GA, которая обновляется раз в сутки, <strong>Метрика</strong> показывает результаты практически в реальном времени, как Liveinternet &#8212; это гораздо удобнее.</p>
<p>Если сайт рекламируется с помощью <strong>Яндекс.Директ</strong> и на рекламируемом сайте установлен код для сбора статистики для Директа &#8212; это и есть код Метрики!  В этом случае можно уже не напрягаться, а смотреть отчеты.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/_K_4VmUXk1RUtvLNpGEu0kF3-s8/0/da"><img src="http://feedads.g.doubleclick.net/~a/_K_4VmUXk1RUtvLNpGEu0kF3-s8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/_K_4VmUXk1RUtvLNpGEu0kF3-s8/1/da"><img src="http://feedads.g.doubleclick.net/~a/_K_4VmUXk1RUtvLNpGEu0kF3-s8/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=Kqe18IsLWTI:sPVb_SbbgG0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=Kqe18IsLWTI:sPVb_SbbgG0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=Kqe18IsLWTI:sPVb_SbbgG0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=Kqe18IsLWTI:sPVb_SbbgG0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=Kqe18IsLWTI:sPVb_SbbgG0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=Kqe18IsLWTI:sPVb_SbbgG0:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/Kqe18IsLWTI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/05/metricheskaya-analitika/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UPDATE нельзя INSERT</title>
		<link>http://www.handmadesite.net/2009/04/update-insert/</link>
		<comments>http://www.handmadesite.net/2009/04/update-insert/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 22:13:55 +0000</pubDate>
		<dc:creator>Сергей</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[таблицы]]></category>

		<guid isPermaLink="false">http://www.handmadesite.net/?p=293</guid>
		<description><![CDATA[Задача очень простая: обновить запись в таблице, а если подходящей записи нет, добавить новую. Кажется вполне тривиальной задачей. Особенно, если условия, по которым выбирается запись для обновления сделать первичным или уникальным ключом.
Эта тема пару месяцев назад обсуждалась в ЖЖ сообществе ru_php, но как-то вяло. Попробую этим небольшим постом обобщить разные методики.
Самый простой метод: сначала SELECT [...]]]></description>
			<content:encoded><![CDATA[<p>Задача очень простая: обновить запись в таблице, а если подходящей записи нет, добавить новую. Кажется вполне тривиальной задачей. Особенно, если условия, по которым выбирается запись для обновления сделать первичным или уникальным ключом.</p>
<p>Эта тема пару месяцев назад обсуждалась в <a href="http://community.livejournal.com/ru_php/1321540.html" target="_blank">ЖЖ сообществе ru_php</a>, но как-то вяло. Попробую этим небольшим постом обобщить разные методики.</p>
<p>Самый простой метод: сначала SELECT COUNT(*), а потом, по результатам, либо INSERT, либо UPDATE. Если речь идет об обновлении одной записи на этом методе можно остановиться.</p>
<p>Увы, если надо вставить много записей, этот метод начинает изрядно тормозить. Для такого случая у MySQL есть несколько разных методов.</p>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/replace.html" target="_blank">REPLACE</a> &#8212; наиболее очевидный и самый неудобный. Сервер пытается вставить новую строку, если возникает ошибка с повторяющимся уникальным ключом, запись удаляется и потом снова добавляется новая. Увы, при этом значения тех полей, которые обновлять не надо сбрасываются в дефолтные. Использовать эту команду можно, если обновляется полностью вся запись, что случается редко. Например, если в таблице есть колонка `created`, содержащая дату <em>создания</em> записи, то REPLACE уже не подходит. Кроме того, в случае, если большинство записей заменяется, а не добавляется, получается конструкция INSERT-(ошибка)-DELETE-INSERT &#8212; три запроса!</p>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html" target="_blank">INSERT &#8230; ON DUPLICATE KEY UPDATE &#8230;</a> &#8212; этот вариант сильно интереснее. Сервер пытается вставить запись, если получает ошибку c дублирующимся ключом, обновляет поля, указанные в после UPDATE. Работает отлично, в документации сказано, что эта конструкция специально задумана для вставки множества записей. Но пара неприятных моментов есть.</p>
<ol>
<li>Первый, как мне казалось, довольно экзотичный, но я с ним все-таки столкнулся. В конструкции INSERT можно в качестве источника данных использовать <a href="http://dev.mysql.com/doc/refman/5.1/en/insert-select.html" target="_blank">подзапрос SELECT</a>. Но, в случае с INSERT &#8230; ON DUPLICATE KEY UPDATE, в подзапросе <em>не должно</em> быть группировки GROUP BY.</li>
<li>Второй момент для многих неважен. Если записей для обновления сильно больше чем новых, то получается все равно много лишних обращений к БД &#8212; ведь вся конструкция это сочетание INSERT-(ошибка)-UPDATE. Лучше, чем с REPLACE, но все же&#8230;</li>
</ol>
<p>Долгое время я пользовался UPDATE, а потом проверял mysql_affected_rows() (в CakePHP это $DataSource-&gt;lastAffected(). То есть проверял количество обновленных записей и, если получал 0, добавлял запись. У этого метода есть очень существенный недостаток: если среди данных для обновления встречаются две одинаковых строки, то при повторном UPDATE сервер, как самый умный, не обновляет запись. Соответственно число обновленных записей, affected rows, при построчном переборе, будет равно 0 несмотря на то, что такая строка в таблице есть. Соответственно решение о вставки новой строки будет ошибочным.</p>
<p>Устав мириться с ожидаемым, но неприятным поведением mysql_affected_rows() я порылся в документации на MySQL и нашел еще одну функцию: <a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-info.html" target="_blank">mysql_info()</a>. Она выдает обычную строчку со статистикой последнего запроса к БД, причем для разных типов запросов строчки разные. Для UPDATE выглядит так:</p>
<p><code class="literal">Rows matched: 40 Changed: 40             Warnings: 0</code></p>
<p>Зато содержит чрезвычайно ценную информацию: количество записей, которые попадают под условие для обновления. Это те цифры, что после слова &#8216;<em>matched:</em>&#8216;. Ну, регулярное выражение для получения циферок из строки сами напишите? ;-)</p>
<p>P.S. У меня ощущение deja vu &#8212; мне кажется, что я уже писал похожий пост. Перерыл дневники &#8212; нет такого. Или это черновик был&#8230;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/doB8CRgAW-FEczx9-pQhbiByXvs/0/da"><img src="http://feedads.g.doubleclick.net/~a/doB8CRgAW-FEczx9-pQhbiByXvs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/doB8CRgAW-FEczx9-pQhbiByXvs/1/da"><img src="http://feedads.g.doubleclick.net/~a/doB8CRgAW-FEczx9-pQhbiByXvs/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/handmadesite?a=eoT_CJnm7Vg:HR-sTyDzKeg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=eoT_CJnm7Vg:HR-sTyDzKeg:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=eoT_CJnm7Vg:HR-sTyDzKeg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=eoT_CJnm7Vg:HR-sTyDzKeg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/handmadesite?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/handmadesite?a=eoT_CJnm7Vg:HR-sTyDzKeg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/handmadesite?i=eoT_CJnm7Vg:HR-sTyDzKeg:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/handmadesite/~4/eoT_CJnm7Vg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.handmadesite.net/2009/04/update-insert/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
