Статьи

Phar: библиотеки PHP включены в один файл

Phar — это расширение php, которое предоставляет средства для распространения кода в виде одного архива, который не нужно извлекать в папку перед использованием.

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

Phar доступен для PHP 5.3 и новее. В этой статье мы видим игрушечный пример использования Phar и реальный мир, в котором мы помещаем Doctrine 2 ORM в один файл.

Привет мир пример

В нашем игрушечном примере мы хотим упаковать этот файл как Phar ( hello.php ):

<?php
echo "Hello, world of Phar!\n";

Реальное приложение будет состоять из нескольких файлов и папок, но цель этого первого примера — просто научиться работать с оборудованием.

Упаковка Phar происходит с помощью PHP-кода, который мы можем поместить в скрипт сборки ( package.php ):

#!/usr/bin/env php
<?php
$archive = new Phar('hello.phar', 0, 'hello.phar');
$archive->setStub('<?php
    Phar::mapPhar();
    include "hello.php";
    __HALT_COMPILER();
');
$archive['hello.php'] = file_get_contents('hello.php');
// use also $archive->buildFromDirectory(); $archive->buildFromIterator();

hello.phar — это (соответственно) путь и имя созданного архива.

Заглушка, которую мы установили как PHP-код, — это то, что будет выполняться, когда Phar будет доступен из внешнего кода; он всегда должен начинаться с Phar :: mapPhar () и всегда заканчиваться на __HALT_COMPILER (). Однако в середине заглушки мы можем делать то, что хотим, от включения файлов до настройки автозагрузки или выполнения кода.

Теперь давайте выполним наш скрипт сборки и используем новый Phar:

[10:52:02][giorgio@Desmond:~/phar_example]$ php build.php
[10:52:03][giorgio@Desmond:~/phar_example]$ php hello.phar
Hello, world of Phar!

Теперь наше приложение может распространяться как один файл, например, по HTTP, не беспокоясь о распаковке или правах доступа к файлу.

Практическое использование: Учение 2

Этот более практичный пример использует Phar для реального кода, состоящего из ORM Doctrine 2. В настоящее время он упакован как tarball, который перед использованием должен быть распакован; однако большая часть механизма заключается в настройке автозагрузки для различных папок внутри пакета, Doctrine / и Symfony /. Последняя папка также необъяснимо помещается в Doctrine / one, нарушая соглашение PSR-0 (так как она содержит классы Symfony \ …).

Давайте получим пакет tarball и развернем его в папку:

wget http://www.doctrine-project.org/downloads/DoctrineORM-2.1.1-full.tar.gz
tar xvzf DoctrineORM-2.1.1-full.tar.gz 

Теперь мы можем написать скрипт сборки phar-package.php:

<?php
$archive = new Phar('doctrine-2.1.1.phar', 0, 'doctrine-2.1.1.phar');
$archive->buildFromDirectory('doctrine-orm', '/Doctrine\/(Common|DBAL|ORM)/');
$archive->buildFromDirectory('doctrine-orm/Doctrine', '/Symfony/');
$archive->setStub(file_get_contents('phar-bootstrap.php'));

Этот скрипт будет включать код из заглушки для выполнения при включении Phar-phar-bootstrap.php:

<?php
Phar::mapPhar();

$basePath = 'phar://' . __FILE__ . '/';
require $basePath . 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', $basePath);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', $basePath);
$classLoader->register();

__HALT_COMPILER();

Пример использования Doctrine 2 в качестве Phar намного проще, чем настройка автозагрузки:

<?php
include_once 'doctrine-2.1.1.phar';
var_dump(class_exists('Doctrine\ORM\EntityManager', true));
var_dump(class_exists('Symfony\Component\Console\Application', true));

Я поместил сценарии на Github для вашего удобства. Я последовал примеру упаковочного кода Эрика Клеммонса для доктрин-миграций .

Хочу больше?

Phar не ограничивается архивированием файлов. Он предлагает больше функций, таких как сжатие на основе формата zip или хэширование архива с MD5 или SHA1 с автоматической проверкой.

Поскольку упакованный в Phar код работает из архива, он не может легко создавать временные файлы, что усложняет использование этого метода для приложений. Это также требует другого способа доступа к файлам для чтения и выполнения, вставляя перед ними префикс phar: //archive.phar /.

Однако мне кажется, что это действительно практичный способ распространения библиотек или утилит командной строки, которые можно просто загрузить и включить без проблем, связанных с include_path или автозагрузкой. Фактически, установщик PEAR2 распространяется как Phar.