Как сделать zip файл из phar

Обновлено: 06.07.2024

Этот метод используется для конвертирования phar-архив в tar- или zip-файл. Чтобы создать сделать tar или zip неисполняемым, из создаваемого в результате конвертации архива удаляются загрушка и псевдоним phar-архива.

Если не были указаны никакие изменения, то данный метод выбросит исключение BadMethodCallException, если форматом файла архива является phar. В случае использования с архивами в формате tar или zip, данный метод конвертирует архив в неисполняемый архив.

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

Список параметров

Значением этого параметра должна быть одна из констант: Phar::TAR или Phar::ZIP . Если значение установлено в null , то существующий формат файла будет сохранен.

Значением этого параметра должна быть одна из констант: Phar::NONE для отсутствия сжатия всего архива, Phar::GZ для сжатия, основанного на zlib, или Phar::BZ2 для bzip-сжатия.

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

В случае конвертации phar-архива, основанного на tar, расширениями по умолчанию являются: .tar , .tar.gz и .tar.bz2 , в зависимости от указанного сжатия. Для архивов, основанных на zip, расширением по умолчанию является .zip .

Возвращаемые значения

Данный метод возвращает объект PharData в случае успеха и выбрасывает исключение в случае неудачи.

Ошибки

Данный метод выбрасывает исключение BadMethodCallException в следующих случаях: при невозможности сжатия; если был передан неизвестный алгоритм сжатия; в запрошенном архиве была включена буферизация с помощью Phar::startBuffering() и не была завершена с помощью Phar::stopBuffering() . В случае возникновения каких-либо проблем в процессе создания phar будет выброшено исключение PharException.

Примеры

image

Данную статью я хочу посвятить одному интересному нововведению в 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::addFile()
  • Phar::addFromString()
  • Phar::addEmptyDir()
  • Phar::buildFromDirectory()
  • Phar::buildFromIterator()

