<?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; Phing</title>
	<atom:link href="http://www.simplecoding.org/category/phing/feed" rel="self" type="application/rss+xml" />
	<link>http://www.simplecoding.org</link>
	<description>Блог о программировании</description>
	<lastBuildDate>Sun, 14 Mar 2010 15:23:12 +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>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>32</slash:comments>
		</item>
		<item>
		<title>Изменяем файлы с помощью Phing</title>
		<link>http://www.simplecoding.org/izmenyaem-faily-s-pomoshhyu-phing.html</link>
		<comments>http://www.simplecoding.org/izmenyaem-faily-s-pomoshhyu-phing.html#comments</comments>
		<pubDate>Mon, 26 Jan 2009 08:53:48 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=736</guid>
		<description><![CDATA[На сегодняшний день большинство web приложений содержит множество конфигурационных файлов с различными настройками. Например, имя домена, параметры подключения к базе данных, размещение библиотек и т.д.
В принципе, это довольно удобно, т.к. эти файлы можно легко отредактировать с помощью обычного текстового редактора. Но проблема в том, что редактировать их приходится постоянно.
Представьте ситуацию. Вы делаете сайт, сначала тестируете [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_737" class="wp-caption alignnone" style="width: 287px"><img src="http://www.simplecoding.org/wp-content/uploads/2009/01/phing_search_replace.png" alt="phing search replace" style="float:left" title="phing search replace" width="277" height="108" class="size-full wp-image-737" /><p class="wp-caption-text"> </p></div>
<p>На сегодняшний день большинство web приложений содержит множество конфигурационных файлов с различными настройками. Например, имя домена, параметры подключения к базе данных, размещение библиотек и т.д.</p>
<p>В принципе, это довольно удобно, т.к. эти файлы можно легко отредактировать с помощью обычного текстового редактора. Но проблема в том, что <strong>редактировать их приходится постоянно</strong>.</p>
<p>Представьте ситуацию. Вы делаете сайт, сначала тестируете его локально, а затем переносите на сервер. Естественно, перед загрузкой на сервер нужно будет как минимум изменить параметры подключения к БД.</p>
<p>Затем вы находите ошибку (или просто решаете что-то изменить) и процесс повторяется заново.</p>
<p>Каждый раз менять настройки вам быстро надоест, особенно если изменить нужно не один файл, а несколько. Да и забыть что-то очень легко.</p>
<p>В этой статье я покажу небольшой пример как с помощью <a href="http://phing.info/trac/">Phing</a> можно автоматизировать такие операции.</p>
<p><em>Примечание</em>. Почитать о том что такое <strong>Phing</strong> и зачем нужен можно <a href="http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html">здесь</a>.</p>
<p>Прежде всего, <strong>сформулируем задачу</strong>.<br />
<span id="more-736"></span><br />
Чтобы ничего не придумывать я возьму пример из <a href="http://www.simplecoding.org/otmechaem-posetitela-na-yandex-karte.html">предыдущей статьи</a>. Напомню, речь там шла об использовании <strong>Яндекс.Карт</strong>.</p>
<p>Дело в том, что для вставки карты на свой сайт нужно получить у Яндекса специальный <strong><acronym title="Application Programming Interface">API</acronym>-ключ</strong>, который выдается для каждого домена отдельно. Т.е. ключ, полученный для <code>mydomen.local</code>, не будет работать на <code>mydomen.com</code>.</p>
<p>Таким образом, <strong>перед переносом страницы с картой на сервер нужно изменить этот ключ</strong>.</p>
<p><strong>UPD</strong>. <em>Когда я практически дописывал этот пост пришел комментарий к предыдущей статье от <a href="http://yandex.ru/">Андрея Кармацкого</a>, в котором он рассказал, что api-ключ, полученный для любого домена, будет работать и на localhost</em>.</p>
<p>Напомню, ключ указывается внутри тега <code>script</code> в заголовке страницы.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc2"><span class="kw2">&lt;script</span> <span class="kw3">src</span>=<span class="st0">&quot;http://api-maps.yandex.ru/1.0/index.xml?key=key_for_local_domen&quot;</span> <span class="kw3">type</span>=<span class="st0">&quot;text/javascript&quot;</span><span class="kw2">&gt;</span></span><span class="sc2"><span class="kw2">&lt;/script&gt;</span></span></div>
</li>
</ol>
</div>
<p>Здесь нам нужно <code>key_for_local_domen</code> заменить на новый ключ.</p>
<p><strong>Посмотрим как с помощью Phing решить эту задачу</strong>.</p>
<p>Создаем в корне проекта файл с названием <code>build.xml</code></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;IPLocYandexMaps&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;deploy&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; &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;DEPLOY_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;deploy&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;SRC_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;public_html&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;DEPLOY_KEY&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;api-key-for-my-host&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;prepare&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Removing old files&#8230;&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;delete</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span> <span class="re0">includeemptydirs</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">verbose</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">failonerror</span>=<span class="st0">&quot;true&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Creating new dir&#8230;&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;mkdir</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}&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;/target<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;copyfiles&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;prepare&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Copying main files&#8230;&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;copy</span> <span class="re0">todir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;${SRC_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;index.php&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;filterchain<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;replaceregexp<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;regexp</span> <span class="re0">pattern</span>=<span class="st0">&quot;index.xml\?key=(.*?)&quot;</span><span class="st0">&quot; replace=&quot;</span>index.xml?<span class="re0">key</span>=$<span class="br0">&#123;</span>DEPLOY_KEY<span class="br0">&#125;</span><span class="st0">&quot;&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/replaceregexp<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/filterchain<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/copy<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></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;target</span> <span class="re0">name</span>=<span class="st0">&quot;deploy&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;copyfiles&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;/target<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/project<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Теперь рассмотрим как это все работает.</p>
<p>В начале (строки 4-6) мы объявили три константы:<br />
<code>DEPLOY_DIR</code> – имя папки, в которой будет размещен измененный файл (в данном примере – index.php);<br />
<code>SRC_DIR</code> – имя папки с исходным файом;<br />
<code>DEPLOY_KEY</code> – <acronym title="Application Programming Interface">API</acronym>-ключ.</p>
<p>Затем мы написали операцию prepare (строки 8-13). Она сначала удаляет папку <code>${DEPLOY_DIR}</code> со всем содержимым, и сразу же создает её заново. Такой подход гарантирует, что если мы решим изменить имя файла со страницей, то в папке deploy не останется файл со старым именем.</p>
<p>И, самое интересное, операция <code>copyfiles</code>.</p>
<p>Сначала мы <strong>создаем задачу копирования</strong> (тег copy, строка 17) и указываем какие файлы нужно скопировать (в данном случае это только один файл – index.php).</p>
<p>После этого <strong>добавляем задачу filterchain</strong> (строки 21-25), т.е. создаем цепочку фильтров, которая будет применена к каждому копируемому файлу.</p>
<p>Чтобы заменить ключ нам хватит всего одного фильтра, который выполнит замену на основе регулярного выражения (строки 22-24). Фильтр создаем с помощью тегов replaceregexp и regexp.</p>
<p>Для <code>regexp</code> нужно задать параметры в атрибутах:</p>
<p><code>pattern</code> – регулярное выражение;<br />
<code>replace</code> – текст на который будет заменен результат поиска.</p>
<p>Вот и все, теперь с помощью этого build файла мы сможем изменять ключ буквально одним нажатием кнопки.</p>
<p><em>Примечание</em>. Последняя операция сама по себе ничего не делает, а просто запускает предыдущие.</p>
<p>Кстати, есть ещё одно преимущество такого подхода. Т.к. <strong>Phing</strong> копирует файл с новым ключом в отдельную папку, то ваша локальная версия страницы остается в рабочем состоянии.</p>
<p>Представьте сколько времени можно сэкономить если вам нужно заниматься поддержкой страниц с такими картами на десятке разных доменов <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Удачи!</p>
<p><strong>Интересно почитать</strong>.</p>
<p>Оригинальные и очень красивые отделочные материалы &#8211; <a href="http://www.safari-ukraine.com/material.asp?id=02">РБО и сайдинг бамбуковый</a>.<br />
Создаем собственный микроклимат с помощью <a href="http://ionstream.com.ua">BIOCLIMATIC</a>.</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=736&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/izmenyaem-faily-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как написать задачу для Phing</title>
		<link>http://www.simplecoding.org/kak-napisat-zadachu-dlya-phing.html</link>
		<comments>http://www.simplecoding.org/kak-napisat-zadachu-dlya-phing.html#comments</comments>
		<pubDate>Tue, 30 Dec 2008 15:50:55 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=696</guid>
		<description><![CDATA[Тема работы с Phing уже не однократно поднималась в этом блоге. Переоценить значение этого инструмента очень сложно. Но всегда наступает момент, когда стандартных возможностей становиться недостаточно. В такой ситуации вы можете сами написать нужные функции и оформить их в виде задач.
В этой статье я покажу пример создания такой задачи.
Примечание. Я предполагаю, что вы хотя бы [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_697" class="wp-caption alignnone" style="width: 205px"><img src="http://www.simplecoding.org/wp-content/uploads/2008/12/phing_task.png" alt="phing task" title="phing task" width="195" height="119" class="size-full wp-image-697" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Тема работы с <a href="http://phing.info/trac/">Phing</a> уже не однократно поднималась в этом блоге. Переоценить <a href="http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html">значение этого инструмента</a> очень сложно. Но всегда наступает момент, когда <strong>стандартных возможностей становиться недостаточно</strong>. В такой ситуации вы можете сами написать нужные функции и оформить их в виде задач.</p>
<p>В этой статье я покажу <strong>пример создания такой задачи</strong>.</p>
<p><em>Примечание</em>. Я предполагаю, что вы хотя бы в общих чертах знакомы с <strong>Phing</strong> и знаете как его установить и написать простейший <strong>build файл</strong>. Если нет, советую сначала почитать эти статьи: Программирование на <acronym title="PHP: Hypertext Preprocessor">PHP</acronym>. <a href="http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html">Избавляемся от рутинных операций с помощью Phing</a> и <a href="http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html">Использование Phing для сборки web приложений</a>.</p>
<p>Допустим, нам нужно <strong>изменять кодировку файлов</strong>. На <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> сделать это можно, например, с помощью функции <code>mb_convert_encoding</code>. В качестве параметров она принимает:<br />
- исходный текст;<br />
- нужную кодировку;<br />
- исходную кодировку.<br />
А после выполнения возвращает перекодированный текст.</p>
<p>Т.е. можно написать элементарный <strong><acronym title="PHP: Hypertext Preprocessor">PHP</acronym> скрипт</strong>, который будет изменять кодировки указанных файлов.</p>
<p>Но если нужно выполнять эту операцию на каком-то <strong>промежуточном этапе</strong> при построении проекта, то пользоваться таким скриптом будет не очень удобно. Придется либо запускать его каждый раз вручную, либо писать еще один скрипт, который будет запускать перекодировщик.</p>
<p>С другой стороны, с помощью <strong>Phing</strong> мы можем запустить несколько операций нажатием одной кнопки. Почему бы не добавить сюда и перекодировку?</p>
<p>Итак, приступим.<br />
<span id="more-696"></span><br />
<strong>Шаг 1. Составляем перечень исходных данных</strong>.</p>
<p>Исходя из перечня параметров функции <code>mb_convert_encoding</code> нам потребуются:<br />
- название исходной кодировки файлов;<br />
- название кодировки, в которую мы хотим преобразовать файлы;<br />
- список файлов;<br />
- папку, в которую будем складывать перекодированные файл.</p>
<p>Теперь взгляните на <strong>пример использования</strong> нашей задачи.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">&lt;taskdef name=<span class="st0">&quot;convencoding&quot;</span> classname=<span class="st0">&quot;phing.tasks.my.convEncodingTask&quot;</span> /&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;target name=<span class="st0">&quot;convertencoding&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;convencoding fromencoding=<span class="st0">&quot;windows-1251&quot;</span> toencoding=<span class="st0">&quot;utf-8&quot;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; targetdir=<span class="st0">&quot;new_dir&quot;</span>&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &lt;fileset <span class="kw3">dir</span>=<span class="st0">&quot;src_dir&quot;</span> /&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;/convencoding&gt;</div>
</li>
<li class="li1">
<div class="de1">&lt;/target&gt;</div>
</li>
</ol>
</div>
<p>Разберем его подробнее.</p>
<p>В первой строке мы подключаем нашу задачу. Конечно, на данный момент мы её еще не написали, но уже сейчас нужно определиться с её размещением и названием (задается в атрибуте <code>classname</code>).</p>
<p>В данном случае, она должна находиться в папке <code>phing.tasks.my</code>. Тут <code>phing</code> указывает на папку в которую он установлен, а все точки нужно заменить на «\» (или «/»). </p>
<p>После этого мы создаем новую операцию (<strong>target</strong>) и в неё добавляем нашу задачу (<code>convencoding</code>) (строки 4-7).<br />
В её атрибутах указываем три параметра:<br />
- <code>fromencoding</code> &#8211; исходная кодировка;<br />
- <code>toencoding</code> &#8211; кодировка, которую нужно получить;<br />
- <code>targetdir</code> &#8211; папка, в которую будем складывать перекодированные файлы.</p>
<p>И добавляем тег <code>fileset</code>, в котором определяем список исходных файлов.</p>
<p><strong>Шаг 2. Создаем скрипт задачи.</strong></p>
<p>Для этого заходим в папку с <code>phing/tasks/</code>, создаем в ней папку <code>my</code>, а в ней файл <code>convEncodingTask.php</code>. Этот файл будет содержать весь код нашей задачи. Его название составляется из названия задачи и слова <strong>Task</strong>.</p>
<p>Этот файл должен содержать класс, название которого совпадает с именем файла и, кроме того, он должен быть потомком класса <code>Task</code>.</p>
<p>Объявляем класс.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">require_once</span> <span class="st0">&#039;phing/Task.php&#039;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">class</span> convEncodingTask <span class="kw2">extends</span> Task <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><strong>Шаг 3. Работа с атрибутами</strong>.</p>
<p>Как я уже говорил, все исходные данные для задач <strong>Phing</strong> мы передаем в атрибутах. Поэтому объявляем свойства для каждого атрибута (область видимости &#8211; protected).</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1">protected <span class="re0">$targetDir</span>;</div>
</li>
<li class="li1">
<div class="de1">protected <span class="re0">$fromEncoding</span>;</div>
</li>
<li class="li1">
<div class="de1">protected <span class="re0">$toEncoding</span>;</div>
</li>
<li class="li1">
<div class="de1">protected <span class="re0">$filesets</span> &nbsp; &nbsp;= <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">protected <span class="re0">$failonerror</span> = <span class="kw2">false</span>;</div>
</li>
</ol>
</div>
<p>Названия свойств <strong>должны совпадать</strong> с названиями атрибутов.</p>
<p>Обратите внимание на свойство <code>$filesets</code>, которому мы присвоили пустой массив. В нем будет храниться список файлов, который мы задали с помощью задачи <code>fileset</code> (строка 7 в первом листинге).</p>
<p>Последнее свойство используется для того, чтобы разработчик build файла мог указать нужно ли продолжать выполнение при возникновении ошибки в этой задаче.</p>
<p><strong>Каждый атрибут с исходными данными должен иметь соответствующее свойство и метод, который его устанавливает.</strong></p>
<p>Тут важно понимать, что <strong>Phing вызывает эти методы сам</strong>, т.е. нам нужно их только объявить.</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> setTargetDir<span class="br0">&#40;</span><span class="re0">$targetDir</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">targetDir</span> = <span class="re0">$targetDir</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <span class="kw2">function</span> setFromEncoding<span class="br0">&#40;</span><span class="re0">$fromEncoding</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">fromEncoding</span> = <span class="re0">$fromEncoding</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> setToEncoding<span class="br0">&#40;</span><span class="re0">$toEncoding</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">toEncoding</span> = <span class="re0">$toEncoding</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> setFailonerror<span class="br0">&#40;</span><span class="re0">$value</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">failonerror</span> = <span class="re0">$value</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Как видите, эти методы просто устанавливают значения соответствующих свойств. Их имена образуются добавлением приставки <code>set</code> к имени свойства.</p>
<p><strong>Шаг 4. Добавляем поддержку списка файлов</strong>.</p>
<p>Отдельных пояснений требует метод установки списка файлов. Называется он <code>createFileSet</code>.</p>
<p>В нём мы создаем объект типа <code>FileSet</code>, сохраняем его в массиве <code>$this-&gt;filesets</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> createFileSet<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; <span class="re0">$num</span> = <span class="kw3">array_push</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">filesets</span>, <span class="kw2">new</span> FileSet<span class="br0">&#40;</span><span class="br0">&#41;</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>-&gt;<span class="me1">filesets</span><span class="br0">&#91;</span><span class="re0">$num</span> &#8211; <span class="nu0">1</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Еще раз хочу напомнить. Напрямую к этим методам мы обращаться не будем. Это сделает Phing без нашего участия. Поэтому очень важно правильно записать имена методов и проследить за типом возвращаемых значений.</p>
<p><strong>Шаг 5. Инициализация</strong></p>
<p>Тут нам нужно просто объявить метод <code>init</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> init<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; <span class="kw1">return</span> <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><strong>Шаг 6. Пишем основной метод</strong>.</p>
<p>В нём мы будем выполнять изменение кодировок файлов. На момент его запуска Phing установит значения всех свойств, т.е. мы можем ими спокойно пользоваться (внутри этого метода).</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> main<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; <span class="co1">//проверяем, установлен ли модуль Multibyte String</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">function_exists</span><span class="br0">&#40;</span><span class="st0">&quot;mb_convert_encoding&quot;</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="co1">//начинаем обработку</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//(у нас может быть несколько наборов файлов FileSet)</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">$this</span>-&gt;<span class="me1">filesets</span> <span class="kw1">as</span> <span class="re0">$fs</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; try <span class="br0">&#123;</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="re0">$files</span> = <span class="re0">$fs</span>-&gt;<span class="me1">getDirectoryScanner</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">project</span><span class="br0">&#41;</span>-&gt;<span class="me1">getIncludedFiles</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$fullPath</span> = <span class="kw3">realpath</span><span class="br0">&#40;</span><span class="re0">$fs</span>-&gt;<span class="me1">getDir</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">project</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; &nbsp; &nbsp; <span class="co1">//изменяем кодировку каждого файла</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$files</span> <span class="kw1">as</span> <span class="re0">$file</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; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">log</span><span class="br0">&#40;</span><span class="st0">&#039;Converting file &#039;</span> . <span class="re0">$file</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//формируем путь к конвертированному файлу</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$target</span> = <span class="re0">$this</span>-&gt;<span class="me1">targetDir</span> . <span class="st0">&#039;/&#039;</span> . <span class="kw3">str_replace</span><span class="br0">&#40;</span><span class="re0">$fullPath</span>, <span class="st0">&#034;</span>, <span class="re0">$file</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">file_exists</span><span class="br0">&#40;</span><span class="kw3">dirname</span><span class="br0">&#40;</span><span class="re0">$target</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">false</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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mkdir</span><span class="br0">&#40;</span><span class="kw3">dirname</span><span class="br0">&#40;</span><span class="re0">$target</span><span class="br0">&#41;</span>, <span class="nu0">0700</span>, <span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//конвертируем файл</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; file_put_contents<span class="br0">&#40;</span><span class="re0">$target</span>, <span class="kw3">mb_convert_encoding</span><span class="br0">&#40;</span><span class="kw3">file_get_contents</span><span class="br0">&#40;</span><span class="re0">$fullPath</span> . <span class="st0">&#039;/&#039;</span> . <span class="re0">$file</span><span class="br0">&#41;</span>, <span class="re0">$this</span>-&gt;<span class="me1">toEncoding</span>, <span class="re0">$this</span>-&gt;<span class="me1">fromEncoding</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; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>BuildException <span class="re0">$be</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; &nbsp; &nbsp; <span class="co1">// папка не существует или доступ к ней закрыт</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">failonerror</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; &nbsp; &nbsp; &nbsp; &nbsp; throw <span class="re0">$be</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">log</span><span class="br0">&#40;</span><span class="re0">$be</span>-&gt;<span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="re0">$this</span>-&gt;<span class="me1">quiet</span> ? Project::<span class="me2">MSG_VERBOSE</span> : Project::<span class="me2">MSG_WARN</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</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="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//ошибка (недоступна функция mb_convert_encoding)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$be</span> = <span class="kw2">new</span> BuildException<span class="br0">&#40;</span><span class="st0">&#039;No Multibyte String support&#039;</span><span class="br0">&#41;</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="re0">$this</span>-&gt;<span class="me1">failonerror</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; throw <span class="re0">$be</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="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//если нужно продолжать выполнение build файла, несмотрая на ошибку, просто пишем в лог</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">log</span><span class="br0">&#40;</span><span class="re0">$be</span>-&gt;<span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="re0">$this</span>-&gt;<span class="me1">quiet</span> ? Project::<span class="me2">MSG_VERBOSE</span> : Project::<span class="me2">MSG_WARN</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; <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>Рассмотрим все по порядку.</p>
<p>В строке 3 мы проверяем, доступна ли функция <code>mb_convert_encoding</code>. Если нет, то создаем исключение (<code>BuildException</code>) и в зависимости от значения свойства <code>failonerror</code> либо отправляем его, либо пишем сообщение в лог.</p>
<p>Если функция доступна, <strong>начинаем обработку файлов</strong>.</p>
<p>Как вы помните, список файлов хранится в свойстве <code>filesets</code>, точнее в нем хранится массив объектов <code>FileSet</code>, каждый из которых содержит список файлов.</p>
<p>Поэтому для обработки всех файлов нам нужно использовать два вложенных цикла. Внешний (строка 6) проходит по всем объектам <code>FileSet</code>, а внутренний (строка 12) – по всем файлам в этих объектах.</p>
<p>Вы, наверное, заметили, что здесь мы используем свойство, которого не объявляли (<code>$this-&gt;project</code>). Это свойство содержит объект с данными проекта и создается автоматически. В данном случае мы его используем при получении имен файлов.</p>
<p>Кроме того, мы используем несколько методов объекта <code>FileSet</code>. Например, <code>getDirectoryScanner</code> (объявлен в файле <code>phing\types\AbstractFileSet.php</code>). Подробно я на них останавливаться не буду, названия говорят сами за себя. В любом случае, они нам нужны только для того, чтобы получить список исходных файлов. И в большинстве задач этот код (строки 9-10) меняться не будет.</p>
<p>Во внутреннем цикле (строки 12-21) мы <strong>формируем пути к перекодированным файлам и изменяем кодировку</strong> (строка 20).</p>
<p>Обратите внимание на строку 13. В ней мы записываем в лог имена всех переименованных файлов. Эти записи очень помогают при поиске ошибок в build файлах.</p>
<p>В строках 22-29 мы перехватываем и обрабатываем возможные исключения.</p>
<p><strong>Заключение</strong>.</p>
<p>Как видите, создание собственно задачи для Phing не намного сложнее разработки обычного <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> скрипта. Нужно только знать несколько правил и особенностей.</p>
<p>По большому счету, написать скрипт с аналогичной функциональностью было бы сложнее, т.к. пришлось бы писать парсер для xml файла или придумывать другой способ ввода информации.</p>
<p><strong>Скачать</strong>.</p>
<p>Если вы хотите поэкспериментировать – качайте <a href='http://www.simplecoding.org/wp-content/uploads/2008/12/convencodingtask.zip'>архив с этой задачей</a>. В нем же находится небольшая инструкция по установке.</p>
<p><strong>Интересно почитать</strong>.</p>
<p>Учимся профессионально водить с <a href="http://voditel.info/">авто инструктор</a>ом.<br />
Рассказать о чем-то всему миру можно с помощью <a href="http://www.slando.kz/">бесплатные объявления казахстан</a>.<br />
Позаботиться о своем здоровье вам помогут в <a href="http://polinar.com.ua">клиника Марыныч</a>.</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=696&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/kak-napisat-zadachu-dlya-phing.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Загрузка файлов по FTP с помощью Phing</title>
		<link>http://www.simplecoding.org/zagruzka-fajlov-po-ftp-s-pomoshhyu-phing.html</link>
		<comments>http://www.simplecoding.org/zagruzka-fajlov-po-ftp-s-pomoshhyu-phing.html#comments</comments>
		<pubDate>Wed, 15 Oct 2008 11:40:20 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=580</guid>
		<description><![CDATA[Предыдущая статья о Phing была немного не полной из-за отсутствия возможности загружать файлы на сервер в автоматическом режиме.
В стандартной комплектации Phing загрузку по FTP не поддерживает (кстати, довольно странно). Но, естественно, писать самостоятельно этот task не придется. Все уже сделано за нас   .
Я нашел два task’а, предназначенных для работы с FTP: FtpUploadTask и [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_581" class="wp-caption alignnone" style="width: 260px"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/phing_ftp.png" alt="phing ftp" title="phing ftp" width="250" height="122" class="size-full wp-image-581" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Предыдущая <a href="http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html">статья о Phing</a> была немного не полной из-за отсутствия возможности <strong>загружать файлы на сервер в автоматическом режиме</strong>.</p>
<p>В стандартной комплектации <a href="http://phing.info/">Phing</a> загрузку по <strong><acronym title="File Transfer Protocol">FTP</acronym></strong> не поддерживает (кстати, довольно странно). Но, естественно, писать самостоятельно этот task не придется. Все уже сделано за нас <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
<p>Я нашел два task’а, предназначенных для работы с FTP: <a href="http://miracle.rpz.name/2007/11/15/phing-ftpupload-task/">FtpUploadTask</a> и <a href="http://phing.info/trac/ticket/15">FtpDeploy</a>.<br />
<span id="more-580"></span><br />
Т.к., судя по описанию, возможности и настройки практически идентичны, я расскажу только о первом. К тому же его автор ведет собственный блог (<a href="http://miracle.rpz.name/">Чудо{вищные} заметки</a>) и написал довольно много интересных статей о Phing.</p>
<p>Прежде чем перейти к описанию, хочу предупредить.</p>
<p><strong>Не ставьте эксперименты на вашем рабочем сервере!</strong> Установите локальный <acronym title="File Transfer Protocol">FTP</acronym> (вполне подойдет FileZilla Server (http://filezilla-project.org/)) и тестируйте на нём.</p>
<p><strong>Устанавливаем task</strong>.</p>
<p>Качаем файл <code>FtpUploadTask.php</code> и сохраняем его в папку <code>$PHING_DIR$/tasks/ext/</code> ($<code>PHING_DIR$</code> &#8211; папка в которую установлен <strong>Phing</strong>).</p>
<p><strong>Объявляем новый task</strong>. Для этого в build файл добавляем строку.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;taskdef</span> <span class="re0">name</span>=<span class="st0">&quot;ftpupload&quot;</span> <span class="re0">classname</span>=<span class="st0">&quot;phing.tasks.ext.FtpUploadTask&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
</ol>
</div>
<p>Теперь можно использовать <strong>ftpupload</strong> для отправки файлов на сервер.</p>
<p>Я приведу пример задачи, которую написал в дополнение к <a href="http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html">предыдущей статье</a>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;deploy&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;copyfiles, gzipjs, minifycss&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;ftpupload</span> <span class="re0">host</span>=<span class="st0">&quot;host&quot;</span> <span class="re0">username</span>=<span class="st0">&quot;user&quot;</span> <span class="re0">password</span>=<span class="st0">&quot;pass&quot;</span> <span class="re0">cleanDir</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">targetDir</span>=<span class="st0">&quot;/app_folder/&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/ftpupload<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Здесь мы указали следующие параметры:</p>
<p>1)	<code>host</code> &#8211; адрес сервера;</p>
<p>2)	<code>username</code> – имя пользователя (с правами записи);</p>
<p>3)	<code>password</code> – пароль;</p>
<p>4)	<code>cleanDir</code> – удаляем все старые файлы;</p>
<p>5)	<code>targetDir</code> – папка в которую будет загружено приложение.</p>
<p>Список загружаемых файлов создаем с помощью <code>fileset</code>, т.е. в данном случае мы включили все файлы приложения.</p>
<p>Кроме того, можно задать ещё несколько параметров, например, явно указать порт <acronym title="File Transfer Protocol">FTP</acronym> сервера. Полный список параметров можно посмотреть <a href="http://miracle.rpz.name/2007/11/15/phing-ftpupload-task/">здесь</a>.</p>
<p>Как видите, Phing – это очень удобный инструмент, особенно если вы нашли все необходимые task&#039;и <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  . Но, в любом случае, если вы можете написать <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> скрипт, который решает вашу задачу, то переделать его в виде task’а будет совсем не сложно.</p>
<p>До встречи!</p>
<p><strong>P.S.</strong> Ещё раз хочу напомнить. Подумайте дважды (лучше трижды), прежде чем запускать ftpupload с параметрами <code>cleanDir=&quot;true&quot; targetDir=&quot;/&quot;</code>. Восстановить файлы будет НЕВОЗМОЖНО.</p>
<p><strong>Интересно почитать:</strong></p>
<p><a href="http://www.tyorkin.com/malenkie-xitrosti-google-%E2%80%93-najdem-nashix-konkurentov-v-adsense/">Маленькие хитрости Google – найдем наших конкурентов в AdSense.</a></p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=580&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/zagruzka-fajlov-po-ftp-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Запуск сторонних программ из Eclipse</title>
		<link>http://www.simplecoding.org/zapusk-storonnix-programm-iz-eclipse.html</link>
		<comments>http://www.simplecoding.org/zapusk-storonnix-programm-iz-eclipse.html#comments</comments>
		<pubDate>Tue, 14 Oct 2008 14:45:41 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=573</guid>
		<description><![CDATA[Современные IDE буквально «нашпигованы» различными возможностями. Тем не менее, предусмотреть все невозможно и возникают ситуации, когда нужно использовать дополнительные программы. Речь, прежде всего, идет о различных консольных утилитах.
Естественно, гораздо удобнее, запускать эти утилиты прямо из меню IDE, а не из консоли. Эта заметка о том, как добавить такую возможность в Eclipse.
Прежде чем приступать к настройке [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_574" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/eclipse_cli.png" alt="eclipse cli" title="eclipse cli" width="300" height="131" class="size-full wp-image-574" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Современные <strong>IDE</strong> буквально «нашпигованы» различными возможностями. Тем не менее, предусмотреть все невозможно и возникают ситуации, когда нужно использовать дополнительные программы. Речь, прежде всего, идет о различных консольных утилитах.</p>
<p>Естественно, гораздо удобнее, запускать эти утилиты прямо из меню IDE, а не из консоли. Эта заметка о том, как добавить такую возможность в <a href="http://www.eclipse.org/">Eclipse</a>.</p>
<p>Прежде чем приступать к настройке <strong>Eclipse</strong>, необходимо определиться с параметрами, которые нужно передавать программе.</p>
<p>В качестве примера рассмотрим запуск <a href="http://phing.info/">Phing</a> (о нем речь шла в <a href="http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html">прошлой статье</a>).</p>
<p><strong>Формат команды</strong> такой:<br />
<span id="more-573"></span><br />
<code>phing -f mybuildfile.xml mytarget</code></p>
<p>Сначала идет имя программы, затем имя build файла (mybuildfile.xml) и название задачи которую нужно выполнить (mytarget). Тут предполагается:</p>
<p>1)	что система знает, где находится <strong>phing</strong> (путь указан в переменной PATH), если это не так, то необходимо явно указать путь к нему;</p>
<p>2)	вы выполняете команду в папке, в которой находится файл mybuildfile.xml (в противном случае нужно указать его размещение).</p>
<p>Кроме того, поддерживается <strong>сокращенный вариант записи команды</strong>.</p>
<p>Например, если опустить название файла, то Phing попытается использовать файл build.xml. Название задачи тоже можно не указывать. В этом случае её имя будет взято из атрибута <code>default</code> тега <code>project</code>.</p>
<p>Теперь посмотрим, как запустить эти команды из <strong>Eclipse</strong>. Для начала сделаем вариант запуска без параметров.</p>
<p>Открываем меню <code>Run – External Tools – Open External Tools Dialog…</code></p>
<p>В левой части окна выбираем пункт Program и нажимаем кнопку «New launch configuration» (обведена зеленым).</p>
<p>В правой части окна указываем:</p>
<p>1) Имя задачи (поле Name).</p>
<p>2) Размещение программы (Location). Я указал абсолютный путь к файлу phing.bat.</p>
<p>3) Рабочую папку (Working Directory). Чтобы её выбрать нажимаем кнопку «Browse Workspace» (обведена синим) и выбираем текущий проект.</p>
<p>4) Нажимаем Apply и закрываем это окно.</p>
<p>Описанные настройки показаны на скриншоте.</p>
<div id="attachment_576" class="wp-caption alignnone" style="width: 360px"><a href="http://www.simplecoding.org/wp-content/uploads/2008/10/external_tools.png" target="_blank"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/external_tools_thumb.png" alt="external tools thumb" title="external tools thumb" width="350" height="349" class="size-full wp-image-576" /></a><p class="wp-caption-text"> </p></div>
<p>Теперь нажимаем на панели инструментов на стрелку рядом с кнопкой, на которой нарисованы зеленая стрелка и чемодан.</p>
<div id="attachment_577" class="wp-caption alignnone" style="width: 331px"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/run_phing_menu.png" alt="run phing menu" title="run phing menu" width="321" height="156" class="size-full wp-image-577" /><p class="wp-caption-text"> </p></div>
<p>Как видите, в первом пункте меню появилась наша новая команда (<strong>Phing</strong>).</p>
<p>Теперь добавим возможность запуска <strong>произвольной задачи</strong> из build файла. Для этого снова открываем <strong>Open External Tools Dialog</strong> и создаем ещё одну команду (<strong>Phing custom</strong>). Настройки такие же, только в поле Arguments задаем параметр <code>${string_prompt}</code>. Его можно выбрать, нажав на кнопку Variables (обведена красным).</p>
<div id="attachment_579" class="wp-caption alignnone" style="width: 360px"><a href="http://www.simplecoding.org/wp-content/uploads/2008/10/external_tools_custom.png" target="_blank"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/external_tools_custom_thumb.png" alt="external tools custom thumb" title="external tools custom thumb" width="350" height="348" class="size-full wp-image-579" /></a><p class="wp-caption-text"> </p></div>
<p>После запуска этой команды будет появляться окно, в которое нужно ввести имя задачи.</p>
<p>Таким же образом, можно добавить поддержку практически любых консольных утилит в Eclipse.</p>
<p>Удачи!</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=573&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/zapusk-storonnix-programm-iz-eclipse.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Использование Phing для сборки web приложений</title>
		<link>http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html</link>
		<comments>http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html#comments</comments>
		<pubDate>Mon, 13 Oct 2008 18:51:40 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=570</guid>
		<description><![CDATA[В этой статье я хочу рассказать об использовании Phing при разработке небольшого web приложения. Почему небольшого? Все очень просто. С одной стороны в качестве примера будет использован реальный build файл, а не упрощенный вариант из учебника. А с другой – этот build файл достаточно короткий, и о нем можно было рассказать в рамках статьи  [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_571" class="wp-caption alignnone" style="width: 281px"><img src="http://www.simplecoding.org/wp-content/uploads/2008/10/phing_logo.png" alt="phing logo" title="phing logo" width="271" height="113" class="size-full wp-image-571" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>В этой статье я хочу рассказать об использовании <a href="http://phing.info/">Phing</a> при разработке небольшого <strong>web приложения</strong>. Почему небольшого? Все очень просто. С одной стороны в качестве примера будет использован реальный build файл, а не упрощенный вариант из учебника. А с другой – этот build файл достаточно короткий, и о нем можно было рассказать в рамках статьи <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
<p><em>Примечание</em>. <strong>Phing</strong> – это система сборки проектов, основанная на Apache Ant. Я предполагаю, что вы знаете как её установить и настроить. Если нет – читайте «<a href="http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html">Программирование на <acronym title="PHP: Hypertext Preprocessor">PHP</acronym>. Избавляемся от рутинных операций с помощью Phing</a>».</p>
<p>Итак, <strong>приступим</strong>.</p>
<p>Недавно я писал о <a href="http://www.simplecoding.org/formgenerator/">генераторе форм для фреймворка CodeIgniter</a>. Как вы понимаете приложение небольшое, но, тем не менее, перед переносом его на сервер нужно сделать массу <strong>рутинных операций</strong>.</p>
<p>1)	Subversion в каждой папке приложения создает скрытую папку “.svn”, что значительно усложняет «ручное» копирование файлов. Т.е. каждую папку придется копировать отдельно.</p>
<p>2)	JavaScript и <acronym title="Cascading Style Sheets">CSS</acronym> файлы желательно сжать.</p>
<p>3)	Кроме того, много маленьких файлов загружаются дольше, чем один большой. Т.к. в данном приложении используется 5 js-файлов, то разумно будет объединить их в один. С другой стороны, во время разработки удобнее работать именно с 5-тью маленькими файлами.</p>
<p>4)	Раз мы объединяем несколько js-файлов в один, то необходимо изменить теги <code>&lt;script&gt;</code> в заголовках страниц.</p>
<p>5)	Практически все современные браузеры поддерживают gzip сжатие. Поэтому сделаем архивную версию объединенного JavaScript файла (для браузеров, которые поддерживают gzip, будем отдавать архивную версию, всем остальным &#8211; обычную).</p>
<p>Как видите, работы не много. Но представьте, вы подготовили приложения для размещения на сервере, и нашли ошибку или решили что-то изменить. Исправить сжатые js файлы конечно можно, но, поверьте, это далеко не самое увлекательное занятие <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  . Т.е. вам придется внести исправления в исходный вариант и выполнить все шаги с 1 по 5 заново.</p>
<p>Естественно такую работу можно автоматизировать и Phing отлично подойдет в этой ситуации.<br />
<span id="more-570"></span><br />
Рассмотрим <strong>размещение файлов проекта</strong>.</p>
<pre>css/
	ie6styles.css
	styles.css
images/
	add.png
	ci_logo.jpg
	.......
lib/
	jquery/
		jquery.js
	tabs/
		jquery-ui-personalized-1.5.2.js
	tooltip/
		jquery.dimensions.js
		jquery.tooltip.js
	mainscripts.js
index.html
.htaccess
build.xml</pre>
<p>Здесь <code>index.html</code> – единственная страница приложения, <code>build.xml</code> – файл с задачами для Phing, <code>.htaccess</code> – определяет в каком случае отправлять архивную версию js файла (подробнее <a href="http://www.simplecoding.org/uvelichivaem-skorost-zagruzki-web-stranic.html">здесь</a>).</p>
<p><strong>Переходим к build файлу</strong>. Т.к. он довольно объемный я буду приводить его по частям. Прежде всего, создаем проект и несколько свойств.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;project</span> <span class="re0">name</span>=<span class="st0">&quot;CIFormBuilder&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;deploy&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; &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;DEPLOY_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;deploy&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;IMG_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;images&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;CSS_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;css&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;LIB_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;lib&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;property</span> <span class="re0">name</span>=<span class="st0">&quot;GLOBAL_LIB_DIR&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;E:/www/libs&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &#8230;&#8230;&#8230;&#8230;.</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/project<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Имя (<code>name</code>) проекта выбираем произвольно. В атрибуте <code>default</code> указываем название задачи, которая будет выполняться по умолчанию. <code>basedir</code> – корневая папка проекта.</p>
<p>С помощью свойств (<code>property</code>) мы объявили константы, которые в данном случае содержат имена папок.</p>
<p>Отдельно хочу остановиться на <code>GLOBAL_LIB_DIR</code>. Это свойство содержит имя папки, в которой находятся <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> скрипты для сжатия файлов (подробнее о них ниже).</p>
<p>Как вы, наверное, догадались, все файлы проекта, предназначенные для размещения на сервере, мы скопируем в папку <code>deploy</code>. Поэтому, прежде всего, создаем её.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;prepare&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Removing old files&#8230;&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;delete</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span> <span class="re0">includeemptydirs</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">verbose</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">failonerror</span>=<span class="st0">&quot;true&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Creating new dir&#8230;&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;mkdir</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Эта задача сначала пытается удалить папку <code>deploy</code> (операция <code>delete</code>) вместе со всем содержимым, а затем с помощью <code>mkdir</code> создает её заново. Таким образом, можно быть уверенным, что проект не будет содержать старых файлов.</p>
<p><em>Примечание</em>. Операция <code>echo</code> выводит произвольное сообщение. К сожалению, русские буквы отображаются не правильно.</p>
<p>Теперь <strong>копируем в эту папку все файлы кроме js и css</strong>. И сразу же исправляем теги <code>&lt;script&gt;</code> в <code>index.html</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;copyfiles&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;prepare&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Copying images&#8230;&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;copy</span> <span class="re0">todir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${IMG_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;${IMG_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;*.gif&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;*.png&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;*.jpg&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/copy<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Copying main files&#8230;&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;copy</span> <span class="re0">todir</span>=<span class="st0">&quot;${DEPLOY_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;.&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;index.html&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;.htaccess&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;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;filterchain<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;replaceregexp<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;regexp</span> <span class="re0">pattern</span>=<span class="st0">&quot;&lt;script.*\/script&gt;</span>\r\n&quot; replace=&quot;&quot; /&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3">&lt;regexp pattern=&quot;</span><span class="br0">&#40;</span><span class="re1">&lt;</span>\/head<span class="re2">&gt;</span></span>)&quot;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; replace=&quot;<span class="sc3"><span class="re1">&lt;script</span> <span class="re0">type</span>=<span class="st0">&quot;text/javascript&quot;</span> <span class="re0">src</span>=<span class="st0">&quot;lib/global.js&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/script<span class="re2">&gt;</span></span></span>\1&quot; /&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;regexp</span> <span class="re0">pattern</span>=<span class="st0">&quot;\.css&quot;</span> <span class="re0">replace</span>=<span class="st0">&quot;-min.css&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/replaceregexp<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/filterchain<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/copy<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Разберем эту задачу подробнее. В первой строке мы задали название и указали, что эта задача зависит от <code>prepare</code>. Т.е. при вызове <code>copyfiles</code> всегда предварительно будет выполняться <code>prepare</code>.</p>
<p>В строках 3-9 мы копируем файлы картинок. Для этого используется операция <code>copy</code>, а список файлов, которые нужно скопировать, создается с помощью <code>fileset</code>.</p>
<p>После этого копируем <code>index.html</code> и <code>.htaccess</code>. Здесь наибольший интерес представляет операция <code>filterchain</code>. Она создает цепочку фильтров, через которые пропускаются файлы. В данном случае фильтр только один. В нем мы используем операцию замены по регулярному выражению <code>replaceregexp</code>.</p>
<p>Первое правило (строка 18) удаляет все теги <code>&lt;script&gt;</code>. Второе – находит тег <code>&lt;/head&gt;</code> и вставляет перед ним тег скрипт со ссылкой на объединенный js файл (<code>global.js</code>). Третье – добавляет к именам css файлов суффикс <code>-min</code> (сжатые версии файлов).</p>
<p>Таким образом, в папку deploy будет записан исправленный index.html.</p>
<p>Теперь <strong>займемся сжатием файлов</strong>.</p>
<p>В стандартную поставку Phing нужные нам задачи не входят. Поэтому нам понадобятся две библиотеки: <a href="http://code.google.com/p/jsmin-php/">JSMin</a> и <a href="http://code.google.com/p/cssmin/">CSSMin</a>. Размещаем их в папке, которую мы задали в свойстве <code>GLOBAL_LIB_DIR</code>.</p>
<p>Напрямую работать с библиотеками Phing не может. Поэтому нужно создать соответствующие операции (<code>tasks</code>). Каждая такая операция представляет собой <strong><acronym title="PHP: Hypertext Preprocessor">PHP</acronym> класс</strong>. Описать его в рамках одной статьи не реально, да и необходимости в этом нет. Для бибилиотеки JsMin я нашел <a href="http://stubbles.net/browser/trunk/src/main/php/info/phing/tasks/stubJsMinTask.php?rev=984">готовое решение</a> и в течении 15 минут переписал его для использования с CSSMin (в конце статьи приведена ссылка на архив с этими файлами).</p>
<p>Т.е. вам нужно просто распаковать этот архив в папку <code>#PHING_DIR#/tasks</code>.</p>
<p>Для того, чтобы Phing узнал о том, что вы создали операцию необходимо в build файле использовать <code>taskdef</code>. Выглядит это так:</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;taskdef</span> <span class="re0">name</span>=<span class="st0">&quot;stubjsmin&quot;</span> <span class="re0">classname</span>=<span class="st0">&quot;phing.tasks.my.stubJsMinTask&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;taskdef</span> <span class="re0">name</span>=<span class="st0">&quot;stubcssmin&quot;</span> <span class="re0">classname</span>=<span class="st0">&quot;phing.tasks.my.stubCssMinTask&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
</ol>
</div>
<p>Правила следующие. Имя должно совпадать с именем класса, но без окончания task. Имя класса (<code>classname</code>) задает имя класса с учетом пути к нему (в качестве разделителя папок используется точка).</p>
<p>Теперь <strong>напишем задачу, которая будет сжимать js файлы</strong>. Сначала создадим набор файлов (<code>fileset</code>).</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">id</span>=<span class="st0">&quot;srcjs&quot;</span> <span class="re0">dir</span>=<span class="st0">&quot;${LIB_DIR}&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;include</span> <span class="re0">name</span>=<span class="st0">&quot;jquery/jquery.js&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;include</span> <span class="re0">name</span>=<span class="st0">&quot;tabs/jquery-ui-personalized-1.5.2.js&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;include</span> <span class="re0">name</span>=<span class="st0">&quot;tooltip/jquery.dimensions.js&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;include</span> <span class="re0">name</span>=<span class="st0">&quot;tooltip/jquery.tooltip.js&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;include</span> <span class="re0">name</span>=<span class="st0">&quot;mainscripts.js&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Теперь <strong>сжимаем файлы</strong>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;minifyjs&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Minifying JavaScript files&#8230;&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;stubjsmin</span> <span class="re0">jsminpath</span>=<span class="st0">&quot;${GLOBAL_LIB_DIR}/jsmin/jsmin-1.1.1.php&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">targetdir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${LIB_DIR}&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;fileset</span> <span class="re0">refid</span>=<span class="st0">&quot;srcjs&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;/stubjsmin<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Здесь нужно отметить два момента.</p>
<p>Первый – использование операции <code>stubjsmin</code>. В её параметрах мы указываем размещение библиотеки JSmin и путь к папке, в которой будут размещены сжатые файлы. При записи сжатых файлов будет сохранена структура папок, в которых они размещены.</p>
<p>Второй – использование <code>fileset</code> внутри <code>stubjsmin</code>. Имя набора файлов указывается с помощью параметра <code>refid</code>.</p>
<p><strong>Сжатие <acronym title="Cascading Style Sheets">CSS</acronym> файлов</strong> выполняется точно также.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;minifycss&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Minifying <acronym title="Cascading Style Sheets">CSS</acronym> files&#8230;&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;stubcssmin</span> <span class="re0">cssminpath</span>=<span class="st0">&quot;${GLOBAL_LIB_DIR}/cssmin/cssmin_v.1.0.php&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">targetdir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${CSS_DIR}&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;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;${CSS_DIR}&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;/stubcssmin<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Теперь <strong>объединяем JavaScript файлы в один и удаляем сжатые версии js файлов</strong>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;combinejs&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;minifyjs&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;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Creating single js file&#8230;&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;append</span> <span class="re0">destFile</span>=<span class="st0">&quot;${DEPLOY_DIR}/${LIB_DIR}/global.js&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;filelist</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">files</span>=<span class="st0">&quot;jquery/jquery-min.js, tabs/jquery-ui-personalized-1.5.2-min.js, tooltip/jquery.dimensions-min.js, tooltip/jquery.tooltip-min.js, mainscripts-min.js&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;/append<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">msg</span>=<span class="st0">&quot;Deleting minified js files&#8230;&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;delete</span> <span class="re0">includeemptydirs</span>=<span class="st0">&quot;true&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;**&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;exclude</span> <span class="re0">name</span>=<span class="st0">&quot;global.js&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/delete<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Операций всего две.</p>
<p>1)	Объединение файлов (<code>append</code>). Файл, в который будет записан результат, задается с помощью параметра <code>destFile</code>, а файлы-источники – с помощью <code>filelist</code>. Это <strong>важный момент</strong>, т.к. нам нужно объединять файлы в определенном порядке (сначала библиотеки, а потом функции, их использующие). А <code>filelist</code> в отличие от <code>fileset</code> сохраняет не только имена файлов, но и порядок в котором они перечислены.</p>
<p>2)	Удаление (<code>delete</code>) ненужных файлов. Здесь все просто. Удаляем все файлы и папки кроме <code>global.js</code> (строка 11).</p>
<p>Теперь нам нужно заархивировать (gzip) файл <code>global.js</code>.</p>
<p>Тут я столкнулся с одним непонятным моментом. В принципе, существует операция <code>tar</code>, в параметрах которой можно указать метод сжатия – <code>gzip</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;tar</span> <span class="re0">destfile</span>=<span class="st0">&quot;archive_name.gz&quot;</span> <span class="re0">basedir</span>=<span class="st0">&quot;.&quot;</span> <span class="re0">compression</span>=<span class="st0">&quot;gzip&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
</ol>
</div>
<p>Но почему-то браузеры не понимают созданные таким образом архивы.</p>
<p>В общем, разбираться было лень, и я решил задачу «в лоб». Использовал архиватор <a href="http://www.7-zip.org/">7-zip</a>. Для выполнения системных команд в Phing предусмотрена операция <code>exec</code>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;gzipjs&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;combinejs&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;exec</span> <span class="re0">command</span>=<span class="st0">&quot;&amp; quot;c:\program files\7-zip\7z.exe&amp; quot; a -tgzip global.js.gz global.js&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">dir</span>=<span class="st0">&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p><strong>Обратите внимание</strong>. Если путь к файлу содержит пробелы, то его нужно взять в кавычки, которые задаются с помощью эскейп последовательности <code>&amp;quot;</code>. Параметр <code>dir</code> указывает рабочую папку программы.</p>
<p>И <strong>завершающий штрих</strong>. Задача <code>deploy</code>. Сама по себе она ничего не делает, но в её параметре depends перечислены задачи, которые должны быть выполнены при её вызове.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;deploy&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;copyfiles, gzipjs, minifycss&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Таким образом, если выполнить команду</p>
<p><code>e:\projectfolder&gt; phing</code></p>
<p>в корневой папке проекта, то будут последовательно запущены все перечисленные в этой статье задачи.<br />
<em>Примечание</em>. Если имя build файла не указано явно, то Phing ищет build.xml. Тоже самое касается задачи. По умолчанию выполняется та, которая указана в параметре <code>default</code> (в данном случае – это <code>deploy</code>).</p>
<p><strong>Скачать</strong></p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2008/10/css_js_tasks.zip'>Архив с stubJsMinTask и stubCssMinTask</a>.</p>
<p>Если возникли вопросы или замечания, не стесняемся, комментарии открыты <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
<p>До встречи!</p><img src="http://www.simplecoding.org/?ak_action=api_record_view&id=570&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Программирование на PHP. Избавляемся от рутинных операций с помощью Phing</title>
		<link>http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html</link>
		<comments>http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html#comments</comments>
		<pubDate>Thu, 05 Jun 2008 09:08:41 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Phing]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html</guid>
		<description><![CDATA[
В этой статье я хочу рассказать об инструменте, который может значительно сэкономить ваше время и защитить от механических ошибок. Этот инструмент очень часто применяется при разработке крупных проектов профессиональными командами. Но в этой статье я постараюсь показать, что он пригодится и при самостоятельной разработке небольших web приложений.
Речь, конечно, пойдет о Phing. Он позволяет автоматизировать большинство [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.simplecoding.org/wp-content/uploads/2008/06/phing_logo.png" alt="Логотип статьи о Phing" style="float: left" /></p>
<p>В этой статье я хочу рассказать об инструменте, который может значительно <strong>сэкономить ваше время и защитить от механических ошибок</strong>. Этот инструмент очень часто применяется при разработке крупных проектов профессиональными командами. Но в этой статье я постараюсь показать, что он пригодится и при <strong>самостоятельной разработке</strong> небольших web приложений.</p>
<p>Речь, конечно, пойдет о <a href="http://phing.info/trac/">Phing</a>. Он позволяет автоматизировать большинство рутинных операций, с которыми вы можете столкнуться во время разработки.</p>
<p><strong>Принцип работы</strong> следующий. Вы создаете xml файл, в который записываете необходимые группы действия (о синтаксисе этого файла немного ниже), после этого вы сможете <strong>выполнить любую группу действий всего одной командой</strong>. Т.е., по большому счету, phing можно считать «продвинутой» версией командных файлов.<br />
<span id="more-318"></span><br />
<strong>Примечание</strong>. Проект Phing основан на <a href="http://ant.apache.org/">Apache Ant</a> о котором я <a href="http://www.simplecoding.org/nastrojka-i-ispolzovanie-apache-ant.html">уже писал</a>. Синтаксис файлов практически одинаков, основная разница заключается в том, что ant ориентирован в первую очередь на Java, а phing – на <acronym title="PHP: Hypertext Preprocessor">PHP</acronym>.</p>
<p>Сделать даже сокращенный обзор возможностей такого инструмента в рамках статьи практически невозможно, поэтому я только покажу парочку практических примеров, чтобы вы могли сформировать общее представление о нем (если у вас его еще нет <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).</p>
<p>Прежде всего, разберемся, в каких случаях <strong>нет смысла</strong> применять Phing. Принцип очень простой. Чем больше и сложнее проект, тем больше выигрыш от использования Phing. Т.е. если ваш проект содержит больше одного-двух десятков файлов, вам имеет смысл подумать об использовании этого инструмента.</p>
<p><strong>Переходим к установке</strong>. Phing распространяется в двух вариантах. В виде PEAR пакета и как отдельный дистрибутив.</p>
<p>Для первого варианта установка сводится к выполнению двух команд:<br />
<code>pear channel-discover pear.phing.info<br />
pear install phing/phing</code></p>
<p>А второй – достаточно подробно описан в документации, и останавливаться на нем я не буду.</p>
<p>Теперь выбираем проект и создаем для него build файл.</p>
<p>Для этого примера я взял проект с такой структурой:</p>
<pre>public_html
	index.php
	js/
	css/
	system/
		application/
		............</pre>
<p>Как видите, проект довольно простой, содержит две папки с таблицами стилей и JavaScript файлами, а в папке system – находится фреймворк CodeIgniter и php скрипты самого приложения (папка application).</p>
<p>Допустим, мы хотим передать кому-то архив с этим web приложением. Естественно, архив несложно создать вручную, всего пара кликов мышкой. Но подождите, если мы не хотим включать в него файлы фреймворка, то нам придется вручную сортировать файлы для архива.</p>
<p>Попробуем <strong>автоматизировать эту работу с помощью Phing</strong>.</p>
<p>Прежде всего, <strong>создадим папку</strong>, в которую будет помещен архив. Для этого создаем файл build.xml и пишем в него следующее:</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;PhingTesting&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;packSrc&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; &nbsp; <span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;prepare&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;mkdir</span> <span class="re0">dir</span>=<span class="st0">&quot;archive&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/mkdir<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></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;packSrc&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;prepare&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/project<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Разберем, что здесь написано.</p>
<p>Первая строка – обычный заголовок xml файла. Сразу за ней мы добавили тег <code>project</code>, внутри которого будут находиться все задачи данного проекта. Этот тег имеет три атрибута:<br />
<code>name</code> – имя проекта;<br />
<code>default</code> – имя задачи, которая будет выполняться по-умолчанию;<br />
<code>basedir</code> – корневая папка проекта.</p>
<p>Внутри тега <code>project</code> может находиться любое количество тегов <code>target</code>, которые соответствуют конкретным задачам. Наша первая задача (строки 3-5) называется <code>prepare</code> и содержит всего одну операцию (task) – <code>mkdir</code>, которая создает папку.</p>
<p>Обратите внимание, что все операции по-сути являются обычными xml тегами, а в их атрибутах указываются параметры операций. В данном случае в атрибуте <code>dir</code> мы указали имя папки, которую нужно создать.</p>
<p>Теперь <strong>выполняем команду</strong></p>
<p><code>phing prepare</code></p>
<p><strong>Примечание</strong>. Название файла может быть любым, но если оно отличается от build.xml его придется указывать явно (например, <code>phing my_file.xml prepare</code>).</p>
<p>Теперь переходим к <strong>созданию архива</strong>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;packSrc&quot;</span> <span class="re0">depends</span>=<span class="st0">&quot;prepare&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;zip</span> <span class="re0">destfile</span>=<span class="st0">&quot;archive/my_project.zip&quot;</span> <span class="re0">basedir</span>=<span class="st0">&quot;public_html&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/zip<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Для этого мы создадим еще одну задачу &#8211; <code>packSrc</code>. Кстати, обратите внимание на ее атрибут <code>depends</code>. В нем можно перечислить задачи, которые должны быть выполнены раньше текущей. В данном случае в этом атрибуте мы указали задачу <code>prepare</code>, т.е. теперь нам не нужно запускать ее вручную.</p>
<p>Для создания архива используется тег <code>zip</code>, в атрибутах которого нужно указать имя файла с архивом и файлы, которые нужно в него добавить.</p>
<p>На данный момент в архив будет добавляться весь проект целиком. Исправляем ситуацию.</p>
<div class="dean_ch" style="white-space: nowrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;zip</span> <span class="re0">destfile</span>=<span class="st0">&quot;archive/my_project.zip&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;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;public_html&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;index.php&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/include<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;css/**&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/include<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;js/**&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/include<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;system/application/**&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/include<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/zip<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Как видите, мы добавили вложенный тег <code>fileset</code>, который предназначен для создания <strong>набора файлов</strong>. Добавление и удаление конкретных файлов и папок в набор выполняется тегами <code>include</code> и <code>exclude</code>, в атрибуте <code>name</code> которых указывают конкретное имя.</p>
<p>Хочу отметить, что в этом примере показан, в общем-то, самый простой способ выбора файлов. Phing позволяет создавать гораздо более сложные правила и выбирать файлы не только по их имени, но и по дате создания, размеру, содержимому и т.д.</p>
<p>Кроме того, с помощью Phing можно запускать тесты, создавать документацию (PHPdocumentor), переименовывать файлы и папки, менять их содержимое, «заливать» файлы на сервер и выполнять множество других операций. К тому же вы всегда сможете расширить функциональность любой из стандартных задач Phing или написать свою собственную.</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=318&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
