<?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>Fri, 27 Jan 2012 18:27:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<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">Программирование на PHP. Избавляемся от рутинных операций с помощью 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>
<pre class="brush: bash">mysqldump -uпользователь -pпароль название_базы > dump.sql</pre>
<p>Для сохранения файла в <strong>Subversion</strong> используется команда <strong>commit</strong>.</p>
<pre class="brush: bash">svn.exe commit -m “db_backup” --username имя --password пароль имя_файла</pre>
<p>Здесь мы указываем текст сообщения (после параметра -m), имя пользователя Subversion, его пароль и имя файла, который нужно сохранить.</p>
<p><em>Примечание</em>. Подробнее об этой системе контроля версий можно почитать в разделе <a href="http://www.simplecoding.org/category/sv">Subversion</a>.</p>
<p>Теперь рассмотрим build-файл.</p>
<pre class="brush: xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project name="DbBackup" default="commit" basedir="."&gt;

	&lt;property name="DUMP_FILE" value="dump.sql" /&gt;
	&lt;property name="MYSQL_PATH" value="путь_к_mysql" /&gt;
	&lt;property name="DB_NAME" value="имя_базы_данных" /&gt;
	&lt;property name="DB_HOST" value="localhost" /&gt;
	&lt;property name="DB_USER" value="имя_пользователя_mysql" /&gt;
	&lt;property name="DB_PASS" value="пароль_mysql" /&gt;

	&lt;property name="SVN_USER" value="имя_пользователя_subversion" /&gt;
	&lt;property name="SVN_PASS" value="пароль_subversion" /&gt;

	&lt;target name="backup"&gt;
		&lt;exec command="${MYSQL_PATH}mysqldump -u${DB_USER} -p${DB_PASS} ${DB_NAME} &gt; ${DUMP_FILE}" dir="." /&gt;
	&lt;/target&gt;

	&lt;target name="commit" depends="backup"&gt;
		&lt;exec command="svn.exe commit -m &quot;db_backup&quot; --username ${SVN_USER} --password ${SVN_PASS} ${DUMP_FILE}" dir="." /&gt;
	&lt;/target&gt;
&lt;/project&gt;</pre>
<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>
<pre class="brush: bash">phing -verbose</pre>
<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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/phing-backup-i-soxranenie-v-subversion-bazy-dannyx.html/feed</wfw:commentRss>
		<slash:comments>66</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>API-ключ</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>
<pre class="brush: html">&lt;script src="http://api-maps.yandex.ru/1.0/index.xml?key=key_for_local_domen" type="text/javascript"&gt;&lt;/script&gt;</pre>
<p>Здесь нам нужно <code>key_for_local_domen</code> заменить на новый ключ.</p>
<p><strong>Посмотрим как с помощью Phing решить эту задачу</strong>.</p>
<p>Создаем в корне проекта файл с названием <code>build.xml</code></p>
<pre class="brush: xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project name="IPLocYandexMaps" default="deploy" basedir="."&gt;

	&lt;property name="DEPLOY_DIR" value="deploy" /&gt;
	&lt;property name="SRC_DIR" value="public_html" /&gt;
	&lt;property name="DEPLOY_KEY" value="api-key-for-my-host" /&gt;

	&lt;target name="prepare"&gt;
		&lt;echo msg="Removing old files..." /&gt;
		&lt;delete dir="${DEPLOY_DIR}" includeemptydirs="true" verbose="true" failonerror="true" /&gt;
		&lt;echo msg="Creating new dir..." /&gt;
		&lt;mkdir dir="${DEPLOY_DIR}" /&gt;
	&lt;/target&gt;

	&lt;target name="copyfiles" depends="prepare"&gt;
		&lt;echo msg="Copying main files..." /&gt;
		&lt;copy todir="${DEPLOY_DIR}"&gt;
			&lt;fileset dir="${SRC_DIR}"&gt;
				&lt;include name="index.php" /&gt;
			&lt;/fileset&gt;
			&lt;filterchain&gt;
				&lt;replaceregexp&gt;
					&lt;regexp pattern="index.xml\?key=(.*?)&quot;" replace="index.xml?key=${DEPLOY_KEY}&quot;" /&gt;
				&lt;/replaceregexp&gt;
			&lt;/filterchain&gt;
		&lt;/copy&gt;
	&lt;/target&gt;

	&lt;target name="deploy" depends="copyfiles"&gt;
	&lt;/target&gt;
