Проверка готовности symfony

Найден замечательный проект с полезными советами перед запуском сайта на symfony. Некоторые пункты касаются вообще любых сайтов:

  • Создание быстрых, но полезных страниц ошибок 403, 404, 500
  • Наличие иконки сайта favicon.ico (сюда же robots.txt)
  • Отказ от файлов .htaccess
  • Строгая фильтрация загружаемых пользователями файлов, запрет выполнения из папки загрузки
  • PHP-акселератор
  • HTML-атрибут языка lang="ru"
  • Задать свое название сессии в куках

Приятного выкатывания!

Перенос проекта cp1251 → utf-8

Этот маленький скрипт я написал для проекта в кодировке windows-1251, так как база данных MySQL оказалась в кодировке UTF-8 и все «поплыло». Чтобы исправить отображение русских букв, я решил перевести все файлы проекта в современный формат UTF.

Использование: Кидаем скрипт в папку с проектом, запускаем с параметром -p dirname, в результате все скрипты и шаблоны (*.php, *.tpl, *.conf, *.inc) переводятся на UTF-8. Для работы необходимо расширение iconv. Если файл уже в UTF-8, то пропускает.


<?php
/**
 * @usage
 * php recode.php -p www
 */

// ищем файлы
function browseCall($dir$regex$cb) {
  foreach(
glob(chop($dir,'/')."/*") as $file) {
    if (
is_dir($file)) browseCall($file$regex$cb);
    if (
is_file($file) && preg_match($regexbasename($file)))
      call_user_func_array($cb, array($file));
  }
}
// заменяем кодировку
function myRecode($file) {
  
$s file_get_contents($file);
  
$e detectEncoding($s);
  echo 
"[".$e."] $file";
  if (
'windows-1251'==$e) {
    
$r iconv('windows-1251','utf-8',$s);
    
file_put_contents($file$r);
    echo 
" [written ".strlen($r)." bytes]\n";
  }
  else echo 
"\n";
}
// определялка кодировки
function detectEncoding($string) {
  static 
$list = array('utf-8''windows-1251');
  foreach (
$list as $item) {
    
$sample = @iconv($item$item$string);
    if (
md5($sample) == md5($string))
      return 
$item;
  }
  return 
null;
}

if (preg_match("~-p ([^ ]+)~"implode(' ',$argv), $matches)) {
  
$path $matches[1];
  
browseCall($path"~\.php$|\.tpl$|\.conf$|\.inc$|\.js$~""myRecode");
}
?>

Настраиваем gettext в wordpress

Тот самый gettext, при упоминании которого меня уже начинает бросать в дрожь, оказывается, можно встроить в WordPress, и выиграть в производительности вашего блога.

К сожалению, делается это пока только руками, а при накате обновлений вся малина потрется. Кроме того, установка обошлась мне в час времени.

Мои комментарии к статье:
1) Локаль не задавайте — умрут теги.
2) Объявите переменную LANG или LANGUAGE (в зависимости от платформы):

putenv("LANGUAGE=ru_RU");

Это нужно, чтобы gettext открыл папку вашего языка, например:
/wp-content/languages/ru_RU/LC_MESSAGES/default.mo

На этом наш сеанс магии заканчивается, до новых встреч!

SQL-Рекурсия, версия замороченная

Написал функцию, которая осуществляет собственно sql-рекурсию, вызывая ваш callback на каждой итерации. Применять можно для таблиц всяких рубрикаторов, вложенность которых построена на т.н. parentID.

Поддерживаются дополнительные переменные, которые будут передаваться в callback-функцию. Сама функция весьма хитро жонглирует аргументами, давая возможность передать в sqlRecursion() любое количество дополнительных аргументов (после обязательных).
Единственное ограничение на sql-запрос: Ключевое поле ID должно идти первым, а родительский ID — последним.

/**
 * Recursively executes sql query by parentID
 */
