<rmcreative>

RSS

Все заметки с тегом «php»

Можно уточнить:

  1. urldecode и кодировки

    9 июля 2011

    Сегодня неожиданно много времени провёл за изучением одного из репортов в трекере Yii. Первопричина оказалась совсем не той и крылась, как это часто бывает, в несоблюдении стандартов. Вообще тонкости две:

    1. PHP-шный urldecode работает напрямую с октетами (теми, что %AB), так что интерпретация строки зависит от кодировки скрипта. В случае Yii это UTF-8.

    2. Хоть RFC 3986 в районе 16-ой страницы и говорит нам, что «data should first be encoded as octets according to the UTF-8 character encoding», но всё-же достаточно большое количество ПО использует другие кодировки. Чаще всего это ISO-8859-1.

    То есть после декодирования мы можем получить либо UTF-8, либо что-то ещё. Это ещё скорее всего будет ISO-8859-1.

    Ну и решение — свой urldecode:

    /**
     * Improved variant of urldecode.
     * Properly decodes both UTF-8 and ISO-8859-1 encoded URIs.
     *
     * @param string $str encoded string
     * @return string decoded string
     */
    private function urldecode($str)
    {
        $str = urldecode($str);
     
        // is it UTF-8?
        // http://w3.org/International/questions/qa-forms-utf-8.html
        if(preg_match('%^(?:
           [\x09\x0A\x0D\x20-\x7E]            # ASCII
         | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
         | \xE0[\xA0-\xBF][\x80-\xBF]         # excluding overlongs
         | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
         | \xED[\x80-\x9F][\x80-\xBF]         # excluding surrogates
         | \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
         | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
         | \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
        )*$%xs', $str))
        {
            return $str;
        }
        else
        {
            return utf8_encode($str);
        }
    }
    3 комментария
  2. Сравнение популярных PHP-фреймворков

    8 июля 2011

    CMS Magazine опубликовал собранную мной сравнительную табличку по PHP-фреймворкам. Данные очень субъективны и основаны на личном опыте, поэтому ранее я не акцентировал на ней внимания. Если у вас есть уточнения или что-либо кажется вам совсем не верным, напишите об этом в комментариях.

    Рассматриваем

    48 комментариев
  3. PHP 5.4 alpha1

    30 июня 2011

    После долгого безрелизья PHP сдвинулся с мёртвой точки. Команда выпустила вкусную альфа-версию 5.4, которая, кстати, является первой версией, выпущенной согласно releaseprocess RFC:

    А вот типизацию параметров для скалярных типов данных, похоже, выпилили совсем.

    Версия тестовая, так что использовать на production не стоит. О найденных ошибках отписываемся в [email protected] и в багтрекер.

    Да, в следующих альфах должна быть ещё куча вкусностей.

    5 комментариев
  4. Несколько SQL-запросов за один раз через PDO

    24 июня 2011

    Понадобилось исполнить несколько не однотипных запросов за один раз. Также, как это делает mysqli::multi_query, но через PDO. Сделать это, оказалось, вполне реально, но и без интересностей не обошлось.

    Во-первых нагуглить это оказалось почему-то не так просто: вылезали какие-то обсуждения PDO_MYSQLND 2008-го года и, хоть и свежие, но оставшиеся без внятного ответа вопросы на StackOverflow.

    Оказалось, что PDO_MYSQLND с релизом PHP 5.3 заменил PDO_MYSQL, который такие вещи не поддерживал. Причём заменил под тем же именем PDO_MYSQL.

    Итого, для выполнения нескольких запросов за один раз понадобится:

    • PHP 5.3+
    • mysqlnd
    • Эмуляция prepared statement через PDO::ATTR_EMULATE_PREPARES, выставленный в 1 (по умолчанию) или, как альтернатива, не использование prepared statements и выполнение запроса напрямую через $pdo->exec.

    Используем exec

    $db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
     
    // работает как для реальных statement-ов, так и для эмуляции
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
     
    $sql = "DELETE FROM car; INSERT INTO car(name, type) VALUES ('car1', 'coupe'); INSERT INTO car(name, type) VALUES ('car2', 'coupe');";
     
    try {
        $db->exec($sql);
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
        die();
    }

    Используем statement-ы

    $db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
     
    // Не будет работать с реальными statement-ами. Только с эмуляцией.
    // Строку ниже можно закомментировать, это умолчание
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
     
    $sql = "DELETE FROM car; INSERT INTO car(name, type) VALUES ('car1', 'coupe'); INSERT INTO car(name, type) VALUES ('car2', 'coupe');";
     
    try {
        $stmt = $db->prepare($sql);
        $stmt->execute();
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
        die();
    }
    12 комментариев
  5. DevConf 2011, впечатления

    6 июня 2011

    Вчера вернулся с DevConf, где читал доклад про Yii и процесс его разработки. В общем доклад был похож на одноимённый с CodeFest, но включал себя багфиксы и раскрывал мысль несколько лучше. На вопрос «во что может превратиться Yii, если его разработчики станут компанией» я чётко ответил «в Битрикс», чем, сдаётся мне, поверг окружающих в лёгкий в шок. На самом деле оговорился :) Вопросы были, кстати, очень хорошие и правильные. Спасибо задававшим их людям.

    Читаем

    18 комментариев
  6. Рекурсивные анонимные функции PHP

    1 июня 2011

    // считаем факториал
    $fact = function($n) use (&$fact)
    {
        if($n==1)
            return 1;
     
        return $fact($n-1)*$n;
    };
    echo $fact(5); // =120
    26 комментариев
  7. Импорт больших SQL-дампов через PHP

    27 мая 2011

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

    $f = @fopen("path/to/dump.sql", "r");
    if($f)
    {
        $q = '';
     
        while(!feof($f))
        {
            // читаем построчно в буфер $q      
            $q .= fgets($f);
     
            // пока не упрёмся в ;
            if(substr(rtrim($q), -1) == ';')
            {
                // выполяем запрос
                execute_sql($q);
     
                // обнуляем буфер
                $q = '';
            }
        }
    }
    20 комментариев
  8. Как скомпилить libevent для PHP под Windows

    22 мая 2011

    Компилировать расширения PHP под Windows нет так уж и просто. Но задача вполне выполнимая.

    Читаем

    6 комментариев
  9. PHP, построение URL

    20 мая 2011

    При работе с разными API (и не только) требуется построить URL. На входе имеем массив параметров имя-значение, на выходе получаем URL. Решение очень простое:

    function getUrl($url, $params = array())
    {
        return $url.'&'.http_build_query($params);
    }
     
    // используем так
    echo getUrl('http://open.mapquestapi.com/nominatim/v1/search?format=json', array('q' => 'Olympiaturm, Spiridon-Louis-Ring 7, München 80809'));

    UPD: http_build_url.

    13 комментариев
  10. Короткий echo в PHP 5.4

    19 мая 2011

    Похоже, в 5.4 и последующих версиях PHP собираются включить короткий echo по умолчанию и сделать его независимым от short_tags. Меня лично данное известие радует

    <?=$username?>

    выглядит гораздо приятнее, чем

    <?php echo $username?>

    Единственное, что пока останавливает от повсеместного использования более короткого синтаксиса — необходимость писать продукты под дефолтные конфиги PHP. Хотя, например, в коде этого блога как раз используется короткий echo.

    14 комментариев