<?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; PHP</title>
	<atom:link href="http://www.simplecoding.org/category/p/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>Yii фреймворк: создание XML-RPC сервера</title>
		<link>http://www.simplecoding.org/yii-frejmvork-sozdanie-xml-rpc-servera.html</link>
		<comments>http://www.simplecoding.org/yii-frejmvork-sozdanie-xml-rpc-servera.html#comments</comments>
		<pubDate>Sat, 24 Dec 2011 20:15:06 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[Yii]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1247</guid>
		<description><![CDATA[На мой взгляд, XML-RPC протокол является одним из наиболее удобных способов передачи данных между Интернет-ресурсами. Можно, конечно, поспорить, но на изучение XML-RPC требуется минимальное количество времени, есть множество готовых библиотек, да и используется он очень широко. Поэтому я никогда не понимал, почему разработчики отличного фреймворка Yii решили не включать библиотеку для работы с XML-RPC в [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1021" class="wp-caption alignnone" style="width: 272px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/03/yii_xml_rpc.png" alt="yii xml rpc" title="yii xml rpc" width="262" height="189" style="float:left" class="size-full wp-image-1021" /><p class="wp-caption-text"> </p></div>
<p>На мой взгляд, <strong>XML-RPC протокол</strong> является одним из наиболее удобных способов передачи данных между Интернет-ресурсами. Можно, конечно, поспорить, но на изучение XML-RPC требуется минимальное количество времени, есть множество готовых библиотек, да и используется он очень широко. Поэтому я никогда не понимал, почему разработчики отличного <a href="http://www.yiiframework.com">фреймворка Yii</a> решили не включать библиотеку для работы с XML-RPC в дистрибутив. Хотя, возможно, это вопрос времени <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Тем не менее, работать нужно уже сейчас, и в этой статье мы разберём, как решить проблему с помощью сторонних библиотек.</p>
<p><em>Примечание</em>. Если вас интересует создание XML-RPC клиента, почитайте статью <a href="http://www.simplecoding.org/xml-rpc-i-yii-frejmvork.html">XML-RPC и Yii фреймворк</a>.</p>
<h2>Немного теории.</h2>
<p>Мы можем использовать два основных подхода при создании <strong>XML-RPC сервера</strong>.</p>
<p><strong>1) Отдельный скрипт.</strong> В этом случае создаём файл с именем вроде xmlrpc.php и помещаем его в корень сайта. В нём будет находиться код обработки XML-RPC запросов. Такой подход используется, например, в WordPress. Достоинство в том, что вам не нужно вносить никаких изменений в код вашего проекта, т.е. XML-RPC интерфейс получается независимым. С другой стороны, независимость приводит к тому, что вам будет гораздо сложнее работать со встроенными библиотеками фреймворка.</p>
<p><strong>2) Использование действий контроллера.</strong> Этот вариант гораздо интереснее. Во-первых, вы автоматически получаете доступ ко всем возможностям Yii. Во-вторых, в этом случае XML-RPC методы можно разделить по модулям. Т.е. подключение / отключение модуля будет автоматически подключать / отключать соответствующие XML-RPC методы.<br />
<span id="more-1247"></span><br />
Т.к. реализация первого подхода никакой сложности не представляет (фактически вы можете использовать примеры из документации к вашей библиотеке для работы с XML-RPC), мы рассмотрим второй вариант.</p>
<h2>Какие библиотеки можно использовать?</h2>
<p>По большому счёту – любые, т.к. подключение сторонних библиотек к Yii выполняется без особых проблем. Я обычно использую библиотеку <a href="http://scripts.incutio.com/xmlrpc/manual.php">Incutio XML-RPC Library</a>. Она достаточно простая, работает без проблем и, кроме того, используется в WordPress, а эта CMS используется очень часто.</p>
<p>Переходим к практике.</p>
<h2>Шаг 1. Подключаем библиотеку.</h2>
<p>Для этого скачиваем библиотеку и сохраняем файл <code>IXR_Library.php</code> в папку <code>protected/vendors</code>. Теперь подключить библиотеку можно так:</p>
<pre class="brush: php">Yii::import('application.vendors.*');
require_once ('IXR_Library.php');</pre>
<p>Этот код можно добавить в любое действие (<code>action</code>) контроллера.</p>
<h2>Шаг 2. Создаём точку входа.</h2>
<p>Как я уже говорил, в качестве точки входа мы используем действие контроллера. Код будет выглядеть примерно так:</p>
<pre class="brush: php">class MyController extends Controller {
	...
	public function actionXmlrpc() {
		Yii::import('application.vendors.*');
		require_once ('IXR_Library.php');

		$server = new IXR_Server(array(
			'my.hello' =&gt; array($this,'hello'),
		));
	}
	...
}</pre>
<p>В этом методе мы просто создаём объект типа <code>IXR_Server</code>, конструктору которого нужно передать массив с названиями XML-RPC методов. В данном случае в массиве только один элемент. Ключ этого элемента является названием XML-RPC метода, а значение – именем функции, которую нужно вызвать.</p>
<p><code>array($this,'hello')</code> означает, что будет вызван метод <code>hello</code> данного контроллера.</p>
<p>Тут нужно помнить об одном нюансе. Обычно в XML-RPC запросах не передаются данные сессий. Логин и пароль отправляются в каждом запросе в качестве параметров. Поэтому необходимо, обеспечить доступ к методу <code>actionXmlrpc()</code> без авторизации. Для этого немного изменим метод <code>accessRules</code></p>
<pre class="brush: php">public function accessRules() {
	return array(
		array('allow',  // allow all users to perform 'index' and 'view' actions
			'actions'=&gt;array('index','view','xmlrpc'),
			'users'=&gt;array('*'),
		),
		…,
	);
}</pre>
<h2>Шаг 3. Добавляем методы.</h2>
<p>Теоретически, можно ограничиться просто добавлением метода <code>hello</code>, который просто вернет «Hello, world!».</p>
<pre class="brush: php">public function hello($args) {
	return 'Hello, world!';
}</pre>
<p>Но в 99% нужно аутентифицировать пользователя. Добавим метод</p>
<pre class="brush: php">protected function xmlrpcLogin($username, $password) {
	$identity = new UserIdentity($username, $password);
	$identity-&gt;authenticate();
	if ($identity-&gt;errorCode === UserIdentity::ERROR_NONE) {
		Yii::app()-&gt;user-&gt;login($identity, 0);
		return true;
	}
	else {
		return false;
	}
}</pre>
<p>Здесь мы используем класс <code>UserIdentity</code>, который автоматически создаётся фреймворком Yii при создании приложения. В параметрах этого метода нужно передать логин и пароль. В случае успешной аутентификации метод вернёт TRUE, в противном случае – FALSE. Кроме того, данные пользователя будут доступны через Yii::app()-&gt;user, т.е. точно также как и при обычной работе с фреймворком.</p>
<p>Теперь перепишем код метода hello.</p>
<pre class="brush: php">public function hello($args) {
	if (!$this-&gt;xmlrpcLogin($args[0], $args[1])) {
		return new IXR_Error(-1, 'You did not provide the correct password');
	}
return 'Hello, world!';
}</pre>
<p>Здесь предполагается, что логин и пароль будут переданы в первом и втором параметрах XML-RPC запроса.</p>
<h2>Шаг 4. Проверяем работу.</h2>
<p>Для проверки достаточно создать обычный PHP скрипт со следующим кодом.</p>
<pre class="brush: php">require_once ('IXR_Library.php');

$client = new IXR_Client('http://my_site.domen/my/xmlrpc');
$client-&gt;debug = true;

$args = array();
$args[0] = 'login';
$args[1] = 'password';

if (!$client-&gt;query('my.hello', $args)) {
    die('Something went wrong - '.$client-&gt;getErrorCode().' : '.$client-&gt;getErrorMessage());
}
echo $client-&gt;getResponse();</pre>
<p>Как видите, создание XML-RPC сервера особой сложности не представляет. Конечно, самая сложная работа – это написание самих методов. Но не забывайте, что если у вас уже готов web интерфейс и логика по максимуму вынесена в модели, то вы сможете спокойно использовать её и в XML-RPC методах.</p>
<p><strong>Успехов!</strong></p>
<p><em>Полезная информация</em></p>
<p>Новогодний подарок от Inferno Solutions &#8211; всем новым клиентам панель ISP бесплатно и 30$ в подарок при заказе <a href="https://cp.inferno.name/cart.php">VPS в Германии</a>, Украине или Голландии! Укажите при заказе в примечании ISP+30.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/yii-frejmvork-sozdanie-xml-rpc-servera.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress: публикация постов с помощью XML-RPC с поддержкой таксономий</title>
		<link>http://www.simplecoding.org/wordpress-publikaciya-postov-s-pomoshhyu-xml-rpc-s-podderzhkoj-taksonomij.html</link>
		<comments>http://www.simplecoding.org/wordpress-publikaciya-postov-s-pomoshhyu-xml-rpc-s-podderzhkoj-taksonomij.html#comments</comments>
		<pubDate>Tue, 11 Oct 2011 08:02:30 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1229</guid>
		<description><![CDATA[WordPress на сегодняшний день является одой из самых популярных CMS и последнее время активно развивается. Но, к сожалению, это развитие не всегда получается гармоничным. Одной из возможностей, которая почему-то по возможностям постоянно отстаёт от остальной части движка, является XML-RPC. На сегодняшний день этот протокол является основным средством удалённой публикации постов. И, при этом, он фактически [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1230" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/10/wordpress-xml-rpc-publish.png" alt="wordpress xml-rpc publish" title="wordpress xml-rpc publish" width="300" height="239" class="size-full wp-image-1230" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>WordPress</strong> на сегодняшний день является одой из самых популярных CMS и последнее время активно развивается. Но, к сожалению, это развитие не всегда получается гармоничным.</p>
<p>Одной из возможностей, которая почему-то по возможностям постоянно отстаёт от остальной части движка, является <strong>XML-RPC</strong>. На сегодняшний день этот протокол является основным средством удалённой публикации постов. И, при этом, он фактически бесполезен если вы используете произвольные типы записей (custom post types) и таксономии (custom taxonomies). Ни один XML-RPC метод публикации постов в WP 3.2.1 их не поддерживает.</p>
<p>Конечно, можно надеятся, что в будущих версиях ситуация изменится в лучшую сторону, но ничто не мешает добавить нужные методы прямо сейчас.</p>
<p>Рассмотрим небольшой пример.<br />
<span id="more-1229"></span><br />
Допустим, нам нужно <strong>публиковать посты произвольного типа через XML-RPC и связывать их с таксономиями</strong>. При этом, таксономии могут быть как иерархическими, так и плоскими.</p>
<p><em>Примечание</em>. Подробнее о типах постов и таксономиях рассказано в статьях: <a href="http://www.simplecoding.org/wordpress-vyvod-zapisej-proizvolnyx-tipov-custom-post-types.html">WordPress: вывод записей произвольных типов (Custom Post Types)</a> и <a href="http://www.simplecoding.org/upravlenie-kontentom-v-wordpress-cms-situaciya-na-segodnya-i-blizhajshaya-perspektiva.html">Управление контентом в WordPress CMS: ситуация на сегодня и ближайшая перспектива</a>.</p>
<h2>Немного теории</h2>
<p>В WordPress предусмотрен фильтр (<code>xmlrpc_methods</code>), позволяющий добавлять новые методы во встроенный XML-RPC сервер. Делается это следующим образом:</p>
<pre class="brush: php">add_filter('xmlrpc_methods', 'add_xml_rpc_methods');</pre>
<p>Во втором параметре фильтра указываем имя функции, которая создаст запись в глобальном массиве XML-RPC методов.</p>
<pre class="brush: php">function add_xml_rpc_methods($methods) {
	$methods['my.my_method_name'] = 'my_method_name';
	return $methods;
}

function my_method_name($args) {
//обработка XML-RPC запроса и отправка ответа
}</pre>
<p>Чтобы создать XML-RPC метод нужно добавить новый элемент в массив <code>$methods</code>. Ключ этого элемента является именем метода, а значение – именем функции, которая выполняет обработку XML-RPC запроса и формирует ответ.</p>
<h2>Реализация: XML-RPC клиент</h2>
<p>Начнём с кода, который отправляет XML-RPC запрос. В данном случае будем использовать библиотеку <a href="http://scripts.incutio.com/xmlrpc/">The Incutio XML-RPC Library</a> (она же используется и в WordPress).</p>
<pre class="brush: php">require_once ('IXR_Library.php');

$client = new IXR_Client('http://my_blog.com/xmlrpc.php');
$client-&gt;timeout = 60000;

$requestData[0] = 0; //id блога
$requestData[1] = 'admin'; //имя пользователя
$requestData[2] = 'pass'; //пароль

$post = array();

$post['post_title'] = 'New Post';
$post['post_excerpt'] = 'Short description';
$post['post_content'] = 'This story about ...';
$post['post_status'] = 'draft';
$post['post_type'] = 'my_custom_post_type'; //тип поста
$post['post_date'] = date('Y-m-d H:i:s');
$post['post_modified'] = date('Y-m-d H:i:s');

//формируем массив с терминами таксономий
$terms = array();
$terms['taxonomy_1'][] = (int)$term['term_id_1'];
$terms['taxonomy_1'][] = (int)$term['term_id_2'];
$terms['taxonomy_2'][] = (int)$term['term_id_3'];
$terms['taxonomy_3'][] = (int)$term['term_id_4'];

$post['tax_input'] = $terms;

$requestData[3] = $post;

if (!$client-&gt;query('my.publish_post', $requestData)) {
	echo 'Publish Post error: '.$client-&gt;getErrorMessage();
	return;
}

$publishedPost = $client-&gt;getResponse();</pre>
<p>Прежде всего, создаём объект <code>IXR_Client</code>, конструктору которого передаём адрес скрипт, который выполняет обработку XML-RPC запросов (xmlrpc.php).</p>
<p>Затем формируем массив с данными для публикации поста. В первых трёх элементах указываем: <code>id</code> блога (на данный момент не используется), логин и пароль. В четвертом элементе – массив с данными нового поста.</p>
<p>Чтобы сократить количество кода на стороне XML-RPC сервера, названия полей этого массива должны совпадать с полями массива, который передаётся функции <a href="http://codex.wordpress.org/Function_Reference/wp_insert_post">wp_insert_post</a>. Кстати, большинство ключей элементов этого массива совпадает с именами полей таблицы posts базы данных.</p>
<p>Обратите внимание на параметр</p>
<pre class="brush: php">$post['post_type'] = 'my_custom_post_type'; //тип поста</pre>
<p>В нём указан тип поста, который мы хотим создать. Естественно, этот тип должен быть <a href="http://codex.wordpress.org/Function_Reference/register_post_type">заранее создан</a>.</p>
<p><strong>Отдельно остановимся на таксономиях.</strong></p>
<p>WordPress поддерживает таксономии 2-х типов: иерархические и плоские. Чтобы связать пост с терминами таксономий нужно перечислить их в элементе tax_input массива, который передаётся функции <code>wp_insert_post</code>. Например, так:</p>
<pre class="brush: php">'tax_input' =&gt; array('taxonomy_1' =&gt; array('term', 'term2', 'term3'), 'taxonomy_2' =&gt; array('term1', 'term2'))</pre>
<p>Здесь <code>taxonomy_1</code>, <code>taxonomy_2</code> – имена таксономий, а <code>term</code>, <code>term1</code> и т.д. – имена терминов.</p>
<p>Но здесь есть нюансы. Если публикуется «плоская» таксономия, то можно указать, либо имя термина, либо его <code>id</code>. При этом, <code>id</code> должен иметь тип <code>int</code>, если <code>id</code> сохранён в виде строки, то WordPress просто создаст новый термин. Для иерархических таксономий можно использовать только <code>id</code> термина (при этом нет ограничения на тип значения, оно будет автоматически приведено к типу <code>int</code>).</p>
<p>Т.е. универсальный вариант установки таксономий выглядит так:</p>
<pre class="brush: php">$terms['taxonomy_1'][] = (int)$term['term_id_1'];
$terms['taxonomy_1'][] = (int)$term['term_id_2'];
$terms['taxonomy_2'][] = (int)$term['term_id_3'];
$terms['taxonomy_3'][] = (int)$term['term_id_4'];</pre>
<p>Отправка запроса выполняется с помощью метода query, а прочитать результат можно используя <code>getResponse</code>.</p>
<h2>XML-RPC сервер</h2>
<p>На серверной стороне нужно зарегистрировать новый XML-RPC метод и написать функцию, которая будет обрабатывать запрос, и возвращать результат.</p>
<p><em>Примечание</em>. Следующий код можно добавить в плагин или в файл functions.php темы.</p>
<pre class="brush: php">add_filter('xmlrpc_methods', 'add_xml_rpc_methods' );

function add_xml_rpc_methods($methods) {
	$methods['my.publish_post'] = 'my_publish_post';
	return $methods;
}

function my_publish_post($args) {
	$blog_id = (int) $args[0];
	$username = $args[1];
	$password = $args[2];
	$post_data  = $args[3];

	if ( !get_option( 'enable_xmlrpc' ) ) {
		return new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.  An admin user can enable them at %s'),  admin_url('options-writing.php') ) );
	}

	$user = wp_authenticate($username, $password);

	if (is_wp_error($user)) {
		return new IXR_Error(403, __('Bad login/pass combination.'));
	}

	wp_set_current_user( $user-&gt;ID );

	if ( !current_user_can( 'edit_private_posts' ) ) {
		return new IXR_Error( 401, __( 'Sorry, you cannot edit private posts.' ) );
	}

	if (!is_array($post_data)) {
		return new IXR_Error( 401, __( 'Sorry, no post data not found.' ) );
	}

	$id = wp_insert_post( $post_data );

	if ($id === 0) {
		return new IXR_Error( 401, __( 'Post save error.' ) );
	}

	$post = array();
	$post['id'] = $id;
	$post['permalink'] = get_permalink($id);

	return $post;
}</pre>
<p>Здесь мы регистрируем XML-RPC метод <code>my.publish_post</code> и указываем, что при обращении к нему WordPress должен вызвать функцию <code>my_publish_post</code>.</p>
<p>Большая часть кода в этой функции совпадает с большинством обработчиков стандартных XML-RPC методов WP. Собственно он оттуда и скопирован <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  . Этот код проверяет, разрешен ли XML-RPC для данного блога (строки 14-16, кстати, не забудьте его включить в админке на странице Settings -&gt; Writing), аутентифицирует пользователя и проверяет, достаточно ли у него прав для публикации поста.</p>
<p>Сама публикация выполняется с помощью всего одной функции <code>wp_insert_post</code> (строка 34).</p>
<p>Клиенту возвращаем <code>id</code> созданного поста и постоянную ссылку на него (формируем с помощью функции get_permalink).</p>
<h2>Заключение</h2>
<p>Как видите, принцип достаточно простой. Любую встроенную функцию WP можно вызвать через XML-RPC протокол и использовать все возможности движка при удалённой публикации постов.</p>
<p>Если есть вопросы или замечания, пишите, постараюсь ответить.</p>
<p><strong>Успехов!</strong></p>
<p>Интересные ссылки</p>
<p>Закажите <a href="http://printfotobook.ru">печать фотокниг</a> тремя способами: онлайн, в офисе или вип</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/wordpress-publikaciya-postov-s-pomoshhyu-xml-rpc-s-podderzhkoj-taksonomij.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>HTML5: загрузка файлов с помощью Drag &amp; Drop</title>
		<link>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html</link>
		<comments>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html#comments</comments>
		<pubDate>Thu, 21 Jul 2011 13:13:41 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1222</guid>
		<description><![CDATA[Приветствую всех! В этой статье хочу рассказать о нескольких своих экспериментах с HTML5. Начну издалека. Всем нам периодически приходится работать с различными web интерфейсами и часто возникает ощущение, что эта работа могла бы быть организована более эффективно. Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1223" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/07/html5_drag_drop_upload.png" alt="html5 drag&amp;drop upload" title="html5 drag&amp;drop upload" width="300" height="186" class="size-full wp-image-1223" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>В этой статье хочу рассказать о нескольких своих экспериментах с HTML5. Начну издалека. Всем нам периодически приходится работать с различными web интерфейсами и часто возникает ощущение, что эта работа могла бы быть организована более эффективно.</p>
<p>Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку файлов на сервер. В большинстве случаев вам предложат стандартное поле с кнопкой выбора файла с вашего компьютера и/или поле, в котором можно указать URL файла, размещенного где-нибудь в Сети.</p>
<p>Загрузку файлов с локального компьютера трогать пока не будем, я планирую опубликовать отдельный пост на эту тему, разберем загрузку с удалённого сервера.</p>
<p>Проблемы начинаются с первого же шага. Даже если вы четко понимаете, где искать URL и хорошо умеете пользоваться инструментами вроде <strong>firebug</strong>, то всё равно потребуется несколько кликов мышкой чтобы получить нужный адрес. Было бы гораздо удобнее просто перетянуть нужную картинку из одного окна браузера в другое.<br />
<span id="more-1222"></span><br />
Пример реализации такого интерфейса я покажу в этой статье. Если хотите, можете посмотреть, как он работает на демонстрационной страничке или скачать архив с исходниками.</p>
<p><a href="http://demosites.simplecoding.org/images-upload/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a><a href='http://www.simplecoding.org/wp-content/uploads/2011/07/images-upload.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p><strong>Обратите внимание!</strong> Данный пример работает только в браузере <strong>Google Chrome</strong>. По-идее, поддержка всех необходимых технологий есть в <strong>Firefox</strong> и <strong>Safari</strong>, но с ними я пока не разбирался.<br />
В качестве объектов для «перетягивания» я брал в основном картинки с википедии. Было замечено несколько проблем связанных с не латинскими символами в URL картинок, но чтобы не перегружать пример проверками и преобразованиями я их оставил как есть.</p>
<h2>Принцип работы</h2>
<p>Стандарт HTML5 предусматривает поддержку «перетягивания» объектов страницы (Drag and Drop). Кстати, пример простейшей реализации D&#038;D я уже показывал – <a href="http://www.simplecoding.org/drag-drop-s-ispolzovaniem-html5.html">Drag &#038; Drop с использованием HTML5</a>. И, кроме того, есть довольно много JavaScript библиотек, реализующих поддержку D&#038;D.</p>
<p>Но тут важно понимать, что если необходимо «перетягивать» картинки со сторонних ресурсов, то использовать библиотеки не получится. Т.к. вы не сможете добавить свой JS код на чужую страницу. А для того, чтобы загрузить картинку, нам нужно получить её URL, т.е. браузер должен вместе с перетягиваемым объектом передавать и его параметры (например, атрибут src картинки или весь тег img).</p>
<p>В этом случае мы можем создать на своей странице «приёмник» картинок. Это будет обычный <code>div</code> которому назначен обработчик события <code>drop</code>. Если пользователь «сбросит» картинку над этим div&#039;ом, то будет вызван обработчик и в первом параметре он получит объект, содержащий информацию о перетягиваемой картинке.</p>
<p>Дальше всё достаточно просто. Если мы получили нужный URL, то можно отправить AJAX-запрос серверному скрипту, который выполнит загрузку файла.</p>
<h2>Реализация</h2>
<p>Начнём со страницы нашего приложения.</p>
<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
        &lt;title&gt;Images Upload&lt;/title&gt;
		&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;
    &lt;/head&gt;
    &lt;body&gt;
		&lt;div id="images"&gt;&lt;/div&gt;
		&lt;div id="img_target"&gt;&lt;/div&gt;
		&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"&gt;&lt;/script&gt;
		&lt;script src="main.js"&gt;&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>На ней размещены два блока: <code>images</code> – здесь будем показывать загруженные изображения и <code>img_target</code> – на этот блок нужно перетягивать картинки.</p>
<p>Внизу страницы подключаем библиотеку jQuery и скрипт main.js, который будет отправлять информацию о перетянутых изображениях на сервер.</p>
<p><strong>Рассмотрим main.js</strong></p>
<pre class="brush: javascript">$(function() {
    $('#img_target')
        .bind('dragenter', function(event) {
            $(this).addClass('drop_here');
            return false;
        })
        .bind('dragleave', function(event) {
            $(this).removeClass('drop_here');
            return false;
        })
        .bind('dragover', function(event) {
            return false;
        })
        .bind('drop', function(event) {
            $(this).removeClass('drop_here');
			var srcRegex = /src=\"([^\s]+)\"/ig;
            var data = event.originalEvent.dataTransfer.getData('text/html');
			var img_data = srcRegex.exec(data);
			$.post('upload.php', {'file_url':img_data[1]}, function(res) {
				var response = eval('(' + res + ')');
				$('#images').append($('&lt;img src="' + response.file_url + '" /&gt;'));
			});
            return true;
        });
});</pre>
<p>Здесь мы назначаем обработчики событиям <code>dragenter</code>, <code>dragleave</code> и <code>dragover</code>. Все они должны просто возвращать false и, чтобы как-то проинформировать пользователя о том, что можно «сбрасывать» картинку, в обработчике <code>dragenter</code> устанавливаем CSS класс <code>drop_here</code> для блока-приёмника.</p>
<p>Основная часть работы выполняется в обработчике события <code>drop</code>. При возникновении этого события мы читаем информацию о «сброшенном» объекте и «вырезаем» значение атрибута <code>src</code>, т.е. URL картинки (строки 16-18). Информация передается в объекте event.originalEvent.dataTransfer (строка 17).</p>
<p>Затем <strong>формируем обычный AJAX запрос</strong> и в качестве параметра передаём ему найденный URL.</p>
<p>Серверный скрипт (upload.php) получит URL изображения на удалённом сервере и загрузит его. А в ответе на AJAX запрос он отправит новый URL загруженной картинки.</p>
<p>В свою очередь, обработчик AJAX-запроса создаст тег <code>img</code> и вставит его в блок <code>images</code>. Таким образом, загруженные картинки будут появляться над полем загрузки.</p>
<p><strong>Рассмотрим upload.php</strong></p>
<pre class="brush: php">&lt;?php

define('BASE_URL', 'http://localhost/tests/images-upload/');

function upload_from_url($file_url) {
	$url_segments = explode('/', $file_url);
	$file_name = urldecode(end($url_segments));
	if (false !== $file_name) {
		$file_name_parts = explode('.', $file_name);
		if (in_array(strtolower(end($file_name_parts)), array('jpeg','jpg','png','gif'))) {
			$destination=fopen("upload/".$file_name,"w");
			$source=fopen($file_url,"r");
			$maxsize=300*1024;
			$length=0;
			while (($a=fread($source,1024))&#038;&#038;($length&lt;$maxsize)) {
				$length=$length+1024;
				fwrite($destination,$a);
			}
			fclose($source);
			fclose($destination);
		}
	}
	$new_file_url = BASE_URL.'upload/'.$file_name;
	return $new_file_url;
}

$res = array('err' =&gt; 'Не указан URL файла');

if (isset($_POST['file_url'])) {
	$new_url = upload_from_url($_POST['file_url']);
	$res = array('file_url' =&gt; $new_url);
}

echo json_encode($res);</pre>
<p>Принцип работы следующий. Читаем URL картинки и пытаемся её загрузить (строки 29-32).</p>
<p>Если картинка загружена, сохраняем её в папку <code>upload</code>. Получение картинки с удалённого сервера осуществляется с помощью функций <code>fread</code>. Файл читаем блоками по 1кБ (строки 15-18). Такой подход позволяет прервать загрузку файла, если его размер превышает заданный предел (в данном случае 300кБ).</p>
<p>После загрузки файла формируем для него URL и отправляем браузеру в формате <strong>JSON</strong>.</p>
<p>Как видите, реализовать такой загрузчик несложно. И пользоваться им достаточно удобно. Естественно, основным недостатком является поддержка HTML5 браузерами, точнее её отсутствие <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Тем не менее, если вы создаёте интерфейс для сотрудников какой-нибудь компании, и можете оговорить тип браузера, то HTML5 вполне можно использовать.</p>
<p><strong>Успехов!</strong></p>
<p><em>Интересно почитать.</em></p>
<p>Фотокнига — фантастический <a href="http://imagebook.ru/sjurpriz_ljubimomu_muzhchine">сюрприз для любимого мужчины</a>. Попробуйте сами!</p>
<p>Правильно подготовим <a href="http://online-nalogi.ru/3_ndfl_pokupka_kvartiry">3-ндфл при покупке квартиры за 2011 год</a>, дадим инструкции для получения вычета</p>
<p>Нужно распарсить сайт? Интересный пример как написан <a href="http://www.sergunik.name/?p=140" title="php parser">парсер на php</a>. Можно даже скачать скрипт парсера.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Список докладов и финальная регистрация ZFConf 2011 — второй российской конференции по Zend Framework</title>
		<link>http://www.simplecoding.org/zfconf-2011.html</link>
		<comments>http://www.simplecoding.org/zfconf-2011.html#comments</comments>
		<pubDate>Fri, 06 May 2011 06:15:39 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Разное]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1208</guid>
		<description><![CDATA[Основные подготовительные работы по конференции закончены. Доклады сформированы. Среди спикеров представители KnpLabs, Magento, JetBrains, Sphinx и других известных компаний. Открыта финальная регистрация! Если Вы проходили предварительную регистрацию, то для прохождения финальной регистрации Вам нужно перейти по специальной ссылке, отправленной на e-mail. Введенную ранее информацию нужно будет только подтвердить. Если ссылка не приходила Вам, ее можно [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1209" class="wp-caption alignnone" style="width: 202px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/05/zfconf-2011.jpg" alt="zfconf 2011" title="zfconf 2011" width="192" height="139" style="float:left" class="size-full wp-image-1209" /><p class="wp-caption-text"> </p></div>
<p>Основные подготовительные работы по конференции закончены. Доклады сформированы. Среди спикеров представители KnpLabs, Magento, JetBrains, Sphinx и других известных компаний.</p>
<p>Открыта <a href="http://www.zfconf.ru/registration/" target="_blank"><strong>финальная регистрация</strong></a>!</p>
<p><strong>Если Вы проходили предварительную регистрацию</strong>, то для прохождения финальной регистрации Вам нужно перейти по специальной ссылке, отправленной на e-mail. Введенную ранее информацию нужно будет только подтвердить. Если ссылка не приходила Вам, ее можно запросить через <a href="http://www.zfconf.ru/get-registration-path/" target="_blank">специальную форму</a>.</p>
<p>Пожалуйста, обратите внимание на то, что <strong>изменилось <a href="http://www.zfconf.ru/2011/location/" target="_blank" >место проведения</a></strong>! Мероприятие будет проходить на прошлогодней площадке — в актовом зале ЛГТЦ (Ленгипротранс-Центр), по адресу: Московский пр., 143, ст. м. «Электросила». Кофе-брейки и обсуждения на флипчартах будут проходить в фойе.</p>
<p><strong>Cписок докладов:</strong><br />
<span id="more-1208"></span><br />
<strong><a href="http://www.zfconf.ru/2011/topics/flexible-architecture-using-dependency-injection/" target="_blank">Гибкая архитектура Zend Framework приложений с использованием Dependency Injection</a></strong> </p>
<p>Алексей Качаев (<a href="http://cogniance.com/" target="_blank" >Сogniance</a>, Senior PHP Developer)</p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/performance-increasing-with-phpdaemon-varnish-esi/" target="_blank">Воюем за ресурсы: Повышение производительности Zend Framework приложения с помощью phpDaemon, Varnish и ESI</a></strong> </p>
<p>Алексей Качаев (<a href="http://cogniance.com/" target="_blank" >Сogniance</a>, Senior PHP Developer)</p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/behavior-driven-development/" target="_blank">Behavior Driven Development в PHP и Zend Framework</a></strong> </p>
<p>Константин Кудряшов (<a href="http://www.knplabs.com/" target="_blank" >KnpLabs</a>, Senior Web Developer)</p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/multitasking-distributed-system-with-job-queue/" target="_blank">Разделение труда: Организация многозадачной, распределенной системы в Zend Framework с помощью Job Queue</a></strong> </p>
<p>Александр Готгельф (<a href="http://www.magentocommerce.com/" target="_blank" >Magento</a>, PHP-разработчик) </p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/how-can-help-development-environment/" target="_blank">Как может помочь среда разработки при написании приложения на Zend Framework?</a></strong> </p>
<p>Николай Матвеев (<a href="http://www.jetbrains.com/" target="_blank" >JetBrains</a>, разработчик) </p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/creating-rest-api-for-third-party-developers-and-mobile-devices-with-oauth/" target="_blank">Создание REST-API для сторонних разработчиков и мобильных устройств с авторизацией по протоколу OAuth 1.0</a></strong> </p>
<p>Дмитрий Чижевский (<a href="http://zenmoney.ru/" target="_blank" >Дзен-мани</a>, разработчик) </p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/fat-model-through-orm-development-history/" target="_blank">Толстая модель: История разработки собственного ORM</a></strong> </p>
<p>Михаил Шамин (<a href="http://geometria.ru/" target="_blank" >Геометрия</a>, ведущий разработчик) </p>
<p><strong><a href="http://www.zfconf.ru/2011/topics/what-is-sphinx-and-how-use-it-with-php/" target="_blank">Что такое Sphinx, зачем он вообще нужен и как его использовать с PHP (от простого индекса до поискового кластера)</a></strong> </p>
<p>Владимир Федорков (<a href="http://sphinxsearch.com/" target="_blank" >Sphinx</a>, Director of Professional Services)</p>
<p>Стоимость участия в мероприятии составит 1500 руб. В данную сумму входит: участие в самой конференции, кофе-брейки (от внешней кейтеринг-компании), пакет материалов участника и доступ к профессиональным видеозаписям докладов (после мероприятия). Доступно <a href="http://www.zfconf.ru/payment-types/" target="_blank" >множество способов оплаты</a>.</p>
<p>Торопитесь, <strong>количество мест ограничено</strong>!</p>
<p>Обязательно следите за последними новостями:<br />
<strong>RSS-канал:</strong> <a href="http://feeds.feedburner.com/zfconf" target="_blank">feeds.feedburner.com/zfconf</a><br />
<strong>Twitter:</strong> <a href="http://twitter.com/zfconf" target="_blank">@zfconf</a><br />
<strong>Группа ВКонтакте:</strong> <a href="http://vkontakte.ru/club14951507" target="_blank">vkontakte.ru/club14951507</a></p>
<p><strong>Организатор:</strong> <a href="http://www.wizartech.ru/" target="_blank">компания Wizartech</a><br />
<strong>Партнеры:</strong> <a href="http://zendframework.ru/" target="_blank">сообщество zendframework.ru</a> и <a href="http://zfconf.org.ua/" target="_blank">конференция ZFConf Ukraine</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/zfconf-2011.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress: вывод записей произвольных типов (Custom Post Types)</title>
		<link>http://www.simplecoding.org/wordpress-vyvod-zapisej-proizvolnyx-tipov-custom-post-types.html</link>
		<comments>http://www.simplecoding.org/wordpress-vyvod-zapisej-proizvolnyx-tipov-custom-post-types.html#comments</comments>
		<pubDate>Sun, 13 Mar 2011 14:56:48 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1192</guid>
		<description><![CDATA[На сегодняшний день движок WordPress довольно интенсивно развивается. Во всяком случае изменения в версиях с 2.8 по 3.1 добавляют WP возможности полноценных CMS. Большинство из этих возможностей должны быть активированы на уровне темы (или плагина), поэтому сразу после установки WP вы работаете с ним как с обычным блоговым движком. Вроде бы все правильно. Если какие-то [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1193" class="wp-caption alignnone" style="width: 295px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/03/wordpress_custom_queries.png" alt="wordpress custom queries" title="wordpress custom queries" width="285" height="221" class="size-full wp-image-1193" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>На сегодняшний день движок <strong>WordPress</strong> довольно интенсивно развивается. Во всяком случае изменения в версиях с 2.8 по 3.1 добавляют WP возможности полноценных CMS. Большинство из этих возможностей должны быть активированы на уровне темы (или плагина), поэтому сразу после установки WP вы работаете с ним как с обычным блоговым движком.</p>
<p>Вроде бы все правильно. Если какие-то возможности вам не нужны, вы их не используете. Но при этом возникает серьёзная проблема с документацией. Дело в том, большинство примеров и в Кодексе, и в других источниках, ориентированы на самый простой случай – дефолтную инсталляцию WP. Как только вы активируете дополнительные возможности ко многим рекомендациям нужно относится очень аккуратно.</p>
<p>Об одном из таких примеров я хочу рассказать в этой статье.<br />
<span id="more-1192"></span><br />
Предположим, вы решили использовать произвольные типы записей (custom post types). Создать их достаточно просто и на эту тему есть масса статей, поэтому подробно останавливаться на этом моменте не будем.</p>
<p>В большинстве случаев достаточно добавить следующий код в файл functions.php вашей темы.</p>
<pre class="brush: php">register_post_type('gadgets',
	array(
		'labels' =&gt; array(
			'name' =&gt; __('Gadgets'),
			'singular_name' =&gt; __('Gadget'),
			//остальные переводы
		),
		'public' =&gt; true,
		'publicly_queryable' =&gt; true,
		'query_var' =&gt; true,
		'taxonomies' =&gt; array('category','post_tag'),
		'supports' =&gt; array('title','editor','author','thumbnail','excerpt','comments'),
		'rewrite' =&gt; array('slug' =&gt; 'gadgets'),
		//другие настройки
	)
);</pre>
<p>После этого вы сможете создавать записи данного типа в админке и WordPress автоматически сформирует страницу с лентой из этих записей. Адрес у этой страницы будет следующим.</p>
<p><code>http://blog.url/gadgets</code></p>
<p>Теперь обратите внимание, что для этого типа записей мы используем такие же категории, как и для типа <code>Post</code> (строка 11).</p>
<p>Очевидно, что на странице категории мы захотим увидеть записи <strong>всех</strong> типов, но WordPress покажет только тип Post.</p>
<p>Происходит это потому что WP при формировании запроса к базе данных явно указывает тип поста. И по-умолчанию этот тип – <code>post</code>.</p>
<p>К сожалению, в подобных случаях не все авторы тем хотят вникать в нюансы работы движка и просто используют функцию <a href="http://codex.wordpress.org/Function_Reference/query_posts">query_posts</a>. Я понимаю, что примеры её использования приведены в статье <a href="http://codex.wordpress.org/The_Loop">The Loop</a>, но там предполагается, что вам нужно создать дополнительный цикл на странице. Т.е., например, вывести основной список записей и ещё какой-нибудь дополнительный список, с фильтрацией по определённым условиям.</p>
<p>В данном случае нужно изменить основной запрос, т.к. мы можем за один раз получить все необходимые данные. И нет никакого смысла выполнять дополнительный запрос к базе.</p>
<p><strong>Решается задача достаточно просто.</strong></p>
<pre class="brush: php">function prefix_pre_get_posts($query) {
     if ($query-&gt;is_category) {
          $query-&gt;set('post_type', 'any');
     }
     return $query;
}

add_action('pre_get_posts', 'prefix_pre_get_posts');</pre>
<p>Здесь мы назначаем собственный обработчик события (action) <code>pre_get_posts</code>. Как следует из названия, это событие возникает непосредственно перед отправкой запроса к БД. В первом параметре обработчик получает объект типа <a href="http://codex.wordpress.org/Function_Reference/WP_Query">WP_Query</a>, который формирует запрос к базе.</p>
<p>Прежде всего, мы проверяем, что в данный момент создаётся страница категории (строка 2). А затем изменяем атрибут <code>post_type</code>. По-умолчанию он равен <code>post</code>. Не забывайте, что обработчик обязательно должен вернуть изменённый (или неизменённый) объект <code>WP_Query</code>.</p>
<p>Вообще, если вы планируете работать с новыми возможностями WP (произвольными типами записей, таксономиями, форматами записей), то научиться работать с <a href="http://codex.wordpress.org/Function_Reference/WP_Query">WP_Query</a> нужно обязательно. <em>Встроенными функциями движка здесь вы не обойдетесь</em>.</p>
<p>В целом, этого и следовало ожидать, чем больше возможностей у движка, тем больше времени придётся потратить на его изучение <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Успехов!</strong></p>
<p><em>Интересно почитать</em></p>
<p>Если самостоятельно учиться тяжело, то <a href="http://it-centre.net">курсы программирования Киев</a> помогут приобрести необходимые знания.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/wordpress-vyvod-zapisej-proizvolnyx-tipov-custom-post-types.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Управление контентом в WordPress CMS: ситуация на сегодня и ближайшая перспектива</title>
		<link>http://www.simplecoding.org/upravlenie-kontentom-v-wordpress-cms-situaciya-na-segodnya-i-blizhajshaya-perspektiva.html</link>
		<comments>http://www.simplecoding.org/upravlenie-kontentom-v-wordpress-cms-situaciya-na-segodnya-i-blizhajshaya-perspektiva.html#comments</comments>
		<pubDate>Sat, 19 Feb 2011 09:16:38 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1176</guid>
		<description><![CDATA[Приветствую всех! В этот раз поговорим о нынешних и будущих возможностях одного из самых популярных блоговых движков – WordPress. И заодно обсудим, корректно ли вообще называть его «блоговым». Сразу хочу предупредить, что здесь не будет готовых рекомендаций о том «как правильно делать сайты», просто обсуждение основных возможностей движка, позволяющих работать с контентом, их достоинств и [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1177" class="wp-caption alignnone" style="width: 301px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/wp-cms.png" alt="wp cms" title="wp cms" width="291" height="231" class="size-full wp-image-1177" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong> В этот раз поговорим о нынешних и будущих возможностях одного из самых популярных блоговых движков – <strong>WordPress</strong>. И заодно обсудим, корректно ли вообще называть его «блоговым».</p>
<p>Сразу хочу предупредить, что здесь не будет готовых рекомендаций о том «как правильно делать сайты», просто обсуждение основных возможностей движка, позволяющих работать с контентом, их достоинств и недостатков.</p>
<p>И ещё одно замечание. Под «работой с контентом» я имею в виду не работу редактора, который форматирует текст с помощью <em>TinyMCE</em>, а работу web мастера, т.е. группировку записей по определённым признакам, их индивидуальное оформление, создание страниц архивов, навигацию и т.п.</p>
<p>Начнем с возможностей, которые предоставляет последний стабильный релиз WordPress (на данный момент это версия 3.0.5).<br />
<span id="more-1176"></span></p>
<h2>Таксономии (Custom Taxonomies)</h2>
<p>Если верить википедии, <em>таксономия – это учение о принципах и практике классификации и систематизации</em>. В системах управления контентом (CMS), таксономиями называют различные инструменты для группировки информации.</p>
<p>И обычно их используют для группировки записей по каким-нибудь признакам. Если проводить аналогию с русским языком, то таксономии в WP можно считать прилагательными (отвечают на вопрос «какой? какая?»), т.е. они так или иначе характеризуют запись.</p>
<p>По-умолчанию, WordPress предоставляет три таксономии – <em>категории</em>, <em>теги</em> и <em>ссылки</em>. Но, начиная с версии 2.3 появилась возможность создавать собственные таксономии, правда на все 100% она не используется до сих пор (об этом чуть ниже).</p>
<p>Создать новую таксономию можно с помощью функции <code>register_taxonomy</code>. Для её вызова обычно используется событие (action) <code>init</code>.</p>
<p>Например, если вы создаёте группу записей о каких-то товарах и хотите группировать их по цвету, то можно использовать следующий код.</p>
<pre class="brush: php">function color_init() {
	register_taxonomy(
		'color',
		'post',
		array(
			'label' =&gt; __('Color'),
			'labels'=&gt;array(
				'name'=&gt;__('Colors'),
				'singular_name'=&gt;__('Color'),
				...
			),
			'sort' =&gt; true,
			'args' =&gt; array('orderby' =&gt; 'term_order'),
			'public'=&gt;true,
			'show_in_nav_menus'=&gt;true,
			'show_ui'=&gt;true,
			'show_tagcloud'=&gt;true,
			'hierarchical'=&gt;true,
			'rewrite' =&gt; array('slug' =&gt; 'color'),
		)
	);
}
add_action( 'init', 'color_init' );</pre>
<p>Добавить этот код можно в файл <code>functions.php</code> темы или вызвать из плагина.</p>
<p>Как видите, большинство параметров у функции <code>register_taxonomy</code> – это различные настройки. Если хотите, можете почитать их <a href="http://codex.wordpress.org/Function_Reference/register_taxonomy">подробное описание</a>.</p>
<p>Как только вы зарегистрируете таксономию, справа на страницах создания и редактирования записей появится блок новой таксономии.</p>
<p>Если таксономия иерархическая, то выглядеть он будет так:</p>
<div id="attachment_1178" class="wp-caption alignnone" style="width: 303px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/taxonomy_hierarchical.png" alt="taxonomy hierarchical" title="taxonomy hierarchical" width="293" height="405" class="size-full wp-image-1178" /><p class="wp-caption-text"> </p></div>
<p>а если таксономия обычная, то так:</p>
<div id="attachment_1179" class="wp-caption alignnone" style="width: 305px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/taxonomy_simple.png" alt="taxonomy simple" title="taxonomy simple" width="295" height="156" class="size-full wp-image-1179" /><p class="wp-caption-text"> </p></div>
<p>Кроме того, в левом меню в группе <em>Post</em> появится ссылка на страницу редактирования таксономии.</p>
<div id="attachment_1180" class="wp-caption alignnone" style="width: 168px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/taxonomy_menu.png" alt="taxonomy menu" title="taxonomy menu" width="158" height="148" class="size-full wp-image-1180" /><p class="wp-caption-text"> </p></div>
<p>Как видите, возможности у ваших таксономий будут точно такие же как и у стандартных тегов и категорий.</p>
<p>Кроме того, таксономии автоматически поддерживаются на уровне темы. Т.е. если вы хотите чтобы оформление постов, которые относятся к одной из таксономий отличалось от других, вам будет достаточно создать шаблон для неё. Последовательность в которой WordPress ищет шаблоны таксономий показана на следующем рисунке.</p>
<div id="attachment_1181" class="wp-caption alignnone" style="width: 285px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/taxonomy_templates.png" alt="taxonomy templates" title="taxonomy templates" width="275" height="314" class="size-full wp-image-1181" /><p class="wp-caption-text"> </p></div>
<p><em>Примечание</em>. Вместо текста, выделенного красным, нужно подставить название соответствующей таксономии.</p>
<p>Поддержка такой иерархии шаблонов движком позволяет избавиться от длинных оператов <code>switch</code> в теме.</p>
<p>Также существует API для работы с таксономиями. Например, вы можете создать облако тегов с помощью функции <code>wp_tag_cloud</code>, вывести список терминов с помощью <code>the_terms</code> или использовать таксономии для фильтрации записей (функция <code>query_posts</code>).</p>
<p>Я не буду подробно на них останавливаться, т.к. эти же функции используются для работы со стандартными категориями и тегами.</p>
<p>Лучше рассмотрим <strong>ограничения</strong>, которые имеет система таксономий в WordPress.</p>
<p>Предположим, что вы создали таксономию, которая содержит <em>взаимоисключающие</em> значения. Например, название операционной системы для мобильных устройств. Если вы пишите пост о каком-нибудь телефоне, то будет неправильно если вы выберете одновременно термины Android и Simbian. Но WordPress никак не страхует вас от этой ошибки.</p>
<p>Т.е. в этом случае придется отказаться от использования стандартного интерфейса, создать свой <strong>meta-box</strong> (функция <code>add_meta_box</code>) и выводить в нём группу радиокнопок с терминами.</p>
<p>Ещё одна проблема связана с тем, что таксономии не всегда являются <em>очевидным</em> способом группировки контента.</p>
<p>Допустим, вы хотите чтобы оформление записей, содержащих видеоролики, отличалось от всех остальных. Можно просто создать категорию «Видео» и в инструкции пользователю написать, что все записи, содержащие видео, нужно включить в эту категорию.</p>
<p>Тут сразу же возникнет ряд проблем. Во-первых, люди могут ошибаться и не любят читать инструкции. Во-вторых, категорию можно легко удалить прямо из админки, что моментально приведет к изменению дизайна части записей.</p>
<p>Для решения последней проблемы разработчики добавили возможность создавать произвольные типы записей.</p>
<h2>Типы записей (Custom Post Types)</h2>
<p>Эта возможность появилась в версии 3.0. По большому счёту её можно тоже считать таксономией, но и с точки зрения пользователя, и с точки зрения разработчика реализация этой возможности отличается от таксономий, поэтому не будем их путать.</p>
<p>Создать новый тип записи не сложнее чем таксономию. Используется функция <a href="http://codex.wordpress.org/Function_Reference/register_post_type">register_post_type</a>.</p>
<pre class="brush: php">add_action('init', 'create_post_type');

function create_post_type() {
	register_post_type('video',
		array(
			'labels' =&gt; array(
				'name' =&gt; __('Videos'),
				'singular_name' =&gt; __('Videos'),
				...
			),
			'public' =&gt; true,
			'publicly_queryable' =&gt; true,
			'show_ui' =&gt; true,
			'query_var' =&gt; true,
			'capability_type' =&gt; 'post',
			'hierarchical' =&gt; false,
			'menu_position' =&gt; null,
			'taxonomies' =&gt; array('category','post_tag'),
			'supports' =&gt; array('title','editor','author','thumbnail','excerpt','comments'),
		)
	);
}</pre>
<p>Как видите, используется событие (<code>action</code>) <code>init</code>, а в параметрах задаются основные настройки нового типа записей. Например, перечень полей в форме создания записи (<code>supports</code>), список таксономий (<code>taxonomies</code>) и т.д.</p>
<p>После создания нового типа записей в левом меню админки появится новая группа ссылок для управления записями данного типа.</p>
<div id="attachment_1182" class="wp-caption alignnone" style="width: 170px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/custom_post_types.png" alt="custom post types" title="custom post types" width="160" height="124" class="size-full wp-image-1182" /><p class="wp-caption-text"> </p></div>
<p>Обратите внимание, вы можете «привязывать» любые таксономии к любым типам записей.</p>
<p>Точно также как и в случае с таксономиями, WordPress имеет поддержку типов записей как на уровне темы, так и на уровне API.</p>
<p>Порядок использования шаблонов темы выглядит следующим образом.</p>
<div id="attachment_1183" class="wp-caption alignnone" style="width: 220px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/custom_post_types_templates.png" alt="custom post types templates" title="custom post types templates" width="210" height="194" class="size-full wp-image-1183" /><p class="wp-caption-text"> </p></div>
<p>А примеры работы с типов записей и перечень соответствующих функций вы найдете на <a href="http://codex.wordpress.org/Post_Types">этой странице</a>.</p>
<p><strong>В каких случаях лучше использовать типы записей, а не таксономии?</strong></p>
<p>Если вернуться к аналогии с русским языком, то типы записей можно считать существительными. Т.е. это объекты, например, товары, видеоролики, работы в портфолио и т.п.</p>
<p>Как видите, вроде бы всё выглядит очень неплохо. Типы записей и таксономии позволяют довольно гибко управлять контентом и структурой сайта. И несложно догадаться, в основном они используются на сайтах, которые не являются блогами в классическом понимании.</p>
<p>Тем не менее, появление и широкое использование этих возможностей создало <strong>дополнительную проблему</strong>.</p>
<p>Давайте вспомним, почему WordPress пользуется такой популярностью?</p>
<p>Правильно, из-за большого количества практически бесплатных тем и плагинов.</p>
<p>Вы можете скачать новую тему и изменить дизайн блога с помощью пары кликов мышкой… по крайне мере теоретически. Но что новая тема знает о ваших таксономиях и типах постов? Разработчик темы, конечно, может получить их список, но что дальше? Откуда он знает <em>какую смысловую нагрузку они несут и как их нужно выводить</em>?</p>
<p>В результате получается, что если вы пользуетесь таксономиями и типами записей, то переход на новую тему потребует доработки этой темы. Исключение составляют темы от одного и того же разработчика, при условии, что он использовал в них одинаковые таксономии и типы записей.</p>
<p>В общем, в такой ситуации очень логичным выглядит следующий шаг разработчиков WordPress – <em>попытка стандартизации</em>.</p>
<p>Речь, конечно, о форматах записей (Post Formats).</p>
<h2>Форматы записей (Post Formats)</h2>
<p>Эта возможность появится в версии 3.1. На данный момент чтобы её потестировать вам нужно скачать development версию WordPress. Я использовал 3.1-RC4-17441.</p>
<p>Рассмотрим, что они из себя представляют.</p>
<p>Одно из их отличий от таксономий постов и типов записей заключается в том, что форматы не нужно создавать. Нужно просто включить их поддержку (используется функция <code>add_theme_support</code>).</p>
<pre class="brush: php">add_action('after_setup_theme', 'add_post_formats');
function add_post_formats() {
	add_theme_support( 'post-formats', array( 'aside', 'gallery', 'quote' ) );
}</pre>
<p>Во втором параметре этой функции необходимо перечислить форматы, которые вам нужны. При этом, можно использовать только строго определённые названия форматов. Их список вы найдете на <a href="http://codex.wordpress.org/Post_Formats">этой странице</a>.</p>
<p>В результате справа на страницах редактирования и создания записей вы увидите новый блок.</p>
<div id="attachment_1184" class="wp-caption alignnone" style="width: 301px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/02/post_formats.png" alt="post formats" title="post formats" width="291" height="124" class="size-full wp-image-1184" /><p class="wp-caption-text"> </p></div>
<p>Технически форматы постов в WordPress реализованы как таксономии специального вида, т.е. вы, как разработчик темы, можете обеспечить обратную совместимость вашей темы с предыдущими версиями движка.</p>
<p>Для этого нужно будет зарегистрировать таксономию с названием <code>post_format</code> и добавить в неё термины вида <code>post-format-название_формата</code> (например, <code>post-format-aside</code>). Для добавления термина используется функция <code>wp_insert_term</code>.</p>
<p>Естественно, в теме вы сможете определить формат текущей записи и соответствующим образом изменить её вид.</p>
<p>В общем, ничего принципиально сложного в использовании форматов постов нет. Основная проблема заключается в том, будут ли использовать новую возможность разработчики тем?</p>
<p>Ответить на него довольно сложно. Ясно, что разработка тем немного усложнится. К тому же наличие специальных таксономий, типов и форматов постов автоматически предполагает, что темы станут более специализированными, т.е. их взаимозаменяемость в любом случае будет ограничена.</p>
<p>С другой стороны, это логично. Если тема создавалась для корпоративного ресурса, то вряд ли она подойдет для портфолио. Исключить эту проблему можно было оставив WP чисто блоговым движком.</p>
<p>Но практика показала, что разработчики постоянно пытаются выйти за рамки движка. И все перечисленные в этой статье возможности были доступны и раньше, только за счёт использования специальных плагинов.</p>
<p>В заключение хочу сказать, что я не знаю точно насколько популярными окажутся форматы постов. Кстати, взгляды авторов англоязычных блогов по этому вопросу тоже не однозначные. Но, в любом случае, приятно видеть, что движок развивается!</p>
<p>Поэтому, хочу пожелать его авторам удачи! <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Интересно почитать</strong></p>
<p>Хотите научиться делать красивые сайты? <a href="http://it-centre.net/flash.php">Курсы flash</a> дадут знания для начала работы.</p>
<p>Подготовка <a href="http://online-nalogi.ru/3_ndfl_vychet_za_obuchenie"> 3 ндфл за обучение</a> для получения социального вычета в кратчайшие сроки</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/upravlenie-kontentom-v-wordpress-cms-situaciya-na-segodnya-i-blizhajshaya-perspektiva.html/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Индивидуальное оформление виджетов для WordPress</title>
		<link>http://www.simplecoding.org/individualnoe-oformlenie-vidzhetov-dlya-wordpress.html</link>
		<comments>http://www.simplecoding.org/individualnoe-oformlenie-vidzhetov-dlya-wordpress.html#comments</comments>
		<pubDate>Tue, 30 Nov 2010 15:36:22 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1159</guid>
		<description><![CDATA[Последнее время мне довольно часто приходится заниматься разработкой виджетов для WordPress и иногда возникают ситуации, когда стандартных возможностей движка не хватает. Сегодня я хочу показать прием, который позволяет назначить виджетам (которые находятся внутри одного сайдбара) индивидуальные CSS стили. Прежде всего, разберемся, о каких именно стилях идет речь. Вообще содержимое виджета и его разметка определяются разработчиком. [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1160" class="wp-caption alignnone" style="width: 280px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/11/wp_widget_styling.png" alt="wordpress widget styling" title="wordpress widget styling" width="270" height="236" class="size-full wp-image-1160" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Последнее время мне довольно часто приходится заниматься разработкой виджетов для <strong>WordPress</strong> и иногда возникают ситуации, когда стандартных возможностей движка не хватает.</p>
<p>Сегодня я хочу показать прием, который позволяет назначить виджетам (которые находятся внутри одного сайдбара) <strong>индивидуальные CSS стили</strong>.</p>
<p>Прежде всего, разберемся, о каких именно стилях идет речь.</p>
<p>Вообще содержимое виджета и его разметка определяются разработчиком. Но для того, чтобы виджеты красиво вписывались в дизайн темы предусмотрены 4 параметра, которые должны использовать разработчики виджетов (по крайней мере в теории <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>Эти параметры задаются разработчиком темы при создании сайдбара. Например, так:<br />
<span id="more-1159"></span></p>
<pre class="brush: php">register_sidebar(array(
	...,
	 'before_widget' =&gt; '&lt;li id="%1$s" class="widget %2$s"&gt;',
	 'after_widget'  =&gt; '&lt;/li&gt;',
	 'before_title'  =&gt; '&lt;h2 class="widgettitle"&gt;',
	 'after_title'   =&gt; '&lt;/h2&gt;'
));</pre>
<p>Разработчики виджетов обычно используют их внутри метода <code>widget</code>. Взгляните на фрагмент <a href="http://codex.wordpress.org/Widgets_API">примера из кодекса</a>.</p>
<pre class="brush: php">class My_Widget extends WP_Widget {
...
	function widget($args, $instance) {
		extract( $args );
		$title = apply_filters('widget_title', $instance['title']);
		?&gt;
		&lt;?php echo $before_widget; ?&gt;
			  &lt;?php if ( $title )
				echo $before_title . $title . $after_title; ?&gt;
			  Hello, World!
		  &lt;?php echo $after_widget; ?&gt;
		&lt;?php
	}
}</pre>
<p>Как видите, в параметре <code>before_widget</code> использованы две переменные: <code>%1$s</code> и <code>%2$s</code> (их значения подставляются с помощью функции <code>sprintf</code>). В результате для текстового виджета получим что-то вроде.</p>
<pre class="brush: html">&lt;li id="text-3" class="widget widget_text"&gt;</pre>
<p>Т.е. мы можем <strong>задать стили отдельно для каждого типа виджетов</strong>. Но представьте, что нам нужно вывести заголовки каждого <em>четного</em> виджета в сайдбаре темно-синим, а каждого <em>нечетного</em> – серым цветом. И при этом цвет не зависит от типа виджета, а определяется исключительно порядком размещения виджетов и если пользователь переставит виджеты местами, то и цвета должны измениться.</p>
<p>Использовать параметр <code>id</code> для этих целей вряд ли получится. Он создается при вставке виджета в сайдбар и не изменяется при перемещении виджета.</p>
<p><strong>Решение</strong> довольно простое.</p>
<p>Добавьте в файл <code>functions.php</code> следующий код.</p>
<pre class="brush: php">function custom_widget_counter($params) {
	global $widget_counter;

	if ($params[0]['id'] == 'my_sidebar') {
		$widget_counter++;
		If ($widget_counter % 2 == 0) {
			$params[0]['before_title'] = '&lt;h2 class="even"&gt;';
		}
		else {
			$params[0]['before_title'] = '&lt;h2 class="odd"&gt;';
		}
	}
	return $params;
}

add_filter('dynamic_sidebar_params','custom_widget_counter');</pre>
<p>«Фокус» заключается в использовании фильтра <code>dynamic_sidebar_params</code>, который позволяет изменять параметры, указанные при создании сайдбара (функция <code>register_sidebar</code>).</p>
<p>Установка атрибута <code>class</code> выполняется функцией <code>custom_widget_counter</code> (её имя мы указываем при добавлении фильтра). В первом параметре эта функция получает массив с текущими настройками.</p>
<p>Затем мы объявляем глобальную переменную <code>$widget_counter</code>, которая используется в качестве счетчика виджетов в сайдбаре.</p>
<p>Учитывая, что сайдбаров может быть несколько, проверяем id сайдбара и если он равен <code>my_sidebar</code>, устанавливаем параметр <code>before_title</code>. Для этого достаточно просто присвоить соответствующему элементу массива новое значение.</p>
<p>Если текущий виджет четный, устанавливаем <code>&lt;h2 class="even"&gt;</code>, в противном случае &#8211; <code>&lt;h2 class="odd"&gt;</code>.</p>
<p>И, самое главное, нужно обязательно вернуть (<code>return</code>) изменённый массив, иначе наши изменения применены не будут.</p>
<p>После этого остаётся только добавить соответствующие CSS правила в таблицу стилей.</p>
<p>И ещё раз хочу обратить ваше внимание. Этот метод будет работать для виджетов, которые разработаны в соответствии с рекомендациями кодекса (используются переменные before_widget, before_title и т.д. в разметке виджета). </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>Нужно <a href="http://nippondom.com/prodvizhenie_restorana_i_kafe">продвижение ресторана</a>? Попробуйте муляжи блюд от японских дизайнеров</p>
<p>Качественные и удобные <a href="http://www.onyx-inter.ru/shvejnyj-cex-proizvodstvo-oniks.html">промо сумки на заказ</a> от швейного цеха</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/individualnoe-oformlenie-vidzhetov-dlya-wordpress.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Обновление WordPress плагина Terms Descriptions</title>
		<link>http://www.simplecoding.org/obnovlenie-wordpress-plagina-terms-descriptions.html</link>
		<comments>http://www.simplecoding.org/obnovlenie-wordpress-plagina-terms-descriptions.html#comments</comments>
		<pubDate>Wed, 24 Nov 2010 17:27:44 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1156</guid>
		<description><![CDATA[Приветствую! Сегодня выложил очередное обновление WordPress плагина Terms Descriptions. Для тех, кто слышит о нём впервые, кратко объясню его назначение. Он позволяет создавать списки терминов, назначать им ссылки, автоматически искать термины и преобразовывать их в ссылки в ваших записях. Подробнее можно почитать здесь. Т.е. принцип довольно простой и поставленная задача решается в полном объеме. Но [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1063" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/05/wp_terms_descriptions_logo.png" alt="wp terms descriptions logo" title="wp terms descriptions logo" width="300" height="250" class="size-full wp-image-1063" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Приветствую!</p>
<p>Сегодня выложил очередное обновление WordPress плагина Terms Descriptions.</p>
<p>Для тех, кто слышит о нём впервые, кратко объясню его назначение. Он позволяет создавать списки терминов, назначать им ссылки, автоматически искать термины и преобразовывать их в ссылки в ваших записях. Подробнее можно почитать <a href="http://www.simplecoding.org/plagin-wordpress-terms-descriptions">здесь</a>.</p>
<p>Т.е. принцип довольно простой и поставленная задача решается в полном объеме. Но предусмотреть всё практически не возможно, и пользователи постоянно предлагают хорошие идеи.</p>
<p>Последнее усовершенствование предложил <strong>Андрей Х</strong>.</p>
<p><span id="more-1156"></span></p>
<p>Идея заключается в добавлении атрибута <code>class</code> ссылкам, которые создаёт плагин.</p>
<p>Что это даёт?</p>
<p>1) Возможность выделить ссылки с помощью CSS стилей.</p>
<p>2) Возможность обеспечить единый внешний вид ссылок, если для остальных ссылок уже установлен атрибут class.</p>
<p>Добавить атрибут несложно.</p>
<p><a href="http://wordpress.org/extend/plugins/terms-descriptions/">Обновите</a> плагин, в админке появится дополнительное поле.</p>
<div id="attachment_1157" class="wp-caption alignnone" style="width: 385px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/11/wp_terms_descriptions_class.png" alt="wordpress terms descriptions class" title="wordpress terms descriptions class" width="375" height="359" class="size-full wp-image-1157" /><p class="wp-caption-text"> </p></div>
<p>Значение атрибута нужно указать в поле &#034;Атрибут Class для ссылок&#034;.</p>
<p>После этого, ссылки будут выглядеть так.</p>
<pre class="brush: html">&lt;a href="http://site.domain" class="ext_link"&gt;Текст ссылки&lt;/a&gt;</pre>
<p>Не хотите пользоваться этой возможность, просто оставьте поле пустым.</p>
<p>Ещё одно изменение касается <strong>русской локализации</strong>. За это отдельное спасибо <strong>Андрей Х</strong>, который не поленился и исправил мои ошибки.</p>
<p>Кстати, если есть желание и возможность, вы можете перевести этот плагин на свой язык. Много времени это не займет. Плагин содержит менее 40 текстовых фраз. Для перевода удобнее всего использовать программу <a href="http://www.poedit.net/">Poedit</a>. Затем просто пришлите файл переводов мне.</p>
<p>Надеюсь, нововведения будут вам полезны.</p>
<p>Удачи!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/obnovlenie-wordpress-plagina-terms-descriptions.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Конференции ZFConf Ukraine &amp; MageConf</title>
		<link>http://www.simplecoding.org/konferencii-zfconf-ukraine-mageconf.html</link>
		<comments>http://www.simplecoding.org/konferencii-zfconf-ukraine-mageconf.html#comments</comments>
		<pubDate>Fri, 12 Nov 2010 17:29:14 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1153</guid>
		<description><![CDATA[Приветствую всех читателей! Сегодня хочу просто поделиться хорошей новостью. 27 ноября (суббота) в Киеве пройдет совместная конференция ZFConf Ukraine &#038; MageConf. Подобные мероприятия &#8211; это в любом случае хорошо, но данная конференция выгодно отличается от большинства. Участие в ней бесплатное. Тут нужно отдать должное организаторам. Я не знаю как они уговаривали спонсоров и искали докладчиков, [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://habreffect.ru/files/a10/cbbfacb76/zfconfua_and_mageconf.jpg" title="ZFConf Ukraine &#038; MageConf" class="alignnone" width="236" height="137" style="float:left" /></p>
<p>Приветствую всех читателей!</p>
<p>Сегодня хочу просто поделиться хорошей новостью.</p>
<p>27 ноября (суббота) в Киеве пройдет совместная конференция <a href="http://zfconf.org.ua/">ZFConf Ukraine &#038; MageConf</a>.</p>
<p>Подобные мероприятия &#8211; это в любом случае хорошо, но данная конференция выгодно отличается от большинства. <strong>Участие в ней бесплатное</strong>.</p>
<p>Тут нужно отдать должное организаторам. Я не знаю как они уговаривали спонсоров и искали докладчиков, но, думаю, это было непросто <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Конференция будет длиться один день и пройдет в три потока: Zend Framework, PHP, Magento.</p>
<p>Доклады будут на следующие темы.<br />
<span id="more-1153"></span><br />
<strong>1. Встречайте Zend Framework 2.0</strong><br />
Александр Веремьев / Zend Framework Core команда (Zend Technologies)</p>
<p><strong>2. Эволюция ZF: архитектура, шаблоны, рефакторинг</strong><br />
Виктор Фараздаги / Component Maintainer и Contributor ZF 2.0 (4C)</p>
<p><strong>3. Юнит тестирование в Zend Framework 2.0</strong><br />
Ростислав Михайлив / Chief Developer / Software Architect (Gadu-Gadu)</p>
<p><strong>4. Хранение, обработка и отдача статики с использованием \Zend \File. Опыт социальной сети starlook.ru</strong><br />
Кирилл Мокевнин / Senior developer (undev)</p>
<p><strong>5. Чуть сложнее чем Singleton: аннотации, IOC, АОП</strong><br />
Кирилл Чебунин / Senior PHP Developer (Альпари)</p>
<p><strong>6. Doctrine 2</strong><br />
Валерий Рабиевский / Team leader (stfalcon.com)</p>
<p>Насколько я понял, список докладов не окончательный, и будет дополняться.</p>
<p>Для участия в конференции достаточно <a href="http://zfconf.org.ua/registration/">зарегистрироваться</a>.</p>
<p>В общем, событие обещает быть интересным.</p>
<p>До встречи!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/konferencii-zfconf-ukraine-mageconf.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>WordPress плагин Terms Descriptions. Новая версия.</title>
		<link>http://www.simplecoding.org/wordpress-plagin-terms-descriptions-novaya-versiya.html</link>
		<comments>http://www.simplecoding.org/wordpress-plagin-terms-descriptions-novaya-versiya.html#comments</comments>
		<pubDate>Mon, 08 Nov 2010 07:05:26 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1149</guid>
		<description><![CDATA[Приветствую всех! Я всё-таки собрался и доделал плагин Terms Descriptions Изменений в новой версии не много, но об одном из них меня просили уже несколько раз. Речь о поддержке словоформ, т.е. нескольких вариантов написания одного и того же термина. Например, так яблоко&#124;яблоки&#124;яблок и т.д. Разделять словоформы нужно с помощью символа &#124;. При этом, каждый из [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1063" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/05/wp_terms_descriptions_logo.png" alt="wp terms descriptions logo" title="wp terms descriptions logo" style="float:left" width="300" height="250" class="size-full wp-image-1063" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>Я всё-таки собрался и доделал плагин <a href="http://www.simplecoding.org/plagin-wordpress-terms-descriptions">Terms Descriptions</a> <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Изменений в новой версии не много, но об одном из них меня просили уже несколько раз.</p>
<p>Речь о поддержке словоформ, т.е. нескольких вариантов написания одного и того же термина.</p>
<p>Например, так <code>яблоко|яблоки|яблок</code> и т.д.</p>
<p>Разделять словоформы нужно с помощью символа <code>|</code>. При этом, каждый из вариантов написания может состоять из одного или нескольких слов. Например, <code>жесткий диск|винчестер|HDD</code>.<br />
<span id="more-1149"></span><br />
В общем, эта возможность должна понравиться SEO&#039;шникам <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Хотя я не советую черезмерно увлекаться перелинковкой. Страница с большим количеством ссылок выглядит не естественно. Особенно, если ссылки одни и те же.</p>
<p>Поэтому не лишним будет использовать настройку &#034;Преобразовывать первые &#8230; терминов&#034;.</p>
<p>Обратите внимание, что все словоформы считаются одним термином. Т.е. <code>жесткий диск|винчестер|HDD</code> &#8211; один термин. И если в настройках указать &#034;Преобразовывать первые 2 термина&#034;, то плагин поставит только две ссылки (на те словоформы, которые встретятся первыми в тексте поста).</p>
<p><strong>Важно!</strong></p>
<p>Большие списки терминов (100+) могут отрицательно сказаться на скорости формирования страницы. В таких случаях решить проблему можно с помощью кеширования, благо для WordPress недостатка в соответствующих плагинах нет.</p>
<p><img src="http://www.simplecoding.org/wp-content/uploads/2010/11/screenshot-2.png" alt="" title="screenshot-2" width="472" height="658" class="alignnone size-full wp-image-1150" /></p>
<p>Ещё одна новость касается <strong>размещения плагина</strong>.</p>
<p>Я перенёс его на официальный сайт <a href="http://wordpress.org/extend/plugins/terms-descriptions/">WordPress</a>. Так что теперь будут работать автоматические обновления.</p>
<p>В связи с этим, огромная просьба сообщить мне обо всех замеченных недостатках. Как в описании, так и работе плагина. Предложения новых возможностей или усовершенствования существующих также приветствуются.</p>
<p>Кстати, на <a href="http://wordpress.org/extend/plugins/terms-descriptions/">странице плагина</a> есть виджет <strong>Compatibility</strong>. С его помощью можно указать с какими версиями плагин работает, а с какими &#8211; нет. Мне будет приятно, если вы поучаствуете в наполнении этой статистики.</p>
<p><strong>Удачного обновления!</strong></p>
<p><strong>Интересно почитать</strong></p>
<p>Шьем <a href="http://onyx-inter.ru/sumki_iz_pvh_hlopka_brezenta">сумки из хлопка и ПВХ</a>, цены &#8211; фантастика</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/wordpress-plagin-terms-descriptions-novaya-versiya.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