&lt;/project&gt;</pre>
<p>Теперь рассмотрим как это все работает.</p>
<p>В начале (строки 4-6) мы объявили три константы:<br />
<code>DEPLOY_DIR</code> – имя папки, в которой будет размещен измененный файл (в данном примере – index.php);<br />
<code>SRC_DIR</code> – имя папки с исходным файом;<br />
<code>DEPLOY_KEY</code> – API-ключ.</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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/izmenyaem-faily-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>2</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[Phing]]></category>
		<category><![CDATA[PHP]]></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>. Если нет, советую сначала почитать эти статьи: Программирование на PHP. <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>. На PHP сделать это можно, например, с помощью функции <code>mb_convert_encoding</code>. В качестве параметров она принимает:<br />
- исходный текст;<br />
- нужную кодировку;<br />
- исходную кодировку.<br />
А после выполнения возвращает перекодированный текст.</p>
<p>Т.е. можно написать элементарный <strong>PHP скрипт</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>
<pre class="brush: php">&lt;taskdef name=&quot;convencoding&quot; classname=&quot;phing.tasks.my.convEncodingTask&quot; /&gt;

&lt;target name=&quot;convertencoding&quot;&gt;
	&lt;convencoding fromencoding=&quot;windows-1251&quot; toencoding=&quot;utf-8&quot;
		targetdir=&quot;new_dir&quot;&gt;
		&lt;fileset dir=&quot;src_dir&quot; /&gt;
	&lt;/convencoding&gt;
&lt;/target&gt;</pre>
<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>
<pre class="brush: php">require_once 'phing/Task.php';

