PHP и UTF-8: второй этап (ничего не забыли?)
Итак, на первом этапе перевода нашего веб-сайта на UTF8 мы выяснили какие функции нам нужно будет переписать и какие файлы затронуть. Например, у меня это 38 функций и 173 файла. На втором этапе я предлагаю выяснить не могли ли мы что-то забыть.
Могли. Во-первых, я ищу только файлы с расширением «php», даже если проект ваш и вы твёрдо помните, что никаких других расширений для PHP вы не используете, то я всё равно рекомендую это проверить — может есть файлы с расширением «inc» в чужой библиотеке или где-то в шаблонах используется PHP?
Итак, как их найти? Мне кажется, хороший путь — посмотреть где встречается сигнатура „<?“:
bolk@dev:~/daproject$ grep --binary-files=without-match -R '<?' * | cut -d':' -f1 |
> grep -v '.svn' | sed -re 's/.*?/([^/]+)/1/' | awk -F. '/./{print $NF}' | sort -u
conf
csv
example
inc
js
package
php
pm
png
py
svg
tpl
xml
xsl
Очевидно, что файлы формата XML (у меня это расширения xml, xsl и svg) так же могут содержать сигнатуру „<?“ (там это часть языка), текстовые файлы (conf, csv) так же её могут содержать (они вообще могут содержать что угодно).
Как же отфильтровать такой мусор? У интерпретатора PHP есть специальная опция, для того, чтобы проверить является ли подаваемый на вход файл синтаксически верным. Мы ей можем воспользоваться:
bolk@dev:~/daproject$ grep --binary-files=without-match -R '<?' * | cut -d':' -f1 | egrep -v '.svn|.php' |
> xargs -rn1 -I{} php -r 'echo `php -l {}`;' | grep -F 'No syntax errors detected in' | sort -u
No syntax errors detected in htdocs/_dir/file1.csv
No syntax errors detected in htdocs/_dir/file2.png
No syntax errors detected in htdocs/_dir/file3.csv
No syntax errors detected in htdocs/_dir/file4.png
No syntax errors detected in htdocs/_dir/file5.csv
No syntax errors detected in templates/file1.tpl
…
Оказывается, PHP у меня есть даже внутри файлов с расширением png!
К несчастью, у меня таких файлов достаточно прилично — 39, поэтому я собираюсь некоторые из них отбросить сразу:
sed -e 's/^No syntax errors detected in //' tool2.log | xargs -n1 head --verbose | less
Оказалось, что рассматривать как файлы PHP нужно файлы с ещё двумя расширениями — inc и tpl, остальные так же содержат PHP-код, но его там, либо одна строка (только вызов include), либо это файл примера (с расширением example).
Поэтому я добавлю в программу из предыдущего этапа ещё два расширения и запущу её снова. У меня количество функций не изменилось — 38, а вот файлов добавилось — стало 176 против 173. Ура, теперь файлы с PHP-содержимым мы не упустим.
А что по поводу используемых расширений PHP? Их много и с каждым месяцем становится всё больше (я сам написал 3 или 4), вдруг какие-то из них не работают с UTF-8?
Для начала неплохо было бы узнать сколько у нас вообще расширений. Я знаю, что расширения в PHP подключаются двумя способами: в конфигурационном файле и при помощи функции dl. Для начала посмотрим, используется ли у нас функция dl:
bolk@dev:~/daproject$ find \( -name '*.php' -or -name '*.inc' -or -name '*.tpl' \) -exec egrep -i 'dl\s*\(' {} \; -print
* @return bool Success or not on the dl() call
// if either returns true dl() will produce a FATAL error, stop that
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
./php/lib/PEAR.php
if(!extension_loaded("mysql")) dl("mysql.so");
./php/db/mysql.php
У меня dl используется. Берём на заметку, что через dl подгружается модуль MySQL, а заглянув в PEAR, обнаружим, что там есть метод loadExtension, который является мультиплатформенной обёрткой для dl.
Для очистки совести я поискал случаи использования loadExtension в проекте (не забудьте, что регистр нужно игнорировать), но не нашёл.
Итак, мы выяснили какие модули у нас подгружаются через dl — только один (mysql), что же вкомпилированно в сам PHP или подключено из файлов конфигурации? Нет способа лучше, чем узнать что сам PHP думает об этом:
bolk@dev:~/daproject$ php -m
[PHP Modules]
zip
xmlwriter
libxml
xml
wddx
tokenizer
…
У меня это 54 модуля. Это очень много. Действительно ли их столько используется в проекте? Вот уж вряд ли. Надо каким-то образом найти все те, которые используются. Как это сделать? Вообще, модули могут быть использованы двояко — в виде функций этих модулей (и тогда нам надо найти вызовы этих функций), либо как объекты классов, предоставляемых модулем.
Отсюда мысль — узнать какие функции/классы содержатся в модуле и поискать их в файлах.
Давайте я это сделаю в следующей части, а то мне сейчас собеседование проводить.
чем не устраивает такой вариант?
[arty@arty ~]$ php -m
[PHP Modules]
cgi-fcgi
ctype
curl
…
[Zend Modules]
Комментарий для arty.name:
Чёрт его знает :) Забыл просто о таком варианте, сейчас внесу в статью, спасибо!