Pull to refresh

.phar — исполняемые PHP-архивы

Reading time4 min
Views53K
Данную статью я хочу посвятить одному интересному нововведению в PHP 5.2 (с версии 5.3 входит в стандартную поставку PHP) — PHAR.
image
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.
  • Обладает высокой производительностью.
Tags:
Hubs:
+119
Comments80

Articles