class convEncodingTask extends Task {

}</pre>
<p><strong>Шаг 3. Работа с атрибутами</strong>.</p>
<p>Как я уже говорил, все исходные данные для задач <strong>Phing</strong> мы передаем в атрибутах. Поэтому объявляем свойства для каждого атрибута (область видимости &#8211; protected).</p>
<pre class="brush: php">protected $targetDir;
protected $fromEncoding;
protected $toEncoding;
protected $filesets    = array();
protected $failonerror = false;</pre>
<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>
<pre class="brush: php">public function setTargetDir($targetDir) {
	$this-&gt;targetDir = $targetDir;
}

public function setFromEncoding($fromEncoding) {
	$this-&gt;fromEncoding = $fromEncoding;
}

public function setToEncoding($toEncoding) {
	$this-&gt;toEncoding = $toEncoding;
}

public function setFailonerror($value) {
	$this-&gt;failonerror = $value;
}</pre>
<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>
<pre class="brush: php">public function createFileSet() {
	$num = array_push($this-&gt;filesets, new FileSet());
	return $this-&gt;filesets[$num - 1];
}</pre>
<p>Еще раз хочу напомнить. Напрямую к этим методам мы обращаться не будем. Это сделает Phing без нашего участия. Поэтому очень важно правильно записать имена методов и проследить за типом возвращаемых значений.</p>
<p><strong>Шаг 5. Инициализация</strong></p>
<p>Тут нам нужно просто объявить метод <code>init</code></p>
<pre class="brush: php">public function init() {
    return true;
}</pre>
<p><strong>Шаг 6. Пишем основной метод</strong>.</p>
<p>В нём мы будем выполнять изменение кодировок файлов. На момент его запуска Phing установит значения всех свойств, т.е. мы можем ими спокойно пользоваться (внутри этого метода).</p>
<p>Теперь взгляните на код метода.</p>
<pre class="brush: php">public function main() {
	//проверяем, установлен ли модуль Multibyte String
	if (function_exists(&quot;mb_convert_encoding&quot;)) {
		//начинаем обработку
		//(у нас может быть несколько наборов файлов FileSet)
		foreach ($this-&gt;filesets as $fs) {
			try {
				//получаем массив со списком исходных файлов
				$files = $fs-&gt;getDirectoryScanner($this-&gt;project)-&gt;getIncludedFiles();
				$fullPath = realpath($fs-&gt;getDir($this-&gt;project));
				//изменяем кодировку каждого файла
				foreach ($files as $file) {
					$this-&gt;log('Converting file ' . $file);
					//формируем путь к конвертированному файлу
					$target = $this-&gt;targetDir . '/' . str_replace($fullPath, '', $file);
					if (file_exists(dirname($target)) == false) {
						mkdir(dirname($target), 0700, true);
					}
					//конвертируем файл
					file_put_contents($target, mb_convert_encoding(file_get_contents($fullPath . '/' . $file), $this-&gt;toEncoding, $this-&gt;fromEncoding));
				}
			} catch (BuildException $be) {
				// папка не существует или доступ к ней закрыт
				if ($this-&gt;failonerror) {
					throw $be;
				} else {
					$this-&gt;log($be-&gt;getMessage(), $this-&gt;quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
				}
			}
		}
	}
	else {
		//ошибка (недоступна функция mb_convert_encoding)
		$be = new BuildException('No Multibyte String support');
		if ($this-&gt;failonerror) {
			throw $be;
		}
		else {
			//если нужно продолжать выполнение build файла, несмотрая на ошибку, просто пишем в лог
			$this-&gt;log($be-&gt;getMessage(), $this-&gt;quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
		}
	}
}</pre>
<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 не намного сложнее разработки обычного PHP скрипта. Нужно только знать несколько правил и особенностей.</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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/kak-napisat-zadachu-dlya-phing.html/feed</wfw:commentRss>
		<slash:comments>4</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[Phing]]></category>
		<category><![CDATA[PHP]]></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>FTP</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> Установите локальный FTP (вполне подойдет 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>
<pre class="brush: xml">&lt;taskdef name=&quot;ftpupload&quot; classname=&quot;phing.tasks.ext.FtpUploadTask&quot; /&gt;</pre>
<p>Теперь можно использовать <strong>ftpupload</strong> для отправки файлов на сервер.</p>
<p>Я приведу пример задачи, которую написал в дополнение к <a href="http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html">предыдущей статье</a>.</p>
<pre class="brush: xml">&lt;target name=&quot;deploy&quot; depends=&quot;copyfiles, gzipjs, minifycss&quot;&gt;
	&lt;ftpupload host=&quot;host&quot; username=&quot;user&quot; password=&quot;pass&quot; cleanDir=&quot;true&quot; targetDir=&quot;/app_folder/&quot;&gt;
		&lt;fileset dir=&quot;${DEPLOY_DIR}&quot;&gt;
		&lt;/fileset&gt;
	&lt;/ftpupload&gt;
&lt;/target&gt;</pre>
<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>Кроме того, можно задать ещё несколько параметров, например, явно указать порт FTP сервера. Полный список параметров можно посмотреть <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' />  . Но, в любом случае, если вы можете написать PHP скрипт, который решает вашу задачу, то переделать его в виде 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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/zagruzka-fajlov-po-ftp-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>6</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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/zapusk-storonnix-programm-iz-eclipse.html/feed</wfw:commentRss>
		<slash:comments>20</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">Программирование на PHP. Избавляемся от рутинных операций с помощью 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 и CSS файлы желательно сжать.</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>
<pre class="brush: xml">&lt;project name=&quot;CIFormBuilder&quot; default=&quot;deploy&quot; basedir=&quot;.&quot;&gt;

	&lt;property name=&quot;DEPLOY_DIR&quot; value=&quot;deploy&quot; /&gt;
	&lt;property name=&quot;IMG_DIR&quot; value=&quot;images&quot; /&gt;
	&lt;property name=&quot;CSS_DIR&quot; value=&quot;css&quot; /&gt;
	&lt;property name=&quot;LIB_DIR&quot; value=&quot;lib&quot; /&gt;

	&lt;property name=&quot;GLOBAL_LIB_DIR&quot; value=&quot;E:/www/libs&quot; /&gt;

	.............

&lt;/project&gt;</pre>
<p>Имя (<code>name</code>) проекта выбираем произвольно. В атрибуте <code>default</code> указываем название задачи, которая будет выполняться по умолчанию. <code>basedir</code> – корневая папка проекта.</p>
<p>С помощью свойств (<code>property</code>) мы объявили константы, которые в данном случае содержат имена папок.</p>
<p>Отдельно хочу остановиться на <code>GLOBAL_LIB_DIR</code>. Это свойство содержит имя папки, в которой находятся PHP скрипты для сжатия файлов (подробнее о них ниже).</p>
<p>Как вы, наверное, догадались, все файлы проекта, предназначенные для размещения на сервере, мы скопируем в папку <code>deploy</code>. Поэтому, прежде всего, создаем её.</p>
<pre class="brush: xml">&lt;target name=&quot;prepare&quot;&gt;
	&lt;echo msg=&quot;Removing old files...&quot; /&gt;
	&lt;delete dir=&quot;${DEPLOY_DIR}&quot; includeemptydirs=&quot;true&quot; verbose=&quot;true&quot; failonerror=&quot;true&quot; /&gt;
	&lt;echo msg=&quot;Creating new dir...&quot; /&gt;
	&lt;mkdir dir=&quot;${DEPLOY_DIR}&quot; /&gt;
&lt;/target&gt;</pre>
<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>
<pre class="brush: xml"><target name="copyfiles" depends="prepare">
	<echo msg="Copying images..." />
	<copy todir="${DEPLOY_DIR}/${IMG_DIR}">
		<fileset dir="${IMG_DIR}">
			<include name="*.gif" />
			<include name="*.png" />
			<include name="*.jpg" />
		</fileset>
	</copy>
	<echo msg="Copying main files..." />
	<copy todir="${DEPLOY_DIR}">
		<fileset dir=".">
			<include name="index.html" />
			<include name=".htaccess" />
		</fileset>
		<filterchain>
			<replaceregexp>
				<regexp pattern="&lt;script.*\/script&gt;\r\n" replace="" />
				<regexp pattern="(&lt;\/head&gt;)"
					replace="&lt;script type=&quot;text/javascript&quot; src=&quot;lib/global.js&quot;&gt;&lt;/script&gt;\1" />
				<regexp pattern="\.css" replace="-min.css" />
			</replaceregexp>
		</filterchain>
	</copy>
</target></pre>
<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>PHP класс</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>
<pre class="brush: xml">&lt;taskdef name=&quot;stubjsmin&quot; classname=&quot;phing.tasks.my.stubJsMinTask&quot; /&gt;
&lt;taskdef name=&quot;stubcssmin&quot; classname=&quot;phing.tasks.my.stubCssMinTask&quot; /&gt;</pre>
<p>Правила следующие. Имя должно совпадать с именем класса, но без окончания task. Имя класса (<code>classname</code>) задает имя класса с учетом пути к нему (в качестве разделителя папок используется точка).</p>
<p>Теперь <strong>напишем задачу, которая будет сжимать js файлы</strong>. Сначала создадим набор файлов (<code>fileset</code>).</p>
<pre class="brush: xml">&lt;fileset id=&quot;srcjs&quot; dir=&quot;${LIB_DIR}&quot;&gt;
	&lt;include name=&quot;jquery/jquery.js&quot; /&gt;
	&lt;include name=&quot;tabs/jquery-ui-personalized-1.5.2.js&quot; /&gt;
	&lt;include name=&quot;tooltip/jquery.dimensions.js&quot; /&gt;
	&lt;include name=&quot;tooltip/jquery.tooltip.js&quot; /&gt;
	&lt;include name=&quot;mainscripts.js&quot; /&gt;
&lt;/fileset&gt;</pre>
<p>Теперь <strong>сжимаем файлы</strong>.</p>
<pre class="brush: xml">&lt;target name=&quot;minifyjs&quot;&gt;
	&lt;echo msg=&quot;Minifying JavaScript files...&quot; /&gt;
	&lt;stubjsmin jsminpath=&quot;${GLOBAL_LIB_DIR}/jsmin/jsmin-1.1.1.php&quot;
		targetdir=&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;&gt;
		&lt;fileset refid=&quot;srcjs&quot; /&gt;
	&lt;/stubjsmin&gt;
&lt;/target&gt;</pre>
<p>Здесь нужно отметить два момента.</p>
<p>Первый – использование операции <code>stubjsmin</code>. В её параметрах мы указываем размещение библиотеки JSmin и путь к папке, в которой будут размещены сжатые файлы. При записи сжатых файлов будет сохранена структура папок, в которых они размещены.</p>
<p>Второй – использование <code>fileset</code> внутри <code>stubjsmin</code>. Имя набора файлов указывается с помощью параметра <code>refid</code>.</p>
<p><strong>Сжатие CSS файлов</strong> выполняется точно также.</p>
<pre class="brush: xml">&lt;target name=&quot;minifycss&quot;&gt;
	&lt;echo msg=&quot;Minifying CSS files...&quot; /&gt;
	&lt;stubcssmin cssminpath=&quot;${GLOBAL_LIB_DIR}/cssmin/cssmin_v.1.0.php&quot;
		targetdir=&quot;${DEPLOY_DIR}/${CSS_DIR}&quot;&gt;
		&lt;fileset dir=&quot;${CSS_DIR}&quot; /&gt;
	&lt;/stubcssmin&gt;
&lt;/target&gt;</pre>
<p>Теперь <strong>объединяем JavaScript файлы в один и удаляем сжатые версии js файлов</strong>.</p>
<pre class="brush: xml">&lt;target name=&quot;combinejs&quot; depends=&quot;minifyjs&quot;&gt;
	&lt;echo msg=&quot;Creating single js file...&quot; /&gt;
	&lt;append destFile=&quot;${DEPLOY_DIR}/${LIB_DIR}/global.js&quot;&gt;
		&lt;filelist dir=&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;
			files=&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; /&gt;
	&lt;/append&gt;
	&lt;echo msg=&quot;Deleting minified js files...&quot; /&gt;
	&lt;delete includeemptydirs=&quot;true&quot;&gt;
		&lt;fileset dir=&quot;${DEPLOY_DIR}/${LIB_DIR}&quot;&gt;
			&lt;include name=&quot;**&quot; /&gt;
			&lt;exclude name=&quot;global.js&quot; /&gt;
		&lt;/fileset&gt;
	&lt;/delete&gt;
&lt;/target&gt;</pre>
<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>
<pre class="brush: xml">&lt;tar destfile=&quot;archive_name.gz&quot; basedir=&quot;.&quot; compression=&quot;gzip&quot; /&gt;</pre>
<p>Но почему-то браузеры не понимают созданные таким образом архивы.</p>
<p>В общем, разбираться было лень, и я решил задачу «в лоб». Использовал архиватор <a href="http://www.7-zip.org/">7-zip</a>. Для выполнения системных команд в Phing предусмотрена операция <code>exec</code>.</p>
<pre class="brush: xml"><target name="gzipjs" depends="combinejs">
	<exec command="& quot;c:\program files\7-zip\7z.exe& quot; a -tgzip global.js.gz global.js"
		dir="${DEPLOY_DIR}/${LIB_DIR}" />
</target></pre>
<p><strong>Обратите внимание</strong>. Если путь к файлу содержит пробелы, то его нужно взять в кавычки, которые задаются с помощью эскейп последовательности <code>&amp;quot;</code>. Параметр <code>dir</code> указывает рабочую папку программы.</p>
<p>И <strong>завершающий штрих</strong>. Задача <code>deploy</code>. Сама по себе она ничего не делает, но в её параметре depends перечислены задачи, которые должны быть выполнены при её вызове.</p>
<pre class="brush: xml">&lt;target name=&quot;deploy&quot; depends=&quot;copyfiles, gzipjs, minifycss&quot;&gt;
&lt;/target&gt;</pre>
<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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/ispolzovanie-phing-dlya-sborki-web-prilozhenij.html/feed</wfw:commentRss>
		<slash:comments>15</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[Phing]]></category>
		<category><![CDATA[PHP]]></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 – на PHP.</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>
<pre class="brush: xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project name="PhingTesting" default="packSrc" basedir="."&gt;
	&lt;target name="prepare"&gt;
		&lt;mkdir dir="archive"&gt;&lt;/mkdir&gt;
	&lt;/target&gt;
	&lt;target name="packSrc" depends="prepare"&gt;&lt;/target&gt;
&lt;/project&gt;</pre>
<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>
<pre class="brush: xml">&lt;target name="packSrc" depends="prepare"&gt;
	&lt;zip destfile="archive/my_project.zip" basedir="public_html"&gt;&lt;/zip&gt;
&lt;/target&gt;</pre>
<p>Для этого мы создадим еще одну задачу &#8211; <code>packSrc</code>. Кстати, обратите внимание на ее атрибут <code>depends</code>. В нем можно перечислить задачи, которые должны быть выполнены раньше текущей. В данном случае в этом атрибуте мы указали задачу <code>prepare</code>, т.е. теперь нам не нужно запускать ее вручную.</p>
<p>Для создания архива используется тег <code>zip</code>, в атрибутах которого нужно указать имя файла с архивом и файлы, которые нужно в него добавить.</p>
<p>На данный момент в архив будет добавляться весь проект целиком. Исправляем ситуацию.</p>
<pre class="brush: xml">&lt;zip destfile="archive/my_project.zip"&gt;
	&lt;fileset dir="public_html"&gt;
		&lt;include name="index.php"&gt;&lt;/include&gt;
		&lt;include name="css/**"&gt;&lt;/include&gt;
		&lt;include name="js/**"&gt;&lt;/include&gt;
		&lt;include name="system/application/**"&gt;&lt;/include&gt;
	&lt;/fileset&gt;
&lt;/zip&gt;</pre>
<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>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/izbavlyaemsya-ot-rutinnyx-operacij-s-pomoshhyu-phing.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