function sqlRecursion($sprintf, $res, $callback, $level=0) {
  $ordering = 0; $a = func_get_args();
  $callbackParams = array_splice($a, 4);
  $tmp = qry($q=call_user_func_array('sprintf', $sprintf), $res);
  while($row = mysql_fetch_assoc($tmp)) {
    $tm = $callbackParams;
    array_unshift($tm, $row, ++$ordering, $level);
    // callback($row, $ordering, $some_vars)
    call_user_func_array($callback, $tm);
    // replaces parent id in sql structure $sprintf
    array_splice($sprintf,count($sprintf)-1,1,reset($row));
    $recParams = array($sprintf, $res, $callback, $level+1);
    array_splice($recParams, count($recParams),0,$callbackParams);
    call_user_func_array('sqlRecursion', $recParams);
  }
}

Пример использования прилагается.

// @example
 function myCallback($row, $ordering, $level, $var1, $var2) {}
 sqlRecursion(array(
     "select ID, %s from %s where parent = %d",
     // ID (keyfield) must be first,
     // parent id must be last in sql query
     'myField', 'myTable', 31337
    ),
    $mysqlResourceLink, 'myCallback', 0, $var1, $var2
 );

phpDesigner 2008

phpDesigner

Обзавелся неплохим редактором кода — phpDesigner от компании mpsoftware. (далее…)

gettext in smarty

Есть прекрасное универсальное решение мультиязычности любых приложений. Называется оно gettext. Работает gettext очень просто, но в этом его прелесть.

Суть случая php+smarty такова:
Приложение содержит строки, требующие локализации, в следующем формате:

  • PHP: _("Текст для локализации") — пропущенные через функцию подчеркивание;
  • Smarty: {"Текст для локализации"|_} — вставленные в модификатор подчеркивание.

Далее под все платформы есть редакторы *.po файлов, позволяющие рекурсивно обходить папки с исходниками. Тип кода определяется по расширению, поэтому иногда требуется донастройка. Так как парсера для smarty я не нашел, то написал свой на php. Результат работы: Создается временный php-файл со строками из шаблонов, скармливается xgettext-у и в итоге все тексты отображаются в редакторе poedit, который уже сохраняет в .po-файл и компилирует его в .mo-файл (платформа windows).
Скрипт протестирован на php 5.2.3.
(далее…)

Доклад Rasmus Lerdorf на phpconf 2006

В Москве проходила международная PHP-конференция phpconf. Одним из интереснейших материалов был доклад
Rasmus Lerdorf (Расмус Лердорф)
architect — platform engineering, Yahoo! Inc
г. Сан-Франциско, США.

Тезисы:

Building a web application is easy. Making it secure is hard. We will explore the dangers of cross-site scripting and do a bit of real-time spelunking to demonstrate just how rampant this problem is.

Так как в раздаточных материалах этого доклада не было, вот где его можно скачать/посмотреть: http://talks.php.net/show/phpclub/

От себя замечу, что в докладе проводится тест производительности php-приложения и конкретное ускорение его работы за счет различных модулей PHP.

Как регулярным выражением вынуть кучу Email-ов из текста?

Работает следующее регулярное выражение:

$mailReg = '/[A-Z0-9._-]+@[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}/i';
preg_match_all($mailReg, $str, $matches);

В массиве с индексом ноль $matches[0] будут находиться вынутые e-mail-ы. Я тестировал этот прием на достаточно большом текстовом файле почты (почта на сервере хранится в одном текстовом файле), порядка 400 М. Дальше полезно убрать дублирующиеся e-mail-ы, но это уже другая история…

Арифметика в PHP: bcmul() не считает числа порядка 0.00001

Описание пробемы:
bcscale(33);
echo 
bcmul(1E-42E-3); // 0.0000002
echo bcmul(1E-42E-5); // 0.0000

Функция bcmul() при работе с числами меньше 0.00001 возвращает ноль (!). Вот от кого не ожидал!
(далее…)