<?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>Erinome Lane &#187; php</title>
	<atom:link href="https://tt.erinome.net/tag/php/feed" rel="self" type="application/rss+xml" />
	<link>https://tt.erinome.net</link>
	<description>a bit of this, a bit of that...</description>
	<lastBuildDate>Mon, 23 Mar 2026 12:51:51 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Резервное копирование в WebDav на OpenWrt</title>
		<link>https://tt.erinome.net/2014/12/742</link>
		<comments>https://tt.erinome.net/2014/12/742#comments</comments>
		<pubDate>Mon, 22 Dec 2014 13:18:13 +0000</pubDate>
		<dc:creator><![CDATA[root]]></dc:creator>
				<category><![CDATA[Сеть и интернет]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[openwrt]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://tt.erinome.net/?p=742</guid>
		<description><![CDATA[Рассмотрим возможность создания резервного копирования в облачное хранилище WebDav на примере Яндекс.Диска при помощи виртуальной файловой системы davfs2, утилиты cadaver и небольшого PHP-скрипта. Может возникнуть закономерный вопрос: зачем изобретать велосипед и почему бы не использовать обычный rsync для копирования данных &#8230; <a href="https://tt.erinome.net/2014/12/742">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Рассмотрим возможность создания резервного копирования в облачное хранилище <strong>WebDav</strong> на примере Яндекс.Диска при помощи виртуальной файловой системы <strong>davfs2</strong>, утилиты <strong>cadaver</strong> и небольшого <strong>PHP</strong>-скрипта.<span id="more-742"></span></p>
<p>Может возникнуть закономерный вопрос: зачем изобретать велосипед и почему бы не использовать обычный <strong>rsync</strong> для копирования данных напрямую в <strong>davfs2</strong>? Ответ простой: это&#8230; не работает как надо. Во всяком случае, с Яндекс.Диском, и если запускать процедуру на роутере под управлением <strong>OpenWrt</strong>.</p>
<p>То ли из-за особой неторопливости Яндекс.Диска, то ли из-за особенностей <strong>davfs2</strong>, но при попытке копирования большого количества файлов (а иногда такое случается и с единичными файлами!), большая их часть оказывалась в каталоге <em>lost+found</em>, служащем для локальных копий файлов, загрузка которых в <strong>WebDav</strong> провалилась. И всё это несмотря на достаточный объем выделенного кэша, стандартные настройки <strong>davfs2</strong> для повторной загрузки файлов в случае ее неудачи, и довольно широкого канала связи.</p>
<p>Итак, для самописного и более надежного бэкапера в WebDav нам понадобятся:</p>
<ol>
<li><strong>davfs2</strong> &#8211; стандартный пакет из репозитория OpenWrt;</li>
<li><strong>cadaver</strong> &#8211; модифицированная версия утилиты для прямого копирования файлов в WebDav <a href="http://fs.erinome.net/openwrt/packages/cadaver" target="_blank">из нашего архива</a>;</li>
<li><strong>php-cli</strong> &#8211; стандартный интерпретатор PHP, при помощи которого мы сгенерируем набор команд для cadaver&#8217;а.</li>
</ol>
<p>Добавленные в <strong>cadaver </strong>патчи позволяют при помощи нового ключа <strong>-F</strong> пропускать проверку подлинности сертификатов (а под <strong>OpenWrt </strong>у нас все используемые в WebDav SSL-сертификаты считаются подозрительными и требуют ручного подтверждения), а также указывать с помощью ключа <strong>-n</strong> нестандартный путь к хранилищу паролей для автоматической авторизации на WebDav-сервере. Внесенные изменения позволяют создать для <strong>cadaver</strong> файл с набором команд, которые будут выполняться автоматически без участия человека.</p>
<p>Теперь обратим внимание на скрипт <a href="http://fs.erinome.net/openwrt/scripts/phpsync.php" target="_blank">phpsync.php</a>.</p>
<p>У этого скрипта две задачи:<br />
Во-первых, он отвечает за &#8220;обратную синхронизацию&#8221; &#8211; в скрипте производится проверка, все ли находящиеся в WebDav-хранилище файлы продолжают находиться на локальном диске. В случае обнаружения в удаленном хранилище файлов, которые были локально удалены, скрипт удалит их и из WebDav &#8211; обычным вызовом <em>unlink()</em> на смонтированном разделе davfs2.<br />
Во-вторых, скрипт генерирует набор команд для <strong>cadaver</strong>&#8216;а для загрузки локально измененных или отсутствующих в WebDav файлов в удаленное хранилище.<br />
В скрипте есть ряд параметров, которые нужно настроить. Так, параметром <em>$outfile</em> определяется путь к файлу, в который будет записан сгенерированный набор команд, в параметре <em>$remotebase</em> необходимо указать точку монтирования <strong>davfs2</strong>. Также в нем указывается адрес WebDav сервера, к которому должен подключаться <strong>cadaver</strong> &#8211; по умолчанию это <em>https://webdav.yandex.ru</em>. Затем следует указать каталоги, которые требуется синхронизировать, например:</p>
<pre class="console">phpsync("/srv/content","/backup/content");
phpsync("/srv/otherdir","/backup/otherdir");</pre>
<p>Так будут сгенерирован набор команд для отражения локальных каталогов <em>/srv/content</em> и <em>/srv/otherdir</em> в удаленные WebDav-каталоги <em>/backup/content</em> и <em>/backup/otherdir</em> соответственно. Обратите внимание &#8211; удаленные пути указываются относительно корня <strong>WebDav</strong>-диска, без привязки к локальной точке монтирования <strong>davfs2</strong>!</p>
<p>После этого следует создать парольный файл для <strong>cadaver</strong>. Это обычный текстовый документ, содержающий строку следующего вида:</p>
<pre class="console">machine webdav.yandex.ru login вашлогин password вашпароль</pre>
<p>Наконец, создаем <strong>ash</strong>-скрипт, который мы будем вызывать через кронтаб:</p>
<pre class="console">#!/bin/ash
/usr/bin/php-cgi -f /srv/phpsync.php

if [ -e "/var/.phpsync.list" -a $(wc -l "/var/.phpsync.list" | awk '{print $1;}') -gt 2 ]
then
        /usr/bin/cadaver -F -r "/var/.phpsync.list" -n "/srv/auth.rc"
fi
</pre>
<p>Подставляем ваши значения:</p>
<ul>
<li><strong>/srv/phpsync.php</strong> &#8212; путь к PHP-скрипту;</li>
<li><strong>/srv/auth.rc</strong> &#8212; путь к парольному файлу;</li>
<li><strong>/var/.phpsync.list</strong> &#8212; путь к файлу с набором команд для cadaver.</li>
</ul>
<p>Не забываем сделать скрипт исполняемым, выполнив команду <strong>chmod +x</strong> на данном файле. Теперь мы можем проверить работоспособность копирования, запустив этот скрипт. В терминал при этом будет выведен результат работы PHP-генератора, а также будет показан процесс выполнения задания cadaver&#8217;ом.</p>
<p>Если все завершилось успешно &#8211; теперь можем добавить автоматический вызов данного скрипта через кронтаб в ночное время и более не беспокоиться о создании резервных копий.</p>
]]></content:encoded>
			<wfw:commentRss>https://tt.erinome.net/2014/12/742/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>WordPress и длинные &#8220;ярлыки&#8221;</title>
		<link>https://tt.erinome.net/2014/02/650</link>
		<comments>https://tt.erinome.net/2014/02/650#comments</comments>
		<pubDate>Tue, 25 Feb 2014 11:31:11 +0000</pubDate>
		<dc:creator><![CDATA[root]]></dc:creator>
				<category><![CDATA[Сеть и интернет]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[грабли]]></category>

		<guid isPermaLink="false">http://tt.erinome.net/?p=650</guid>
		<description><![CDATA[При эксплуатации WordPress на одном из сайтов был обнаружен неприятный дефект &#8211; некоторые автоматически сгенерированные ярлыки (&#8220;slug&#8221;) для категорий имели покоцанные последние символы, вследствие чего перейти по ссылкам на такие категории не представлялось возможным. Однако при ручном их указании все &#8230; <a href="https://tt.erinome.net/2014/02/650">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>При эксплуатации WordPress на одном из сайтов был обнаружен неприятный дефект &#8211; некоторые автоматически сгенерированные ярлыки (&#8220;slug&#8221;) для категорий имели покоцанные последние символы, вследствие чего перейти по ссылкам на такие категории не представлялось возможным. Однако при ручном их указании все сохранялось корректно.<span id="more-650"></span></p>
<p>Данная проблема явно не относится к тем, с которыми можно часто столкнуться: она возникает при наличии, к примеру, многоуровневой иерархии категорий с повторяющимися названиями узлов. Предположим следующую гипотетическую структуру категорий:</p>
<ul>
<li>Энергетические решения для дома
<ul>
<li>Дизельные установки</li>
<li>Ветряные генераторы</li>
<li>Микроядерные установки</li>
</ul>
</li>
<li>Энергетические решения для офиса
<ul>
<li>Дизельные установки</li>
<li>Микроядерные установки</li>
<li>Термоядерные блоки</li>
</ul>
</li>
</ul>
<p>Причина проблемы состоит в том, что WordPress не допускает существование одинаковых ярлыков, даже если они находятся в разных ветвях иерархии. Поэтому, если при создании данной структуры не заполнять вручную ярлыки (&#8220;slugs&#8221;), автоматически получим такую структуру ярлыков:</p>
<ul>
<li>/категории/энергетические-решения-для-дома
<ul>
<li><strong>/категории/энергетические-решения-для-дома/дизельные-установки</strong></li>
<li>/категории/энергетические-решения-для-дома/ветряные-генераторы</li>
<li><strong>/категории/энергетические-решения-для-дома/микроядерные-установки</strong></li>
</ul>
</li>
<li>/категории/энергетические-решения-для-офиса
<ul>
<li><strong>/категории/энергетические-решения-для-офиса/дизельные-установки<span style="color: red;">-энергетические-решения-для-оф%0с</span></strong></li>
<li><strong>/категории/энергетические-решения-для-офиса/микроядерные-установки<span style="color: red;">-энергетические-решения-дл%3bf~</span></strong></li>
<li>/категории/энергетические-решения-для-офиса/термоядерные-блоки</li>
</ul>
</li>
</ul>
<p>Стандартный алгоритм пытается автозаполнить ярлыки категорий, исходя из их названий. Когда названия повторяются &#8211; WordPress пытается приписать к ярлыку название его родительской категории, создав тем самым более уникальное имя.</p>
<p>Почему сгенерированные названия получаются нерабочими? &#8211; Дело в том, что в базе данных на длину поля ярлыка выделено 200 символов. В принципе, это довольно большое число, которого должно было хватить с запасом в том числе и на имя родительской категории. Однако, как выяснилось, это верно лишь при использовании латинских символов. В базе данных ярлык хранится уже в URL-encoded форме, что при учете использования UTF-8 приводит к тому, что одна русская буква заменяется на последовательность из <strong>6 символов</strong>. В результате, фактически в этом поле умещается название, в котором не более 33 русских букв. И, как выяснилось, никакой проверки этого факта в WordPress не предусмотрено: при записи слишком длинного ярлыка в базу просто пишется та его часть, которая уложилась в 200 символов. А при учете, что на одну русскую букву в кодированной форме приходится 6 символов, получаем, что одна из букв оказывается разорвана пополам. Как итог &#8211; битая нерабочая ссылка.</p>
<p>Для исправления этой ситуации можно пропатчить файл wp-includes/taxonomy.php:</p>
<pre class="console">--- a/taxonomy.php	2014-02-24 13:14:30.649795666 +0400
+++ b/taxonomy.php	2014-02-25 11:23:51.443231774 +0400
@@ -2436,6 +2436,15 @@
  * @param object $term The term object that the $slug will belong too
  * @return string Will return a true unique slug.
  */
+function truncate_slug_to_200_chars($slug, $limit = 200) {
+	while (strlen($slug) >= $limit)
+	{
+		$slug = rawurldecode($slug);
+		$slug = mb_substr($slug,0,-1);
+		$slug = rawurlencode($slug);
+	}
+	return $slug;
+}
 function wp_unique_term_slug($slug, $term) {
 	global $wpdb;
 
@@ -2451,6 +2460,10 @@
 			if ( is_wp_error($parent_term) || empty($parent_term) )
 				break;
 			$slug .= '-' . $parent_term->slug;
+			// [kreon] slugs are url-encoded and limited to 200 chars
+			// if this limit is exceeded then non-ascii urlencoded data will probably break
+			if ( strlen( $slug ) >= 200 )
+				$slug = truncate_slug_to_200_chars( $slug );
 			if ( ! term_exists( $slug ) )
 				return $slug;
 
@@ -2468,6 +2481,10 @@
 
 	if ( $wpdb->get_var( $query ) ) {
 		$num = 2;
+		// [kreon] same thing here. if result exceeds 200 chars, then things may break
+		// make sure we have free space for 3 additional chars to hold '-num' parameter
+		if ( strlen( $slug ) >= 197 )
+			$slug = truncate_slug_to_200_chars ( $slug, 197 );
 		do {
 			$alt_slug = $slug . "-$num";
 			$num++;</pre>
<p>Этот патч не позволяет автозаполнению сгенерировать слишком длинный ярлык, сокращая побуквенно длину декодированного ярлыка до тех пор, пока его кодированное представление не станет менее 200 символов.</p>
<p>Патч не исправит уже имеющиеся поломанные ярлыки &#8211; их необходимо пересохранить повторно вручную.</p>
]]></content:encoded>
			<wfw:commentRss>https://tt.erinome.net/2014/02/650/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[PHP] windows + line count</title>
		<link>https://tt.erinome.net/2013/08/602</link>
		<comments>https://tt.erinome.net/2013/08/602#comments</comments>
		<pubDate>Fri, 16 Aug 2013 08:29:51 +0000</pubDate>
		<dc:creator><![CDATA[root]]></dc:creator>
				<category><![CDATA[Сеть и интернет]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[грабли]]></category>

		<guid isPermaLink="false">http://tt.erinome.net/?p=602</guid>
		<description><![CDATA[Иногда может потребоваться узнать количество строк в файле. В Linux-системах для этих целей можно использовать утилиту wc, просто вызвав ее через exec: $linecnt = exec("wc -l filename.txt"); А что делать, если PHP работает на компьютере под управлением Windows? В Windows-системах &#8230; <a href="https://tt.erinome.net/2013/08/602">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Иногда может потребоваться узнать количество строк в файле. В Linux-системах для этих целей можно использовать утилиту <strong>wc</strong>, просто вызвав ее через <strong>exec</strong>:</p>
<pre class="console">$linecnt = exec("wc -l filename.txt");</pre>
<p>А что делать, если PHP работает на компьютере под управлением Windows?<span id="more-602"></span> В Windows-системах таковой утилиты напрочь нет. Рассмотрим возможные альтернативы:</p>
<p><strong>1.</strong> Для небольших файлов, объем которых не превышает десятков килобайт, достаточно быстрым вариантом является загрузить все содержимое файла в память и посчитать количество получившихся строк:</p>
<pre class="console">$linecnt = count(file("filename.txt"));</pre>
<p>Этот способ не подходит для больших файлов, т.к. таким образом можно легко зажевать всю доступную PHP память.</p>
<p><strong>2.</strong> Для файлов чуть большего размера можно использовать циклический перебор строк и подсчитывать количество итераций до окончания файла:</p>
<pre class="console">$f = fopen("filename.txt",'r');
$linecnt = 0; while (fgets($f)) $linecnt++;
fclose($f);</pre>
<p>Т.к. файл не загружается в память целиком, то расход памяти в данном подходе значительно меньше.</p>
<p><strong>3.</strong> Для больших файлов можно использовать внешние средства. На просторах сети можно отыскать linux-утилиту <strong>wc</strong>, откомпилированную с <strong>Cygwin</strong>, и запустить ее в Windows. А можно обойтись и без установки стороннего софта &#8211; встречайте нецелевое использование стандартной утилиты <strong>find.exe</strong> (в сочетании с <strong>type.exe</strong>):</p>
<pre class="console">$linecnt = exec('type "filename.txt" | find /c /v ""');</pre>
<p>При помощи <strong>type</strong> производится вывод на stdout содержимого файла, а <strong>find</strong> подсчитывает количество непустых строк. Необходимо обратить внимание, что утилита <strong>type</strong> вообще никаким образом не понимает относительных путей, поэтому для передачи пути к файлу не из текущего каталога необходимо воспользоваться функцией <strong>realpath()</strong>.</p>
<p>Пример функции, позволяющий подсчитывать количество строк в крупных файлах как при запуске под Windows, так и под Linux:</p>
<pre class="console">function linecnt($path)
{
	if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
		return (int)exec('type "'.realpath($path).'" | find /c /v ""');
	else
		return (int)exec('wc -l '.$path);
}</pre>
<p>PS: Интересная <a href="http://blogs.msdn.com/b/oldnewthing/archive/2011/08/25/10200026.aspx" target="_blank">историческая справка</a> о том, по какой причине find.exe может выискивать в файле непустые строки путем сравнения с &#8220;&#8221; (пустой строкой).</p>
]]></content:encoded>
			<wfw:commentRss>https://tt.erinome.net/2013/08/602/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PHP] simplexml_load_file и timeout</title>
		<link>https://tt.erinome.net/2013/03/474</link>
		<comments>https://tt.erinome.net/2013/03/474#comments</comments>
		<pubDate>Tue, 26 Mar 2013 08:44:05 +0000</pubDate>
		<dc:creator><![CDATA[root]]></dc:creator>
				<category><![CDATA[Сеть и интернет]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tt.erinome.net/?p=474</guid>
		<description><![CDATA[При запросе XML-данных с внешней URL через функцию simplexml_load_file() отсутствует возможность указания максимального времени выполнения (таймаута). В результате при недоступности удаленного ресурса или временных проблемах с доступом к сети могут возникать непредвиденно большие задержки при использовании данной функции. Простым решением &#8230; <a href="https://tt.erinome.net/2013/03/474">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>При запросе XML-данных с внешней URL через функцию <strong>simplexml_load_file()</strong> отсутствует возможность указания максимального времени выполнения (таймаута). В результате при недоступности удаленного ресурса или временных проблемах с доступом к сети могут возникать непредвиденно большие задержки при использовании данной функции.<span id="more-474"></span></p>
<p>Простым решением подобной проблемы является возможность запросить XML-данные каким-либо другим средством, предусматривающим возможность настройки таймаутов, после чего передать полученную строку в <strong>simplexml_load_string()</strong>.</p>
<h3>Использование file_get_contents+simplexml_load_string</h3>
<p>При использовании <strong>file_get_contents()</strong> для запроса удаленных данных имеется возможность указания ряда параметров при помощи т.н. <em>контекста</em>, создаваемого командой <strong>stream_context_create()</strong>. Например, указать предельное время ожидания HTTP-запроса можно следующим образом:</p>
<pre class="console">$opts = stream_context_create( array(
		'http' => array(
			'timeout' => 1
			)
		) );
$xmlstr = file_get_contents($url, false, $opts);
$xml = @simplexml_load_string($xmlstr);</pre>
<p>Либо короче:</p>
<pre class="console">$xmlstr = file_get_contents($url, $false, stream_context_create(array('http' => array('timeout' => 1))));
$xml = @simplexml_load_string($xmlstr);</pre>
<p>Этот способ работает хорошо до тех пор, пока мы не сталкиваемся с таймаутом при запросе доменного имени $url с DNS. В этом случае выставленный в <em>контексте</em> параметр &#8216;timeout&#8217; в обработке не участвует и время ожидания по-прежнему может быть слишком высоко.</p>
<h3>Использование cURL+simplexml_load_string</h3>
<p>Применение библиотеки cURL хотя и требует фактического наличия означенной библиотеки и более громоздко при использовании, но представляет более широкие возможности по настройке параметров соединения:</p>
<pre class="console">$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$xmlstr = curl_exec($ch);
curl_close($ch);
$xml = @simplexml_load_string($xmlstr);</pre>
<p>При этом параметром &#8216;CURLOPT_TIMEOUT&#8217; определяется не только время выполнения запроса, но целиком время выполнения всех операций cURL, включая запросы к DNS. В PHP начиная с версии 5.2.3 поддерживается также параметр &#8216;CURLOPT_TIMEOUT_MS&#8217;, позволяющий указать длительность таймаута в миллисекундах.</p>
<h3>Запуск под Windows?</h3>
<p>В случае использования apache+php в системе под управлением MS Windows даже при использовании cURL мне не удалось найти никакой действительно работоспособной возможности для обхода длительного таймаута при сбое DNS на стороне локального сервера.</p>
<p>Интересно также, что в принципе запуск модуля cURL (php_curl.dll) в Windows-версии apache по умолчанию происходит с ошибкой, которая в error.log на стороне apache выглядит так:</p>
<pre class="console">PHP Warning:  PHP Startup: Unable to load dynamic library 'C:\\php5\\ext\\php_curl.dll' - \xcd\xe5 \xed\xe0\xe9\xe4\xe5\xed \xf3\xea\xe0\xe7\xe0\xed\xed\xfb\xe9 \xec\xee\xe4\xf3\xeb\xfc.\r\n in Unknown on line 0</pre>
<p>Либо, при переводе в человеческий вид, так:</p>
<pre class="console">PHP Warning:  PHP Startup: Unable to load dynamic library 'C:\\php5\\ext\\php_curl.dll' - Не найден указанный модуль.\r\n in Unknown on line 0</pre>
<p>Это, конечно, на редкость информативно и предоставляет возможности для полета фантазии на тему того, о каком именно модуле идет речь. Интересно отметить тот факт, что при запуске <em>php -i</em> модуль cURL загружается корректно, а проблема возникает только при запуске из-под apache.</p>
<p>В описываемом случае проблема отсутствующего <em>модуля</em> решилась путем копирования файлов &#8216;libeay32.dll&#8217; и &#8216;ssleay32.dll&#8217; из каталога <strong>C:/php5</strong> в каталог <strong>C:/apache/bin</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>https://tt.erinome.net/2013/03/474/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PHP] Создание и корректировка URL</title>
		<link>https://tt.erinome.net/2013/03/424</link>
		<comments>https://tt.erinome.net/2013/03/424#comments</comments>
		<pubDate>Wed, 06 Mar 2013 11:23:08 +0000</pubDate>
		<dc:creator><![CDATA[root]]></dc:creator>
				<category><![CDATA[Сеть и интернет]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://tt.erinome.net/?p=424</guid>
		<description><![CDATA[При необходимости динамически генерировать веб-ссылки для статей возникают закономерные вопросы о том, как правильно следует их оформлять. Транслитерация В случае неимоверного желания использовать в ссылках русские слова, все же может оказаться лучше преобразовывать их в латиницу транслитом. Этим можно решить &#8230; <a href="https://tt.erinome.net/2013/03/424">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>При необходимости динамически генерировать веб-ссылки для статей возникают закономерные вопросы о том, как правильно следует их оформлять.<span id="more-424"></span></p>
<h2>Транслитерация</h2>
<p>В случае неимоверного желания использовать в ссылках русские слова, все же может оказаться лучше преобразовывать их в латиницу транслитом. Этим можно решить ряд проблем в некоторых браузерах, а также такие ссылки будут выглядеть чуть более читаемыми для иностранных посетителей сайта.</p>
<p>Реализация проста:</p>
<pre class="console">// массив замен
$converter = array('а' => 'a', 'б' => 'b', 'в' => 'v', ...);
// быстрая замена
$string = strtr($string, $converter);</pre>
<h2>Граничные эффекты</h2>
<p>Если выбор названия веб-ссылки лежит на пользователе, то не стоит ожидать от него чудес разумности. Избавиться от пробелов, символов табуляции и прочих бессмысленных символов в начале и конце строки поможет обычная фунция trim:</p>
<pre class="console">$string = trim($string);</pre>
<h2>Уничтожение спецсимволов</h2>
<p>В некоторых случаях при автоматическом составлении заголовков в них попадают различные знаки пунктуации, слэши и другие символы, которым нечего делать во фрагменте URL. Их необходимо вырезать или заменять на нейтральные символы. Также следует поступать и с символами пробела. Одним из вариантов может быть замена на дефисы любых символов, не являющихся цифрами или латинскими буквами. При этом в случае двух замен подряд заменяющие дефисы должны склеиваться.</p>
<p>Это реализуется одной строкой при помощи regex&#8217;а:</p>
<pre class="console">$string = preg_replace('/[^a-z0-9]+/', '-', strtolower($string));</pre>
<p>Эта строка также переводит все символы в нижний регистр. Отметим, что после выполнения данной замены следует проверять, не схлопнулась ли вся исходная строка в один единственный дефис. Это означает, что все символы в исходной строке не были цифрами или латинскими буквами.</p>
<h2>Подчеркивания или дефисы</h2>
<p>Один из не самых однозначных вопросов заключается в том, какой символ использовать для разделения слов в URL &#8211; подчеркивание или тире (дефис). В целом, этот вопрос фактически относится лишь к тому, как поисковые системы станут интерпретировать используемые на вашем сайте ссылки. А вот интерпретируют данные поисковые системы эти разделители по-разному.</p>
<p>Так, например, для поисковика MS Bing дефисы и подчеркивания в качестве разделителей неразличимы. А вот поисковик Google, согласно заявлению его <a href="http://www.youtube.com/watch?feature=player_embedded&#038;v=AQcSFsQyct8" target="_blank">представителей</a>, считает дефисы разделителями, а подчеркивания просто игнорирует. Так, выражение &#8220;erinome-lane&#8221; в адресной строке для Google преобразуются в &#8220;erinome lane&#8221;, а выражение &#8220;erinome_lane&#8221; будет восприниматься слитно &#8211; &#8220;erinomelane&#8221;.</p>
<p>Кратко: на настоящий момент в URL рекомендуется использовать тире вместо подчеркиваний.</p>
]]></content:encoded>
			<wfw:commentRss>https://tt.erinome.net/2013/03/424/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
