Данную статью я хочу посвятить одному интересному нововведению в PHP 5.2 (с версии 5.3 входит в стандартную поставку PHP) — PHAR.
PHAR — это утилита для создания исполняемых архивов в PHP, аналог JAR в Java.
PHAR ползволяет упаковать много файлов в один, в результате чего Ваше приложение может работать с целой библиотекой, как с одним файлом.
PHAR умеет создавать, читать, записывать и конвертировать такие форматы, как TAR, ZIP и, собственно, PHAR.
Доступ к файлам в архиве осуществляется напрямую, без необходимости распаковки архива, через PHP Stream Wrapper, тоесть с файлами из архива работают все функции, которые поддерживают PHP Stream Wrapper.
Для того, чтобы работать с архивами PHAR Вам нужен PHP не ниже версии 5.2 с расширениями PHAR, zlib и bzip2 (если у Вас PHP 5.3, то PHAR уже установлен по умолчанию ).
Безопасность
По умолчанию, к PHAR архивам есть только доступ на чтение. При желании, можно установить phar.readonly = 0 в php.ini.
Кроме того, PHAR архивы могут исполняться только PHP интерпретатором
Создаем архив с текстовым файлом:
А теперь считываем его содержимое:
“Заглушка” — это файл, который читается первым при подключении PHAR-архива, это своего рода Bootstrap. Этот файл интерпретируется только в том случае, если архив подключен полностью. Если же скрипт использует только конкретные файлы из архива — файл-заглушка не интерпретируется.
Посмотрим пример:
При создании файла-заглушки используйте вызов __HALT_COMPILER() в конце файла.
Доступ к файлу-заглушке можно получить вызовом метода getStub(), как в примере:
Для установки файла-заглушки по умолчанию нужно использовать метод setDefaultStub():
ВАЖНО: установите phar.readonly = 0 в php.ini
Существует несколько способов записи содержимого:
Несколько примеров:
Как и с записью, существует несколько способов:
Сигнатура используется для проверки достоверности данных.
PHAR поддерживает четыре алгоритма для создания сигнатур:
Для установки сигнатуры следует использовать метод Phar::setSignatureAlgorithm(), который принимает два параметра:
Пример кода:
и для OpenSSL:
PHAR поддерживает чтение ZIP и TAR архивов. При этом чтение происходит так будто это обычный PHAR архив. Однако, следует помнить о том, что длина названия не должна превышать 255 байт, включая путь к файлу, а также, что для того, чтобы архив был исполняемым, он должен содержать в своем названии ‘.phar’ (например, habr.phar.gz)
Сжатие архивов производится одним из двух алгоритмов: gzip или bzip2.
Обратите внимание, что ZIP и TAR архивы могут быть созданы даже если phar.readonly = 1 в php.ini, но в таком случае не могут содержать файл-заглушку или ‘.phar’ в названии.
Конвертация форматов архива
Конвертацию архива можно проделать двумя способами:
1. Phar::ConvertToData(), который принимает три параметра: формат (Phar::TAR, Phar::ZIP), сжатие(Phar::NONE, Phar::GZ, Phar::BZ2) и расширение(.tar, .tar.bz2, .tar.gz, .zip).
2. Phar::ConvertToExecutable(), который принимает все те же параметры за исключением последнего — расширения. Тут доступно гораздо больше вариантов, которые все же основываются на форматах PHAR, ZIP или TAR соответственно: .phar, .phar.gz, .phar.bz2, .phar.tar, .phar.tar.gz, .phar.tar.bz2, .phar.zip
Как я уже написал выше — доступно два способа сжатия: Gzip и Bzip2, при этом сжимать можно как сам архив, так и файлы внутри него.
Для сжатия архива нужно использовать метод compress(), который принимает два параметра — тип сжатия и расширение файла:
Для сжатия файлов — compressFiles() с одним параметром — тип сжатия:
При использовании APC производительность PHAR вырастает до 6 раз.
Без кеширования — почти не отличается от варианта без использования PHAR.
И так, подведем итоги:
PHAR — это утилита для создания исполняемых архивов в PHP, аналог JAR в Java.
PHAR ползволяет упаковать много файлов в один, в результате чего Ваше приложение может работать с целой библиотекой, как с одним файлом.
PHAR умеет создавать, читать, записывать и конвертировать такие форматы, как TAR, ZIP и, собственно, PHAR.
Доступ к файлам в архиве осуществляется напрямую, без необходимости распаковки архива, через PHP Stream Wrapper, тоесть с файлами из архива работают все функции, которые поддерживают PHP Stream Wrapper.
Требования
Для того, чтобы работать с архивами PHAR Вам нужен PHP не ниже версии 5.2 с расширениями PHAR, zlib и bzip2 (если у Вас PHP 5.3, то PHAR уже установлен по умолчанию ).
Безопасность
По умолчанию, к PHAR архивам есть только доступ на чтение. При желании, можно установить phar.readonly = 0 в php.ini.
Кроме того, PHAR архивы могут исполняться только PHP интерпретатором
Пример
Создаем архив с текстовым файлом:
$phar = new Phar('test.phar');
$phar[hello_habr.txt] = 'Hello Habr!';
А теперь считываем его содержимое:
echo file_get_contents('phar://test.phar/hello_habr.txt');
Файл-заглушка
“Заглушка” — это файл, который читается первым при подключении PHAR-архива, это своего рода Bootstrap. Этот файл интерпретируется только в том случае, если архив подключен полностью. Если же скрипт использует только конкретные файлы из архива — файл-заглушка не интерпретируется.
Посмотрим пример:
//файл-заглушка будет прочитан
include_once(‘some_archive.phar’);
//файл-заглушка прочитан не будет
include_once(‘phar://some_archive.phar/somefile.php’);
При создании файла-заглушки используйте вызов __HALT_COMPILER() в конце файла.
Доступ к файлу-заглушке можно получить вызовом метода getStub(), как в примере:
$phar = new Phar(‘some_archive.phar’);
$stub = $phar->getStub();
Для установки файла-заглушки по умолчанию нужно использовать метод setDefaultStub():
$phar = new Phar(‘some_archive.phar’);
$phar->setDefaultStub('cli.php', 'web/index.php');
Создание содержимого архива
ВАЖНО: установите phar.readonly = 0 в php.ini
Существует несколько способов записи содержимого:
- через свойство объекта
- Phar::addFile()
- Phar::addFromString()
- Phar::addEmptyDir()
- Phar::buildFromDirectory()
- Phar::buildFromIterator()
Несколько примеров:
$phar = new Phar(‘habr.phar’);
$phar[‘index.php’] = file_get_contents(‘some/path/to/file.php’); // через свойство объекта в виде доступа к элементам массива (ArrayAccess)
$phar = new Phar(‘habr.phar’);
$phar->addFile(‘http://habrahabr.ru’, ‘HabrHomePage.html’);
$phar->addFromString(‘HabrHomePage’, file_get_contents(‘http://habrahabr.ru’));
$phar = new Phar(‘habr.phar’);
$phar->addEmptyDir(‘temporary/’);
$phar->buildFromDirectory(‘some_directory/’);
$phar = new Phar(‘habr’);
$dir = ‘somedir/’;
$phar->buildFromIterator(
new RecursiveDirectoryIterator($dir)
);
Чтение из архива
Как и с записью, существует несколько способов:
- PHAR stream wrapper (phar://)
- прямое подключение
- Phar::extractTo()
- Итерация по инстансу 'Phar'
Сигнатура PHAR архива
Сигнатура используется для проверки достоверности данных.
PHAR поддерживает четыре алгоритма для создания сигнатур:
- MD5
- SHA1
- SHA256
- SHA512
Для установки сигнатуры следует использовать метод Phar::setSignatureAlgorithm(), который принимает два параметра:
- Тип сигнатуры:
- Phar::MD5
- Phar::SHA1
- Phar::SHA256
- Phar::SHA512
- Phar::OPENSSL
- Приватный ключ — тоесть OpenSSL private key
Пример кода:
$phar=new Phar('habr.phar');
$phar->buildFromDirectory('habr/');
$signatures=Phar::getSupportedSignatures();
if (in_array(PHAR::SHA512,$signatures))
{
$phar->setSignatureAlgorithm(PHAR::SHA512);
}
elseif (in_array(PHAR::SHA256,$signatures))
{
$phar->setSignatureAlgorithm(PHAR::SHA256);
}
elseif (in_array(PHAR::SHA1,$signatures))
{
$phar->setSignatureAlgorithm(PHAR::SHA1);
}
elseif (in_array(PHAR::MD5,$signatures))
{
$phar->setSignatureAlgorithm(PHAR::MD5);
}
и для OpenSSL:
$phar=new Phar('habr.phar');
$phar->buildFromDirectory('habr/');
$OSSLPrivateKey=openssl_get_privatekey(file_get_contents('private.pem'));
$OSSLPKey='';
openssl_pkey_export($OSSLPrivateKey,$OSSLPKey);
$phar->setSignatureAlgorithm(Phar::OPENSSL,$OSSLPKey);
ZIP и TAR
PHAR поддерживает чтение ZIP и TAR архивов. При этом чтение происходит так будто это обычный PHAR архив. Однако, следует помнить о том, что длина названия не должна превышать 255 байт, включая путь к файлу, а также, что для того, чтобы архив был исполняемым, он должен содержать в своем названии ‘.phar’ (например, habr.phar.gz)
Сжатие архивов производится одним из двух алгоритмов: gzip или bzip2.
Обратите внимание, что ZIP и TAR архивы могут быть созданы даже если phar.readonly = 1 в php.ini, но в таком случае не могут содержать файл-заглушку или ‘.phar’ в названии.
Конвертация форматов архива
Конвертацию архива можно проделать двумя способами:
1. Phar::ConvertToData(), который принимает три параметра: формат (Phar::TAR, Phar::ZIP), сжатие(Phar::NONE, Phar::GZ, Phar::BZ2) и расширение(.tar, .tar.bz2, .tar.gz, .zip).
2. Phar::ConvertToExecutable(), который принимает все те же параметры за исключением последнего — расширения. Тут доступно гораздо больше вариантов, которые все же основываются на форматах PHAR, ZIP или TAR соответственно: .phar, .phar.gz, .phar.bz2, .phar.tar, .phar.tar.gz, .phar.tar.bz2, .phar.zip
Сжатие
Как я уже написал выше — доступно два способа сжатия: Gzip и Bzip2, при этом сжимать можно как сам архив, так и файлы внутри него.
Для сжатия архива нужно использовать метод compress(), который принимает два параметра — тип сжатия и расширение файла:
$phar=new Phar('habr.phar');
$phar->buildFromDirectory('habr/');
if (Phar::canCompress(Phar::GZ))
{
$phar->compress(Phar::GZ,'.phar.gz');
}
else if (Phar::canCompress(Phar::BZ2))
{
$phar->compress(Phar::BZ2,'.phar.bz2');
}
Для сжатия файлов — compressFiles() с одним параметром — тип сжатия:
$phar=new Phar('habr.phar');
$phar->buildFromDirectory('habr/');
if (Phar::canCompress(Phar::GZ))
{
$phar->compressFiles(Phar::GZ);
}
else if (Phar::canCompress(Phar::BZ2))
{
$phar->compressFiles(Phar::BZ2);
}
Производительность
При использовании APC производительность PHAR вырастает до 6 раз.
Без кеширования — почти не отличается от варианта без использования PHAR.
Итоги
И так, подведем итоги:
- PHAR легко устанавливается, а если точнее — он входит в стандартную поставку PHP 5.3.
- Его легко использовать.
- Легко разворачивать — всего один файл.
- Он хорошо защищен — сигнатуры, OpenSSL.
- Обладает высокой производительностью.