Tvorba PHAR archívů

Pavel PHP

I jazyk jako je PHP umožňuje tvorbu archívů, které se nazývají PHAR. Může obsahovat vše od PHP skriptů, přes styly až po obrázky a další binární soubory. Klidně celou aplikaci. A navíc je lze spouštět přímo z příkazové řádky.

Tvorba PHAR archívů

PHAR neboli PHp ARchive je archív podobně jako JAR v Javě. Dokáže vytvořit balík mnoha souborů, nejen PHP. Ten lze pak vkládat do jiných projektů nebo přímo spouštět z příkazové řádky. Nejznámější aplikace šířená jako PHAR je určitě Composer.

Pro tvorbu PHAR souborů lze využít třídu Phar přímo v PHP, nebo aplikaci Box. Dnešní díl je ale především o první metodě, tedy nativní třídě. Soubory PHAR mohou být také zabezpečeny a podepsány. Realita ale trochu pokulhává, viz článek na Sucuri.net.

Jak na to

Nejjednodušší způsob je vložit celou aplikaci do složky app, vedle složky vytvořil skript build.php a ten následně spustit s obsahem níže. Ve složce app může být klidně zabalen celý vendor s autoloaderem od Composeru. A hlavně tam musí být tzv. entry point neboli soubor, který se spustí jako první.

V základu je zakázáno měnit PHAR soubory a kód skončí neošetřenou výjimkou PharException. Proto je nutné změnit v souboru php.ini phar.readonly z 1 na 0. Ukázka build soubor, kterým se sestavuje Composer je dostupná v jeho repozitáři.

// Pokud se nepovede změnit mód,
// je nutné změnu provést přímo v php.ini souboru
ini_set("phar.readonly", 0);
if (ini_get("phar.readonly") != 0) {
    die("Nelze zmenit phar.readonly mode");
}

$pharFile = 'app.phar';
// Odstranění starých PHAR souborů
if (file_exists($pharFile)) { unlink($pharFile); }

// Vytvoří nový PHAR
$phar = new Phar($pharFile);
$phar->startBuffering(); // Povinné pro vlastní stub
 
$phar->buildFromDirectory("app");

// Vytvoří základní STUB s výchozím entry pointer index.php
// Soubor index.php musí být rovněž ve složce app
$defaultStub = $phar->createDefaultStub("index.php");
$phar->setStub("#!/usr/bin/env php \n".$defaultStub);

$phar->stopBuffering();
   
echo "{$pharFile} vytvoren";

Pozor na spouštění serverem

Apache v základu není nakonfigurovaný tak, aby soubory s příponou .phar spouštěl jako PHP skript. Pokud se na něj někdo odkáže, bude mu vrácen zdrojový kód. Je proto vhodné, vkládat PHAR soubory do složek, kam přístup není, nebo jej zakázat přes htacess. A protože ze serveru se přímo spouštět nejspíše nebude, může se upravit i základní stub.

Vlastní stub

Stub je úvodní část programu, která říká, jak jej zpracovávat. Základní stub obsahuje plno logiky pro správné vrácení i souborů v něm uložených. To je ale zbytečné, protože serverem se přímo PHAR spouště nebude. Proto se může stub trochu zjednodušit.

$defaultStub = <<<'EOF'
#!/usr/bin/env php
<?php
/*
 * Toto je ukázkový PHAR soubor
 *
 * S minimálním stubem, který vše spustí
 */

Phar::mapPhar();
include 'phar://'.__FILE__.'/index.php';

__HALT_COMPILER();
EOF;
$phar->setStub($defaultStub);

Jak na vlastní složky a podsložky

Pokud není možné všechny soubory vložit do složky app, je nutné vše postupně do PHARu přidat ručně. Zde je nutné zachovávat správné pojmenování, aby všechny include našly správnou cestu k souboru.

function addRecursiveFiles($phar, $dir){
    // Rekurzivně iterovat skrz všechny složky
    // a pro všechny soubory provést
    $phar->addFile($path, str_replace(__DIR__."/", "", $path));
}
addRecursiveFiles($phar, __DIR__.'/myApp');
addRecursiveFiles($phar, __DIR__.'/vendor');

// Možné je soubor do PHARu vložit pod jiným jménem
$phar->addFile(__DIR__."/index.php", 'entry.php');
// Pak je nutné upravit stub
$defaultStub = $phar->createDefaultStub("entry.php");
// Nebo v případě vlastního nahradit include na entry
include 'phar://'.__FILE__.'/entry.php';

Použití PHARu v ostatních PHP skriptech

Přesto, že Apache nejspíše PHAR spouštět nebude, nic nebrání tomu jej používat ve vlastních skriptech. Jednoduše lze se soubory provést include jednotlivých souborů, případně získat jejich obsah ať už se jedná o PHP skript nebo binární obrázek.

// Lze specifikovat celou přesnou cestu k souboru
include 'phar://app.phar/helpers/functions.php';
// Funkce prettify je v souboru functions.php v PHARu výše
echo prettify("test");
// Phar rovněž obsahuje obrázek
$logo = file_get_contents("phar://app.phar/assets/logo.png");
file_put_contents("test.png", $logo);

Vlastní zkušenosti nebo použití PHP archívů PHAR můžete sdílet v komentářích

Přidat komentář

Právě odpovídáte na existující komentář. Zrušit

Komentáře

Novinky z blogu

Z internetu na lokální server pomocí ngrok

ngrok je nástroj, který umožňuje vytvořit zabezpečený tunel z veřejné URL k lokálnímu serveru na vašem stroji. Můžete tak k vašemu localhostu přistupovat...

Další články