Чтение из архива

  • PHAR stream wrapper (phar://)
  • прямое подключение
  • Phar::extractTo()
  • Итерация по инстансу 'Phar'

Сигнатура PHAR архива

  • MD5
  • SHA1
  • SHA256
  • SHA512
  • Тип сигнатуры:
    • Phar::MD5
    • Phar::SHA1
    • Phar::SHA256
    • Phar::SHA512
    • Phar::OPENSSL

    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(), который принимает два параметра — тип сжатия и расширение файла:


    Для сжатия файлов — compressFiles() с одним параметром — тип сжатия:

    Производительность

    При использовании APC производительность PHAR вырастает до 6 раз.
    Без кеширования — почти не отличается от варианта без использования PHAR.

    Сегодня мы познакомимся с понятием phar архивов, и их использовании в PHP. Зачем они нужны? Если вы пишите PHP приложение, которое направлено на развитие, то вы обязательно столкнетесь с такой проблемой. У вас будут происходить накопления PHP файлов, которые некуда будет девать. Предположим, тысяча или несколько тысяч файлов, которые занимают место. К тому же такое количество файлов, очень сложно загружать на хостинг, по FTP. Выходом из данной ситуации, будет использование phar архивов.

    Сегодня мы узнаем

    Что такое Phar?

    Доступ к исходным файлам архива осуществляется напрямую, без распаковки архива. Прямой доступ обеспечивает PHP Stream Wrapper. Другими словами с файлами архива работают функции поддерживаемые PHP Stream Wrapper.

    Требования к PHP версии

    Расширение phar, доступно с версии PHP 5.2. А с версии 5.3 – это неотъемлемая часть PHP. Для начала, советую вам проверить версию PHP. Если версия ниже, меняйте. Если версия PHP не ниже 5.2 – вам необходимо переустановить PHP ядро с Phar, Zlib и bzip2 расширениями. Если у вас версия 5.3 – все отлично, phar установлен по умолчанию.

    Если хотите, можете настроить защиту для ваших phar архивов, и сделать их доступными, только для чтения. Для этого, нужно установить настройку в файле php.ini. Установите следующий параметр phar.readonly = 0.

    Преимущества Phar в PHP

    PHAR легко устанавливается, а если точнее — он входит в стандартную поставку PHP 5.3.

    Удобно при копировании файлов на другой хост.

    Легко разворачивать — всего один файл.

    Высокая степень защиты PHP приложения — сигнатуры, OpenSSL.

    Обладает высокой производительностью.

    Работа с Phar в PHP

    В этом разделе, мы будем работать с утилитой. А точнее, будем создавать и использовать собственные библиотеки файлов PHP приложения. Вы увидите, насколько просто и удобно использовать phar библиотеки.

    Пример Hello World

    Для начала создадим простой архив, с текстовым файлом:

    А теперь, прочитаем его:

    Создание и использование библиотек Phar

    В этом разделе, мы научимся создавать собственные phar библиотеки и использовать их в нужных целях. Для начала напишем 2 класса, которые нам пригодятся:

    classes/SampleClass.php

    classes/SampleClass2.php

    Очень просто, неправда ли? Теперь создадим в этой же папке файл, который будет подключать оба класса.

    classes/index.php

    Теперь создайте папку lib, которая будет использоваться для phar библиотек. И создадим главный PHP файл, который будет компилировать phar архивы, и будет демонстрировать работоспособность библиотек.

    index.php

    Результат выполнения нашего скрипта предоставлен на скриншоте ниже:

    Пример работы Phar

    В начале, проверяем, существует ли наша библиотека (lib/SampleLibrary.phar). Если существует – нам не нужно компилировать ее снова. Если нет – мы автоматически компилируем и пакуем нашу библиотеку.

    Для начала проверяем читаемость phar архива с помощью функции ini_set. Далее, указываем имя и будущее местонахождение архива, для phar конструктора. С помощью setDefaultStub, указываем главный файл в библиотеке, который будет подключать все классы библиотеки. С помощью функции buildFromDirectory, собственно произошло компилирование библиотеки. Функция compress сжала библиотеку в формат GZIP.

    Обращение к библиотеке происходит с помощью phar://. Это синтаксис PHP stream wrapper.

    Добавление файлов в библиотеку Phar

    Добавить файл в библиотеку, можно с помощью разных функций:

    Смотрите несколько примеров добавления файлов в архив:

    Чтение phar архива

    Как в случае с добавлением файлов, чтение phar архива, можно провести несколькими способами:

    PHP stream wrapper (phar://)

    Итерация по инстансу 'Phar'

    Сжатие Phar архива

    Сжатие phar архивов, можно провести с использованием двух функций compress() и compressFiles(). Функция compress(), принимает два параметра, это имя файла и тип сжатия. Функция compressFiles(), принимает только один параметр – тип сжатия.

    Рассмотрим пример использования функции compress():

    Также рассмотрим пример сжатия phar архива с помощью compressFiles():

    Конвертация форматов архива

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

    Phar::ConvertToData()

    Принимает три параметра:

    Формат - Phar::TAR, Phar::ZIP

    Сжатие - Phar::NONE, Phar::GZ, Phar::BZ2

    Расширение - .tar, .tar.bz2, .tar.gz, .zip

    Другой вариант, используя функцию Phar::ConvertToExecutable(), которая принимает все тоже, что и предыдущая, за исключением последнего параметра (расширения).

    Сигнатура (защита) phar архивов

    Сигнатура phar библиотек, используется для защиты архивов. А если говорить точнее, для проверки достоверности данных. PHAR поддерживает несколько алгоритмов создания сигнатур:

    При установки сигнатуры phar архива, используют метод Phar::setSignatureAlgorithm(), который принимает два параметра: тип сигнатуры, приватный ключ. Причем, типы сигнатуры в функции, указываются следующим образом:

    Для большей ясности смотрите примеры установки сигнатуры на phar архив:

    Чтение других архивов

    Также phar поддерживает чтение других архивов: ZIP и TAR. Архивы читаются, так как и phar архивы. При этом, длинна названия архива не должна превышать 255 байт, включая путь файла, и то, что в своем названии он должен иметь слово .phar. Например: sitear.phar.gz.

    Заключение

    Использование phar в программировании на PHP, очень удобно и полезно. Это экономит ваше дисковое пространство, защищает код, улучшает производительность и многое другое при создании больших PHP приложений.

    Если у вас есть предложения или вопросы по использованию Phar в PHP, выскажите их в комментариях!

    Развертывание веб-приложений может быть сложным и громоздким, если у вас нет правильных инструментов. Если вам когда-либо прежде приходилось разворачивать Java приложения, то вы вероятно имеете представление о JAR-файлах (означает "Java Archive"). Все исполняемые и дополнительные файлы приложения могут быть объединены в один файл JAR, что бывает очень удобно, когда приходит время развертывания приложений.

    Файлы Phar ("Php Archive") аналогичны концепции JAR файлов, но для PHP. Если у вас есть PHP 5.3 или выше, расширение Phar встроено и включено; вы можете начать использовать его без каких-либо дополнительных требований.

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

    PHP Phar: Упаковка php приложения с помощью Phar

    Прототипом данной статьи является эта англоязычная статья: Packaging Your Apps with Phar

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

    Через php.ini - файл

    Откройте php.ini, найдите директиву phar.readonly, и изменить её значение на phar.readonly = 0

    При запуске php интерпретатора

    Когда будете запускать скрипт создания Phar файла то интерпретатору PHP можно передать опцию:

    Итак, давайте уже чего-нибудь упакуем.

    PHP Phar: Ваш первый Phar архив

    Начнем с создания структуры каталогов приложения; создайте где-нибудь в вашей системе, следующую структуру:

    Структура каталогов приложения для примера использования Phar

    Каталог build Будет содержать вновь созданный архив PHAR, чтобы избежать засорения каталога исходников сгенерированными артефактами. Каталог src Будет содержать исходные файлы приложения. Файл index.php Будет служить в качестве точки входа приложения. Файл common.php Будет служить в качестве псевдо-библиотеки общих классов, используемых приложением. Файл config.php Будет служить в качестве конфигурационного файла приложения.

    Содержимое index.php выглядит следующим образом:

    Содержимое common.php выглядит следующим образом :

    А содержимое config.ini выглядит следующим образом:

    PHP Phar: Создание Phar архива

    Помимо, структуры приложения, необходимо также написать сценарий для создания архива Phar. Создайте еще один PHP - файл create-phar.php прямо в директории myapp с таким содержимым:

    ** если неправильно определить путь, в статье оригинале, кстати, указано так:
    $srcRoot = "

    /myapp/build";
    и у меня это не заработало, то вполне реально при запуске получить следующую ошибку:
    Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Cannot create phar '/myapp/build/myapp.phar', file extension (or combination) not recognised or the directory does not exist' in /. /myapp/create-phar.php:11

    Phar так же поддерживает компрессию содержимого (необходимо, что бы было установлено соответсвующее расширение)

    Затем откройте окно терминала, перейдите в каталог myapp и запустите его:

    Или, если вы не стали прописывать phar.readonly=0 в php.ini то можно как было сказано выше вызвать так:

    После запуска сценария, вы должны найти архив myapp.phar в каталоге build вместе с копией config.ini файла. Скопируйте эти два файла в корневую директории вашего веб - сервера (например htdocs).

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

    Создайте скрипт запуска назовите его например run.php в корневой директории вашего веб - сервера со следующим содержимым:

    Код по сути ничего не делает, но избавляет вас от перенастройки вашего сервера для обработки PHAR файлов напрямую. Если вы размещаете свое приложение на shared - хостинге и не имеете доступа к конфигурации вашего сервера, то это идеальное решение ;)

    После создания скрипта запуска, корень вашего веб-приложения может выглядеть следующим образом:

    Пример файловой структуры корня веб-приложения использующего Phar

    Укажите в браузере путь к run.php сценарию, и вы должны увидеть следующий вывод:

    Пример вывода веб-приложения использующего Phar

    PHP Phar: Под капотом

    Давайте внимательнее посмотрим на код create-phar.php, чтобы разобраться что все это значит. Взглянем на следующую строку из него:

    Здесь создается новый Phar объект, конструктор которого обычно принимает три аргумента. Первый аргумент это путь, куда сохранить созданный файл. Вы можете не только создавать новые архивы, но и манипулировать существующими.

    Вторым аргументом является флаг, который указывает, как Phar объект будет обрабатывать файлы. Phar объект является подклассом PHP класса RecursiveDirectoryIterator , и этот аргумент просто передается в родительский класс. Аргументы которые я предоставил вообще-то и так передаются ему по умолчанию, но для примера я предоставил их явно.

    Третий аргумент - это псевдоним архива, который необходимо будет использовать в скриптах внутри архива, при подключении других файлов внутри этого же архива, с помощью обертки потока phar. Другими словами, все файлы внутри архива, которые требуют другие файлы из архива, должны ссылаться на него в явном виде с помощью обертки потока и псевдонима. Например, вот код из index.php приведенный ранее, который подключает внутри себя файла common.php:

    Напоминаю, мы рассматриваем код файла create-phar.php ;) После того, как объект создан, далее по коду в архив добавляются файлы index.php и common.php

    Т.к. класс Phar реализует ко всему прочему PHP интерфейс ArrayAccess мы можем работать с Phar объектом так же как и с ассоциативным массивом, указав в качестве ключей имена файлов, а в качестве значений необходимо предоставить содержимое файлов. Это можно сделать с помощью file_get_contents(). Вы можете добавить столько файлов, сколько вам необходимо, но если вам нужно добавить много файлов, или нужно добавить все файлы некоего каталога, то вы можете рассмотреть более удобный метод buildFromDirectory() Который позволяет построить архив Phar из файлов в указанной директории:

    Первый аргумент buildFromDirectory() это путь к нужному каталогу, а второй (необязательный) - регулярное выражение, определяющее, какие файлы каталога включить. Для того, чтобы включить все файлы в каталоге, просто пропустите второй аргумент.

    Далее (в коде create-phar.php) вызывается метод setStub(), чтобы создать файл заглушку. Но я бы его назвал файл-загрузчик (прим. переводчика) Файл-загрузчик говорит архиву, что делать, когда его загрузили компилятором.

    И, в последней строке create-phar.php: config.ini просто копируется из src-каталога в build-каталог рядом с Phar архивом.

    PHP Phar: Файл-загрузчик

    При запуске архива Phar, Файл-загрузчик внутри рассматривается как мета - файл, чтобы инициализировать архив и сообщить ему, что делать, когда его вызывают, не обращаясь к конкретному файлу внутри архива. В примере выше, я предоставил создание Файл-загрузчик Phar объекту при помощи метода createDefaultStub(), который создает Файл-загрузчик по умолчанию, содержащий следующий код:

    Прим. переводчика: на самом деле у меня под PHP 5.6.2 файл-загрузчик по-умолчанию выглядит совсем иначе, и имеет гораздо более объемное содержимое, но это не важно. Важно понимать для чего создается этот файл и в каких случаях он срабатывает.

    При обращении к архиву таким образом файл-загрузчик сработает:

    При обращении к конкретному файлу архива файл-загрузчик НЕ сработает:

    Данный файл полезен тем, что внутри него можно размещать некоторый пользовательский код, который будет выполняться при обращении к архиву, а так же в данном файле можно разместить свой собственный авто-загрузчик, если того потребует ваше приложение. Например так как ниже (взял пример из PSR-4)

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

    PHP Phar: Пояснения по-поводу загрузчика и Phar::mapPhar()

    После недолгого выяснения я узнал что, статичный метод Phar::mapPhar() предназначен для вызова только внутри файла-загрузчика! Данный метод загружает в память интерпретатора мета-информацию об архиве, например, то какие файлы и где он содержит. Без этой информации интерпретатор PHP не сможет работать с архивом - у него не будет инфы, о том какие файлы и где лежат в архиве. Поэтому Phar::mapPhar() - должен быть вызван в загрузчике, прежде чем мы попытаемся подключить какой либо конкретный файл архива! Я бы вообще назвал его не Phar::mapPhar(), а Phar::setup(), или Phar::init()! Но с названиями там похоже везде проблемы :D .

    Да, еще! Файл загрузчика физически располагается в самом начале архива (архив .phar можно попытаться открыть любым текстовым редактором и убедиться в этом). Далее в файле архива следуют данные самого архива, и файлов в нем содержащиеся, вот тут становиться очевидным требование вызова в конце файла-загрузчика директивы __HALT_COMPILER(); т.к. сразу после файла-загрузчика идут данные архива в собственном формате, которые обрушат интерпретатор, если он попытается их интерпретировать. Поэтому, после того, как интерпретатор прочитает данные файла-загрузчика, дальше ему ходить не нужно - "снег в башка попадет. " © ! Вот поэтому мы и "гасим" его директивой __HALT_COMPILER() которая останавливает работу компилятора в точке, где она расположена.

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

    Если вы разрабатываете библиотеку классов или другой "includable" код, то размещение его в архиве PHAR является отличным решением, облегчающим его использование в разных проектах. Расширение Phar было сильно оптимизировано, чтобы дать такую ​​же, если не лучше производительность, чем обычный доступ к файлам, так что, скорее всего, вы не ухудшите производительность ваших приложений, используя его.

    Для того, чтобы эффективно использовать Phar, вы должны знать, что есть некоторые ограничения. Вот несколько советов, которые помогут вам лучше понять Phar и получить максимальную отдачу от него:

    • Вы можете упаковать все приложение в Phar, но это не является решением вопроса автоматического развертывания. Это всего лишь организация единой точки входа для приложения.
    • Вы можете выполнять функции автоматического развертывания вручную внутри архива, ради большей стабильности приложения, такие, как создание кэша и загрузка каталогов на сервер, создание общих файлов конфигурации, и т.д.
    • Вы должны избегать записи в файлы Phar в реальных приложениях. Вместо этого поместите все записываемые файлы вне архива. Запись в Phar отключена в стандартной установке PHP, потому что это небезопасно для вашего приложения.

    PHP Phar: Резюме

    Phar может сэкономить много времени при упаковке и развертывании приложений и я рекомендую вам рассмотреть возможность использования его. Эта статья была призвана познакомить вас с основными понятиями Phar. Вы видели, как создать архив и включать в него файлы, узнали немного о важности файл загрузчика, и как PHP может получить доступ к файлам внутри архива. К сожалению, документация для работы с Phar в PHP руководстве, достаточно скудная, да и в интернете про него не особо пишут. Надеюсь, в будущих статьях я еще напишу про Phar.

    Идея архивов Phar заимствована из технологии Java™ с ее архивами JAR, которые позволяют упаковать приложение в один файл, где есть все необходимое для работы этого приложения. Она отличается от концепции единственного исполняемого файла, который обычно создается такими языками программирования, как С, так как это не скомпилированное приложение, а просто архив. Так что файл JAR на самом деле содержит файлы, составляющие приложение, хотя по причинам безопасности они могут быть скрыты. Расширение Phar основано на аналогичной концепции, но больше ориентировано на веб-среду РНР. Кроме того, в отличие от JAR, архивы Phar могут обрабатываться самим РНР и не требуют внешнего инструмента для своего создания или использования.

    Создание Phar

    Для создания файла Phar нужно выполнить несколько шагов. Все они требуют исполнения команд РНР в той или иной форме, так как самостоятельных инструментов для создания таких архивов не существует. Кроме того, чтобы создать и модифицировать файлы Phar, нужно установить в 0 параметр php.ini phar.readonly. Для открытия или вызова файлов внутри архива Phar в РНР этого не требуется.

    Рассмотрим шаги, необходимые для создания архива Phar, который можно использовать для исполнения приложения. Это приложение должно загружаться прямо из веб-браузера или из командной строки. Первым шагом будет создание файла Phar. Сделаем это, создав объект Phar , с которым мы будем работать в данном примере (листинг 1). Обращение к этому объекту позволит нам управлять всеми аспектами архива Phar.
    Листинг 1. Создание объекта Phar

    Первый параметр конструктора – это путь, по которому должен быть сохранен файл Phar. Второй параметр передает любые параметры в родительский класс RecursiveDirectoryIterator . Третий параметр — это псевдоним, по которому происходит обращение к этому архиву Phar в контексте потоков (streams). Так, возвращаясь к листингу 1, к файлу из этого архива Phar можно обращаться также как к phar://my.phar . Еще можно сделать вызов метода Phar::startBuffering() , чтобы сохранить в буфере изменения, произошедшие в архиве до подачи команды Phar::stopBuffering() . Это не обязательно, но таким способом можно ускорить процесс создания или модификации архива, так как не нужно будет сохранять изменения всякий раз при редактировании сценария.

    По умолчанию созданный архив Phar будет использовать собственный формат архива Phar. Но можно использовать и формат ZIP или TAR, преобразовав файл Phar в этот формат. В листинге 2 показано изменение формата на ZIP.
    Листинг 2. Изменение формата хранения на ZIP

    Изменение формата архива имеет свои преимущества и недостатки. Главное преимущество заключается в том, что содержимое архива можно просматривать при помощи любого инструмента для работы с файлами ZIP или TAR. Однако при использовании архива Phar в форматах ZIP или TAR требуется расширение Phar, а при использовании архива Phar в собственном формате Phar можно обойтись без его загрузки.

    Теперь нужно определить загрузчик файла, то есть первый код, вызываемый при загрузке файла Phar.

    Загрузчик файла Phar

    Загрузчик (stub) Phar-файла — это просто небольшой сегмент кода, который исполняется сразу после загрузки файла Phar. Он всегда оканчивается признаком __HALT_COMPILER() . Пример типичного загрузчика файла приведен в листинге 3.
    Листинг 3. Загрузчик файла Phar

    Обращение к методу Phar::mapPhar() инициализирует архив Phar путем считывания manifest-файла. Это нужно сделать до ссылки на внутренние файлы архива посредством оболочки (stream wrapper) phar://. Первым будет загружаться тот файл, который данное приложение обычно загружает первым; в данном случае: index.php.

    Способ добавления загрузчика в архив Phar зависит от используемого формата архива. Для архивов формата Phar применяется метод Phar::setStub() , который принимает один параметр кода РНР для помещения в загрузчик в виде строки. Этот подход иллюстрируется в листинге 4.
    Листинг 4. Использование Phar::setStub() для создания загрузчика файла

    Если вы не планируете ничего делать в загрузчике, кроме переадресации на страницу index.php, для его создания можно использовать метод helper Phar::createDefaultStub() . Для этого достаточно просто передать имя файла, которое нужно включить в загрузчик файла. В листинге 5 вызов метода Phar::setStub() переписан с применением этого метода.
    Листинг 5. Использование Phar::createDefaultStub() для создания загрузчика файла

    Второй необязательный аргумент метода Phar::createDefaultStub() позволяет включить другой файл, если Phar загружается из веб-сервера. Это удобно, когда приложение должно работать и в командной строке, и в контексте веб-браузера.

    В реализациях на базе ZIP и TAR содержимое загрузчика хранится в файле.phar/stub.php, и команда setStub() не используется.

    Добавление файлов в архив

    Объект Phar использует объект SPL ArrayAccess , позволяющий обращаться к содержимому архива как к массиву. Это открывает массу возможностей для добавления файлов в архив. Простейший способ — прямое использование интерфейса ArrayAccess .
    Листинг 6. Добавление файлов в архив

    Из листинга 6 видно, что имя файла определяется как ключ массива, а содержание — как его значение. Чтобы извлечь содержимое существующего файла для использования в качестве значения, можно прибегнуть к функции file_get_contents() . Это обеспечивает некоторую гибкость при добавлении файлов в архив, позволяя ссылаться на существующий файл или создавать файл динамически. Последнее удобно в сценариях сборки приложения.

    Если в архиве Phar нужно сохранить крупный файл, его можно сжать при помощи gzip или bzip2 соответственно с применением методов PharFileInfo::setCompressedGZ() или PharFileInfo::setCompressedBZIP2() . В листинге 7 производится сжатие файла при помощи bzip2.
    Листинг 7. Сжатие файла в архиве Phar при помощи bzip2

    Чтобы сжать файл или динамически использовать архив со сжатым файлом, нужно, чтобы при установке PHP было разрешено расширение bzip2 или zlib (для файлов, сжимаемых посредством gz).

    Предположим, что в архив нужно добавить много файлов. Добавление их один за другим при помощи интерфейса ArrayAccess может оказаться утомительным делом, но есть несколько способов сократить этот путь. Один из них — применение метода Phar::buildFromDirectory() , который просматривает определенный каталог и добавляет все находящиеся в нем файлы. Он поддерживает также фильтрацию файлов путем добавления второго параметра с шаблоном в виде регулярного выражения для отбора файлов и добавления их в архив (листинг 8).
    Листинг 8. Добавление файлов в архив при помощи Phar::buildFromDirectory()

    В листинге 8 в архив Phar добавляются все файлы РНР из заданного каталога. Затем, если надо внести в добавленные файлы какие-то изменения, например, сжать их, можно еще раз пройти по архиву при помощи интерфейса ArrayAccess .

    Кроме того, можно использовать метод Phar::buildFromIterator() , позволяющий добавить файлы при помощи итератора. Поддерживаются итераторы двух типов: те что отображают имя файла, находящегося внутри Phar, на имя файла на диске и те, что возвращают объекты SplFileInfo . Одним из таких совместимых итераторов является RecursiveDirectoryIterator , который используется в листинге 9 для добавления в архив файлов из каталога.
    Листинг 9. Добавление файлов в архив при помощи Phar::buildFromIterator()

    Метод Phar::buildFromIterator() принимает в качестве единственного аргумента сам объект итератора. В приведенном выше примере объект RecursiveDirectoryIterator упакован в объект RecursiveIteratorIterator , причем последний представляет собой совместимый тип итератора, который требуется методу Phar::buildFromIterator() .

    Итак, мы создали архив Phar, который можно применять в любом приложении РНР. Теперь посмотрим, как использовать этот архив.

    Работа с архивами Phar

    Достоинство архивов Phar состоит в том, что их можно легко интегрировать в приложение, особенно при использовании собственного формата архива на базе Phar. В этом случае даже не нужно устанавливать расширение Phar, так как РНР сам умеет загружать такие файлы и извлекать их содержимое. Для загрузки ZIP- и TAR-архивов требуется расширение Phar.

    Архивы Phar можно включать в приложение как любой другой файл РНР, что делает их использование предельно простым для разработчиков, которые уже знают, как включить в приложение чужой код. Продемонстрируем, как легко интегрировать Phar в приложениt

    Интеграция кода из архива Phar в приложение

    Простейший способ интегрировать код из архива Phar – просто включить в него этот архив, а затем ввести в архив файл, который нужно использовать. Для доступа к файлу внутри загруженного архива Phar можно использовать stream-оболочку phar:// (листинг 10).
    Листинг 10. Загрузка кода из архива Phar

    Первый оператор include загружает архив myphar.phar, включая код, указанный в загрузчике файла. Второй с помощью stream-оболочки открывает архив Phar и включает в архив только указанный файл. Заметим, что, как видно из листинга 10, для включения файла, находящегося в архиве, не обязательно применять include к самому архиву Phar.

    Исполнение РНР-приложения из архива Phar

    1. Любые файлы, которые могут понадобиться для отдельного экземпляра приложения, такие как файлы config, не должны входить в состав архива, так что их нужно записать в отдельное, но доступное место. То же относится к любым кэш-файлам, создаваемым приложением в рамках расширения.
    2. Для максимальной переносимости следует придерживаться формата архива на базе Phar без сжатия файлов в архиве. ZIP- и TAR-архивы требуют установки в РНР расширения Phar, тогда как Phar-архивы можно использовать, не задавая расширение Phar.
    3. Любые ссылки на файлы внутри приложения следует заменить с использованием stream-оболочки phar:// с именем архива, как показано в предыдущем разделе.

    Одно из популярных РНР-приложений, упакованных в Phar для иллюстрации того, как легко работать с архивами Phar, — PHPMyAdmin (см. Ресурсы). Оно целиком разработано для исполнения из файла архива Phar, однако позволяет хранить свой файл конфигурации вне архива Phar.

    Заключение

    Архивы Phar — весьма полезное дополнение к PHP V5.3. Они позволяют упаковать код РНР, что удобно для распространения приложений или библиотек в одном файле. Архив Phar можно легко загрузить из файла РНР при помощи функции require или include, либо выполнить прямо из браузера или командной строки, указав имя архива Phar.

    Спасибо!

    Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:

    Читайте также: