Here is an apache2 htaccess example that prevents the downloading of phar-Archives by the user:
RewriteEngine on
RewriteRule ^(.*)\.phar$ - [F]
It triggers a "403 - Forbidden" message instead of delivering the archive.Модуль Phar предоставляет способ поместить целое PHP-приложение в один-единственный файл, который называется "phar" — PHP Archive для простоты распространения и установки. Модуль Phar также предоставляет метод абстракции формата файла для создания и обработки tar- и zip-архивов через класс PharData, примерно как модуль PDO предоставляет единый интерфейс для доступа к различным базам данных. В отличие от PDO, который не умеет переносить данные между разными базами данных, Phar конвертирует данные между форматами tar, zip и phar одной строкой кода; пример конвертации содержится в описании метода Phar::convertToExecutable().
Что же такое phar? Phar-архивы — удобный способ группировки набора файлов в один. Phar-архив также предоставляет способ распространения целого PHP-приложения в одном-единственном файле и запуска приложения прямо из архивного файла без распаковки на диск. Кроме того, phar-архивы выполняются PHP с той же лёгкостью, что и другие файлы, из командной строки и через веб-сервер. Phar — что-то вроде флеш-накопителя для PHP-приложений.
Phar реализует функциональность через потоки. В стандартном сценарии внешний файл подключают внутрь PHP-скрипта языковой конструкцией include:
Пример #1 Подключение внешнего файла
<?php
include '/path/to/external/file.php';
Для доступа к локальному файлу /path/to/external/file.php
PHP преобразовывает путь в обёртку потока file:///path/to/external/file.php
и за кулисами вызывает стандартные функции
для работы с файловой обёрткой потока.
Файл file.php из phar-архива
/path/to/myphar.phar подключается синтаксисом
наподобие file://.
Пример #2 Подключение файла изнутри phar-архива
<?php
include 'phar:///path/to/myphar.phar/file.php';На практике с phar-архивом работают как с внешним диском через fopen()-подобные функции, функцию opendir() и mkdir()-подобные функции для чтения, изменения или создания новых файлов и директорий внутри phar-архива. Поддержка стандартных функций разрешает целому PHP-приложению распространяться в едином файле и запускаться из одного файла.
Главное назначение phar-архива — распространение целого приложения в одном файле. Установщик PEAR, который поставляется вместе с PHP, распространяется в виде phar-архива. Для работы с архивом phar, который распространяется как единый файл, архивный файл выполняется в командной строке или на веб-сервере.
Phar-архивы распространяются как tar- и zip-архивы,
или как пользовательский формат файла phar, который разработали
для модуля Phar. Каждый формат файла включает преимущества и недостатки. Файлы в форматах
tar и zip считываются или извлекаются сторонними утилитами, которые умеют работать
с такими форматами, но для запуска из PHP требуют установки модуля Phar.
Файловый формат phar специфичен и уникален для модуля Phar, и создаётся только модулем
или PEAR-пакетом » PHP_Archive,
но даёт преимущество: приложения в формате phar запускаются даже без включения модуля Phar.
Другими словами, phar-архив получится выполнить или подключить, даже если модуль Phar отключён. Доступ к отдельным файлам в архиве поддерживается только с модулем Phar, если только архив не создали через пакет PHP_Archive.
Модуль Phar также поддерживает преобразование tar-файлов в формат zip или phar одной командой:
Пример #3 Конвертирование phar-архива из формата phar в tar
<?php
$phar = new Phar('myphar.phar');
$pgz = $phar->convertToExecutable(Phar::TAR, Phar::GZ); // Метод создаст файл myphar.phar.tar.gzМодуль Phar умеет сжимать отдельные файлы или архив целиком методом gzip или bzip2, и автоматически проверяет целостность архива по подписям MD5, SHA-1, SHA-256 или SHA-512.
Наконец, модуль Phar заботится о безопасности и по умолчанию отключает доступ на запись
для исполняемых phar-архивов, а также для создания или изменения
phar-архивов требует отключения настройки phar.readonly
на системном уровне — в файле php.ini. Стандартные tar- и zip-архивы без выполняемой заглушки
создаются или изменяются через класс PharData даже при включённой директиве.
Раздел «Как создавать Phar-архивы» описывает создание приложения для распространения. О различиях между тремя форматами, которые поддерживает модуль Phar, подробно рассказывает раздел «Phar, Tar и Zip».
Полезные советы по работе с phar-приложениями содержатся в разделе «Работа с phar-архивами».
Слово phar образовалось из слов PHP
и Archive с опорой на знакомый Java-разработчикам формат jar (Java Archive).
Реализация Phar-архивов основана на PEAR-пакете » PHP_Archive, и детали реализации схожи, хотя модуль Phar значительно мощнее. Кроме того, модуль Phar позволяет большей части PHP-приложений запускаться без изменений, тогда как phar-архивы на основе пакета PHP_Archive для работы часто требуют существенных изменений.
Here is an apache2 htaccess example that prevents the downloading of phar-Archives by the user:
RewriteEngine on
RewriteRule ^(.*)\.phar$ - [F]
It triggers a "403 - Forbidden" message instead of delivering the archive.If you get blank pages when trying to access a phar web-page, then you probably have Suhosin on your PHP (like in Debian and Ubuntu), and you need to ad this to your php.ini to allow execution of PHAR archives :
suhosin.executor.include.whitelist="phar"Users should set the `sys_temp_dir` directive.
PHAR stores temporary files in either `sys_temp_dir` or the current working directory(CWD).
This is especially important if you're CWD is on a remote file system. Often web server clusters will share a common file system between each web server (using NFS, DFS, etc...). In such scenarios, if you don't set `sys_temp_dir` to a local directory, PHAR will be creating temporary files over the network, which will result in performance and functionality problems.Here is a very simple program for creating phar files with CLI. Note that it requires phar.readonly in php.ini set to false (Off).
<?php
$filename = "default";
$dir = "./";
$regex = "/^(?!.*build\\.php)(?:.*)$/";
$main = "main.php";
$shebang = "#!/usr/bin/env php";
$chmod = true;
for ($i = 0; $i < $argc; $i++) {
switch ($argv[$i]) {
case "-o":
$i++;
if ($i >= $argc) {
echo "Missing output file name" . PHP_EOL;
exit(1);
}
$filename = $argv[$i];
break;
case "-i":
$i++;
if ($i >= $argc) {
echo "Missing input directory name" . PHP_EOL;
exit(1);
}
$dir = $argv[$i];
break;
case "-p":
$i++;
if ($i >= $argc) {
echo "Missing regular expression pattern" . PHP_EOL;
exit(1);
}
$regex = $argv[$i];
break;
case "-m":
$i++;
if ($i >= $argc) {
echo "Missing main file" . PHP_EOL;
exit(1);
}
$main = $argv[$i];
break;
case "-b":
$i++;
if ($i >= $argc) {
echo "Missing shebang of file" . PHP_EOL;
exit(1);
}
$shebang = $argv[$i];
break;
case "--no-chmod":
$chmod = false;
break;
}
}
if (file_exists($filename)) unlink($filename);
$phar = new Phar($filename);
$phar->buildFromDirectory($dir, $regex);
$phar->setStub(($shebang ? $shebang . PHP_EOL : "") . $phar->createDefaultStub($main));
if ($chmod) {
chmod($filename, fileperms($phar) | 0700);
}when read via phar://, stream will unserialize object including phar file
Use this to create phar
<?php
// create new Phar
$phar = new Phar('lemon.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');
// add object of any class as meta data
class AnyClass {}
$object = new AnyClass;
$object->data = 'Chanh';
$phar->setMetadata($object);
$phar->stopBuffering();
?>
and read it by:
<?php
class AnyClass {
function __destruct() {
echo $this->data;
}
}
// output: Chanh
file_get_contents('phar://test.phar');
?>Here is a very simple class to build a phar file from a given source directory. You can use this for your own project and simple deployment.
But my main goal was to show how to use PHAR functions in a simple way.
<?php
class BuildPhar
{
private $_sourceDirectory = null;
private $_stubFile = null;
private $_outputDirectory = null;
private $_pharFileName = null;
/**
* @param $_sourceDirectory // This is the directory where your project is stored.
* @param $stubFile // Name the entry point for your phar file. This file have to be within the source
* directory.
* @param null $_outputDirectory // Directory where the phar file will be placed.
* @param string $pharFileName // Name of your final *.phar file.
*/
public function __construct($_sourceDirectory, $stubFile, $_outputDirectory = null, $pharFileName = 'myPhar.phar') {
if ((file_exists($_sourceDirectory) === false) || (is_dir($_sourceDirectory) === false)) {
throw new Exception('No valid source directory given.');
}
$this->_sourceDirectory = $_sourceDirectory;
if (file_exists($this->_sourceDirectory.'/'.$stubFile) === false) {
throw new Exception('Your given stub file doesn\'t exists.');
}
$this->_stubFile = $stubFile;
if(empty($pharFileName) === true) {
throw new Exception('Your given output name for your phar-file is empty.');
}
$this->_pharFileName = $pharFileName;
if ((empty($_outputDirectory) === true) || (file_exists($_outputDirectory) === false) || (is_dir($_outputDirectory) === false)) {
if ($_outputDirectory !== null) {
trigger_error ( 'Your output directory is invalid. We set the fallback to: "'.dirname(__FILE__).'".', E_USER_WARNING);
}
$this->_outputDirectory = dirname(__FILE__);
} else {
$this->_outputDirectory = $_outputDirectory;
}
$this->prepareBuildDirectory();
$this->buildPhar();
}
private function prepareBuildDirectory() {
if (preg_match('/.phar$/', $this->_pharFileName) == FALSE) {
$this->_pharFileName .= '.phar';
}
if (file_exists($this->_pharFileName) === true) {
unlink($this->_pharFileName);
}
}
private function buildPhar() {
$phar = new Phar($this->_outputDirectory.'/'.$this->_pharFileName);
$phar->buildFromDirectory($this->_sourceDirectory);
$phar->setDefaultStub($this->_stubFile);
}
}
//END Class
//Example Usage:
$builder = new BuildPhar(
dirname(__FILE__).'/_source',
'my_default_stub.php',
dirname(__FILE__).'/_output',
'my-phar-file.phar'
);