Установка расширений PECL

Введение в установку PECL

» PECL — это репозиторий расширений PHP, которые доступны вам через систему » PEAR. Эта часть руководства предназначена для демонстрации того, как вы можете получить и установить расширения PECL.

Эти инструкции подразумевают, что /your/phpsrcdir/ является путем к каталогу с дистрибутивом исходного кода PHP, а extname — это имя расширения PECL. Поэтому, приведем в соответствие. Эти инструкции также подразумевают знакомство с » командой pear. Информация в руководстве PEAR для команды pear также применима для команды pecl.

Для того, чтобы расширение можно было использовать, оно должно быть собрано, установлено и загружено. Методы, описанные ниже, предоставляют вам различные рекомендации по поводу того, как собрать и установить расширения, но сами они не будут автоматически загружены. Расширения могут быть загружены через добавление директивы extension в файл php.ini, или путем использования функции dl().

В процессе сборки модулей PHP важно, чтобы у вас были правильные версии необходимых утилит (autoconf, automake, libtool и т.д.). Информацию об этих утилитах и их версиях можно посмотреть тут » Anonymous CVS Instructions.

Загрузка расширений PECL

Есть несколько вариантов для загрузки расширений PECL, в том числе:

  • » http://pecl.php.net/Вебсайт PECL содержит информацию о различных расширениях, которые предоставлены PHP Development Team. Информация, доступная на этом вебсайте, включает в себя: лог изменений, новости релизов, требования и другие подобные детали.
  • pecl download extnameРасширения PECL, которые были опубликованы на сайте PECL, доступны для скачивания и установки через » команду pecl. Также, могут быть также указаны особые ревизии.
  • CVSБольшинство расширений PECL, также, находятся в CVS. Веб-интерфейс для просмотра доступен по адресу » http://cvs.php.net/pecl/. Для загрузки напрямую из CVS используется следующая последовательность команд. Стоит отметить, что пользователь cvsread имеет пароль phpfi:
    $ cvs -d:pserver:cvsread@cvs.php.net:/repository login
    $ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/extname
  • Загрузка для Windows Пользователи Windows могут найти скомпилированные расширения PECL путем скачивания Collection of PECL modules со страницы » PHP Downloads, либо через » PECL Snapshot, либо расширения DLL на странице » PECL4WIN. Для компиляции PHP под Windows прочитайте соответствующий раздел
  • PECL для пользователей Windows

    Как и в случае DLL расширения PHP, установка проста и заключается в копировании файла DLL расширения PECL в директориюextension_dir и подключением затем его через php.ini. Например, добавьте следующую строку в ваш php.ini:

    extension=php_extname.dll

    После выполнения этих действий, перезапустите web-сервис.

    Компиляция общих расширений с помощью команды pecl

    PECL позволяет легко создавать общие расширения PHP. Используя » команду pecl, выполните следующее:

    $ pecl install extname

    Эта команда загрузит исходный код для расширения extname, скомпилирует и установит extname.so в вашу директорию extension_dir. Файл extname.so может быть затем загружен в php.ini

    По умолчанию, команда pecl не будет устанавливать пакеты, отмеченные состоянием alpha или beta. Если нет доступных стабильных версий пакетов, вы можете установить beta версию пакета, используя следующую команду:

    $ pecl install extname-beta

    Также, вы можете установить определенную версию используя такой вариант:

    $ pecl install extname-0.1

    Замечание: После подключения расширения в php.ini необходимо перезапустить web-сервис для того, чтобы изменения вступили в силу.

    Компиляция общих расширений с помощью phpize

    Иногда, использование инсталятора pecl не подходит. Это может быть связано с тем, что вы находитесь за файерволом или из-за того, что расширение, которое вы хотите установить, недоступно в PECL-совместимом пакете (к примеру, расширения из CVS, которые еще не зарелизены). Если вам необходимо собрать такое расширение, вы можете использовать низкоуровневые утилиты для выполнения сборки вручную.

    Команда phpize используется для подготовки окружения для расширения PHP. В следующем примере директория, где находятся исходные коды расширения, называется extname:

    $ cd extname
    $ phpize
    $ ./configure
    $ make
    # make install

    В случае успешной установки будет создан файл extname.so и помещен в PHP extensions directory. Вам будет необходимо добавить строку extension=extname.so в php.ini перед тем, как вы станете использовать это расширение.

    Если в системе отсутствует phpize, но существует возможность установки заранее скомпилированных пакетов (типа RPM), убедитесь, что установлена соответствующая devel версия пакета PHP, так как они часто содержат команду phpize с подходящими файлами заголовоков для сборки PHP и его расширений.

    Используйте phpize —help для просмотра дополнительной информации.

    Компиляция расширений PECL статически в PHP

    Возможно, вы захотите собрать расширение PECL статично в ваш бинарйный файл PHP. Для этого необходимо поместить код расширения в директорию php-src/ext/ и вызвать перегенерацию конфигурационных скриптов через систему сборки PHP.

    $ cd /your/phpsrcdir/ext
    $ pecl download extname
    $ gzip -d < extname.tgz | tar -xvf -
    $ mv extname-x.x.x extname

    В результате будет создана следующая директория:

        /your/phpsrcdir/ext/extname

    После этого, выполните заново сборку конфигурационного скрипта PHP и затем соберите PHP как обычно:

    $ cd /your/phpsrcdir
    $ rm configure
    $ ./buildconf --force
    $ ./configure --help
    $ ./configure --with-extname --enable-someotherext --with-foobar
    $ make
    $ make install

    Замечание: Для запуска скрипта ‘buildconf’ вам необходимы autoconf версии 2.13 и automake версии 1.4+ (более новые версии autoconf могут работать, но это не поддерживается).

    Одна из двух опций —enable-extname или —with-extname используется в зависимости от расширения. Обычно, в случае, когда расширение не требует подключения внешних библиотек, используется —enable. Для того, чтобы убедиться в этом, выполните следующую команду после buildconf:

    $ ./configure --help | grep extname

    Умное Кеширование и Версионность в Javascript/CSS

    Подключая внешние CSS и Javascript, мы хотим снизить до минимума лишние HTTP-запросы.

    Для этого .js и .css файлы отдаются с заголовками, обеспечивающими надежное кеширование.

    Но что делать, когда какой-то из этих файлов меняется в процессе разработки? У всех пользователей в кеше старый вариант — пока кеш не устарел, придет масса жалоб на сломанную интеграцию серверной и клиентской части.

    Правильный способ кеширования и версионности полностью избавляет от этой проблемы и обеспечивает надежную, прозрачную синхронизацию версий стиля/скрип.

    Простое кеширование ETag

    Самый простой способ кеширования статических ресурсов — использование ETag.

    Достаточно включить соответствующую настройку сервера (для Apache включена по умолчанию) — и к каждому файлу в заголовках будет даваться ETag — хеш, который зависит от времени обновления, размера файла и (на inode-based файловых системах) inode.

    Браузер кеширует такой файл и при последующих запросах указывет заголовок If-None-Match с ETag кешированного документа. Получив такой заголовок, сервер может ответить кодом 304 — и тогда документ будет взят из кеша.

    Выглядит это так:

    Первый запрос к серверу (кеш чистый)

    GET /misc/pack.js HTTP/1.1
    Host: javascript.ru

    Вообще, браузер обычно добавляет еще пачку заголовоков типа User-Agent, Accept и т.п. Для краткости они порезаны.

    Ответ сервераСервер посылает в ответ документ c кодом 200 и ETag:

    HTTP/1.x 200 OK
    Content-Encoding: gzip
    Content-Type: text/javascript; charset=utf-8
    Etag: "3272221997"
    Accept-Ranges: bytes
    Content-Length: 23321
    Date: Fri, 02 May 2008 17:22:46 GMT
    Server: lighttpd

    Следующий запрос браузера
    При следующем запросе браузер добавляет If-None-Match: (кешированный ETag):

    GET /misc/pack.js HTTP/1.1
    Host: javascript.ru
    If-None-Match: "453700005"

    Ответ сервера
    Сервер смотрит — ага, документ не изменился. Значит можно выдать код 304 и не посылать документ заново.

    HTTP/1.x 304 Not Modified
    Content-Encoding: gzip
    Etag: "453700005"
    Content-Type: text/javascript; charset=utf-8
    Accept-Ranges: bytes
    Date: Tue, 15 Apr 2008 10:17:11 GMT

    Альтернативный вариант — если документ изменился, тогда сервер просто посылает 200 с новым ETag.

    Аналогичным образом работает связка Last-Modified + If-Modified-Since:

    1. сервер посылает дату последней модификации в заголовке Last-Modified (вместо ETag)
    2. браузер посылает дату закешированной версии в заголовке If-Modified-Since(вместо If-None-Match)
    3. Если скрипт не изменился — ответ содержит только код 304

    Эти способы работают стабильно и хорошо, но браузеру в любом случае приходится делать по запросу для каждого скрипта или стиля.

    Умное кеширование. Версионность

    Общий подход для версионности — в двух словах:

    1. Во все скрипты добавляется версия (или дата модификации). Например, http://javascript.ru/my.js превратится в http://javascript.ru/my.v1.2.js
    2. Все скрипты жестко кешируются браузером
    3. При обновлении скрипта версия меняется на новую: http://javascript.ru/my.v2.0.js
    4. Адрес изменился, поэтому браузер запросит и закеширует файл заново
    5. Старая версия 1.2 постепенно выпадет из кеша

    Дальше мы разберем, как сделать этот процесс автоматическим и прозрачным.

    Жесткое кеширование

    Жесткое кеширование — своего рода кувалда которая полностью прибивает запросы к серверу для кешированных документов.

    Для этого достаточно добавить заголовки Expires и Cache-Control: max-age.

    Например, чтобы закешировать на 365 дней в PHP:

    header("Expires: ".gmdate("D, d M Y H:i:s", time()+86400*365)." GMT");
    header("Cache-Control: max-age="+86400*365);

    Или можно закешировать контент надолго, используя mod_header в Apache:

    Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT"
    Header add "Cache-Control" "max-age=315360000"

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

    Большинство браузеров (Opera, Internet Explorer 6+, Safari) НЕ кешируют документы, если в адресе есть вопросительный знак, т.к считают их динамическими. Именно поэтому мы добавляем версию в имя файла. Конечно, с такими адресами приходится использовать решение типа mod_rewrite, мы это рассмотрим дальше в статье.P.S А вот Firefox кеширует адреса с вопросительными знаками.

    Автоматическое преобразование имен

    Разберем, как автоматически и прозрачно менять версии, не переименовывая при этом сам файлы.

    Имя с версией -> Файл

    Самое простое — это превратить имя с версией в оригинальное имя файла.

    На уровне Apache это можно сделать mod_rewrite:

    RewriteEngine on
    RewriteRule ^/(.*\.)v[0-9.]+\.(css|js|gif|png|jpg)$    /$1$2    [L]

    Такое правило обрабатывает все css/js/gif/png/jpg-файлы, вырезая из имени версию.

    Например:

    /images/logo.v2.gif -> /images/logo.gif
    /css/style.v1.27.css -> /css/style.css
    /javascript/script.v6.js -> /javascript/script.js

    Но кроме вырезания версии — надо еще добавлять заголовки жесткого кеширования к файлам. Для этого используются директивы mod_header:

    Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT"
    Header add "Cache-Control" "max-age=315360000"

    А все вместе реализует вот такой апачевый конфиг:

    RewriteEngine on
    # убирает версию, и заодно ставит переменную что файл версионный
    RewriteRule ^/(.*\.)v[0-9.]+\.(css|js|gif|png|jpg)$ /$1$2 [L,E=VERSIONED_FILE:1]
     
    # жестко кешируем версионные файлы
    Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE
    Header add "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

    Из-за порядка работы модуля mod_rewrite, RewriteRule нужно поставить в основной конфигурационный файл httpd.conf или в подключаемые к нему(include) файлы, но ни в коем случае не в .htaccess, иначе команды Header будут запущены первыми, до того, как установлена переменная VERSIONED_FILE. Директивы Header могут быть где угодно, даже в .htaccess — без разницы.

    Автоматическое добавление версии в имя файла на HTML-странице

    Как ставить версию в имя скрипта — зависит от Вашей шаблонной системы и, вообще, способа добавлять скрипты (стили и т.п.).

    Например, при использовании даты модификации в качестве версии и шаблонизатора Smarty — ссылки можно ставить так:

    <link href="{version src='/css/group.css'}" rel="stylesheet" type="text/css" />

    Функция version добавляет версию:

    function smarty_version($args){
     
      $stat = stat($GLOBALS['config']['site_root'].$args['src']);
      $version = $stat['mtime'];
     
      echo preg_replace('!\.([a-z]+?)$!', ".v$version.\$1", $args['src']);
    }

    Результат на странице:

    <link href="/css/group.v1234567890.css" rel="stylesheet" type="text/css" />

    Отпимизация

    Чтобы избежать лишних вызовов stat, можно хранить массив со списком текущих версий в отдельной переменной

    $versions['css'] = array(
      'group.css' => '1.1',
      'other.css' => '3.0',
    }

    В этом случае в HTML просто подставляется текущая версия из массива.

    Можно скрестить оба подхода, и выдавать во время разработки версию по дате модификации — для актуальности, а в продакшн — версию из массива, для производительности.

    Применимость

    Такой способ кеширования работает везде, включая Javascript, CSS, изображения, flash-ролики и т.п.

    Он полезен всегда, когда документ изменяется, но в браузере всегда должна быть текущая актуальная версия.

    Хранение изображений в базе данных MySQL

    Для хранения изображений в базе данных MySQL необходимо определить одно из полей таблицы как производное от типа BLOB. Сокращение BLOB означает большой двоичный объект. Тип хранения данных BLOB обладает несколькими вариантами:

    • TINYBLOB — может хранить до 255 байт
    • BLOB — может хранить до 64 килобайт информации
    • MEDIUMBLOB — до 16 мегабайт
    • LONGBLOB — до 4 гигабайт

    Соответсвенно, для хранения изображений нам надо создать таблицу images с двумя полями:

    • id — уникальный ID изображения
    • content — поле для хранения изображения

    Для сохранения файла изображения в базе данных необходимо прочитать файл в переменную и создать запрос на добавление данных в таблицу. Допустим у нас есть форма для загрузки файла изображения на сервер:

    <form action="putimage.php" enctype="multipart/form-data" method="post"> Изображение: <input name="image" type="file" />
    <input type="submit" value="Загрузить" />
    </form>Обработчик формы - файл putimage.php:
    // Проверяем пришел ли файл
    if( !empty( $_FILES['image']['name'] ) ) {
    // Проверяем, что при загрузке не произошло ошибок
    if ( $_FILES['image']['error'] == 0 ) {
    // Если файл загружен успешно, то проверяем - графический ли он
    if( substr($_FILES['image']['type'], 0, 5)=='image' ) {
    // Читаем содержимое файла
    $image = file_get_contents( $_FILES['image']['tmp_name'] );
    // Экранируем специальные символы в содержимом файла
    $image = mysql_escape_string( $image );
    // Формируем запрос на добавление файла в базу данных
    $query="INSERT INTO `images` VALUES(NULL, '".$image."')";
    // После чего остается только выполнить данный запрос к базе данных
    mysql_query( $query );
    }
    }
    }
    ?>

    Извлечь сохраненный файл изображения можно следующим образом (файл image.php):

    if ( isset( $_GET['id'] ) ) {
    // Здесь $id номер изображения
    $id = (int)$_GET['id'];
    if ( $id > 0 ) {
    $query = "SELECT `content` FROM `images` WHERE `id`=".$id;
    // Выполняем запрос и получаем файл
    $res = mysql_query($query);
    if ( mysql_num_rows( $res ) == 1 ) {
    $image = mysql_fetch_array($res);
    // Отсылаем браузеру заголовок, сообщающий о том, что сейчас будет передаваться файл изображения
    header("Content-type: image/*");
    // И  передаем сам файл
    echo $image['content'];
    }
    }
    }
    ?>

    Чтобы вывести изображение в HTML-документе, делаем так:

    <img src="image.php?id=17" alt="" />

    И последнее: графические файлы иногда имеют довольно большой размер, убедитесь, что настройки сервера позволяют работать с таким объемом данных. В файле php.ini это директивы post_max_size — определяет максимальный объем данных передаваемых методом POST, и upload_max_filesize — определяет максимальный размер загружаемого файла. Так же проверьте, позволяют ли настройки MySQL обрабатывать запросы с большим объемом данных (директива max_allowed_packet файла my.ini).