Nette PhpGenerator

Szukasz narzędzia do generowania kodu PHP klas, funkcji albo kompletnych plików?
  • Wspiera wszystkie najnowsze funkcje PHP (jak hooki właściwości, enumy, atrybuty itd.)
  • Pozwala łatwo modyfikować istniejące klasy
  • Wyjście zgodne ze stylem kodowania PSR-12 / PER
  • Dojrzała, stabilna i szeroko używana biblioteka

Instalacja

Pobierz i zainstaluj bibliotekę narzędziem Composer:

composer require nette/php-generator

Kompatybilność z PHP znajdziesz w tabeli kompatybilności.

Klasy

Zacznijmy od przykładu utworzenia klasy za pomocą ClassType:

$class = new Nette\PhpGenerator\ClassType('Demo');

$class
	->setFinal()
	->setExtends(ParentClass::class)
	->addImplement(Countable::class)
	->addComment("Class description.\nSecond line\n")
	->addComment('@property-read Nette\Forms\Form $form');

// kod generujemy po prostu rzutowaniem na ciąg albo przez echo:
echo $class;

Zwróci to poniższy wynik:

/**
 * Class description.
 * Second line
 *
 * @property-read Nette\Forms\Form $form
 */
final class Demo extends ParentClass implements Countable
{
}

Do wygenerowania kodu możesz też użyć printera, który w przeciwieństwie do echo $class da się dalej skonfigurować:

$printer = new Nette\PhpGenerator\Printer;
echo $printer->printClass($class);

Możesz dodawać stałe (klasa Constant) i właściwości (klasa Property):

$class->addConstant('ID', 123)
	->setProtected() // widoczność stałej
	->setType('int')
	->setFinal();

$class->addProperty('items', [1, 2, 3])
	->setPrivate() // albo setVisibility('private')
	->setStatic()
	->addComment('@var int[]');

$class->addProperty('list')
	->setType('?array')
	->setInitialized(); // wypisze '= null'

Generuje to:

final protected const int ID = 123;

/** @var int[] */
private static $items = [1, 2, 3];
public ?array $list = null;

A możesz dodawać metody:

$method = $class->addMethod('count')
	->addComment('Count it.')
	->setFinal()
	->setProtected()
	->setReturnType('?int') // typy zwracane metod
	->setBody('return count($items ?: $this->items);');

$method->addParameter('items', []) // $items = []
	->setReference()           // &$items = []
	->setType('array');        // array &$items = []

Wynik to:

/**
 * Count it.
 */
final protected function count(array &$items = []): ?int
{
	return count($items ?: $this->items);
}

Parametry promowane wprowadzone w PHP 8.0 można przekazać konstruktorowi:

$method = $class->addMethod('__construct');
$method->addPromotedParameter('name');
$method->addPromotedParameter('args', [])
	->setPrivate();

Wynik to:

public function __construct(
	public $name,
	private $args = [],
) {
}

Właściwości i klasy readonly można oznaczyć funkcją setReadOnly().


Jeśli dodawana właściwość, stała, metoda albo trait już istnieje, rzucany jest wyjątek. Parametry są natomiast nadpisywane.

Elementy klasy można usuwać za pomocą removeProperty(), removeConstant(), removeMethod() albo removeParameter().

Do klasy możesz też dodawać istniejące obiekty Method, Property albo Constant:

$method = new Nette\PhpGenerator\Method('getHandle');
$property = new Nette\PhpGenerator\Property('handle');
$const = new Nette\PhpGenerator\Constant('ROLE');

$class = (new Nette\PhpGenerator\ClassType('Demo'))
	->addMember($method)
	->addMember($property)
	->addMember($const);

Istniejące metody, właściwości i stałe możesz też klonować pod inną nazwą za pomocą cloneWithName():

$methodCount = $class->getMethod('count');
$methodRecount = $methodCount->cloneWithName('recount');
$class->addMember($methodRecount);

Interfejsy i traity

Możesz tworzyć interfejsy i traity (klasy InterfaceTypeTraitType):

$interface = new Nette\PhpGenerator\InterfaceType('MyInterface');
$trait = new Nette\PhpGenerator\TraitType('MyTrait');

Użycie traitu:

$class = new Nette\PhpGenerator\ClassType('Demo');
$class->addTrait('SmartObject');
$class->addTrait('MyTrait')
	->addResolution('sayHello as protected')
	->addComment('@use MyTrait<Foo>');
echo $class;

Wynik to:

class Demo
{
	use SmartObject;
	/** @use MyTrait<Foo> */
	use MyTrait {
		sayHello as protected;
	}
}

Enumy

Enumy wprowadzone w PHP 8.1 możesz łatwo utworzyć tak (klasa EnumType):

$enum = new Nette\PhpGenerator\EnumType('Suit');
$enum->addCase('Clubs');
$enum->addCase('Diamonds');
$enum->addCase('Hearts');
$enum->addCase('Spades');

echo $enum;

Wynik to:

enum Suit
{
	case Clubs;
	case Diamonds;
	case Hearts;
	case Spades;
}

Możesz też zdefiniować odpowiedniki skalarne i utworzyć backed enum:

$enum = new Nette\PhpGenerator\EnumType('Suit');
$enum->addCase('Clubs', '♣');
$enum->addCase('Diamonds', '♦');

Każdemu przypadkowi możesz dodać komentarz albo atrybuty za pomocą addComment() albo addAttribute().

Klasy anonimowe

Przekaż jako nazwę null, a masz klasę anonimową:

$class = new Nette\PhpGenerator\ClassType(null);
$class->addMethod('__construct')
	->addParameter('foo');

echo '$obj = new class ($val) ' . $class . ';';

Wynik to:

$obj = new class ($val) {
	public function __construct($foo)
	{
	}
};

Funkcje globalne

Kod funkcji globalnych generuje klasa GlobalFunction:

$function = new Nette\PhpGenerator\GlobalFunction('foo');
$function->setBody('return $a + $b;');
$function->addParameter('a');
$function->addParameter('b');
echo $function;

// albo użyj PsrPrinter dla wyjścia zgodnego z PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printFunction($function);

Wynik to:

function foo($a, $b)
{
	return $a + $b;
}

Funkcje anonimowe

Kod funkcji anonimowych (domknięć) generuje klasa Closure:

$closure = new Nette\PhpGenerator\Closure;
$closure->setBody('return $a + $b;');
$closure->addParameter('a');
$closure->addParameter('b');
$closure->addUse('c')
	->setReference();
echo $closure;

// albo użyj PsrPrinter dla wyjścia zgodnego z PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printClosure($closure);

Wynik to:

function ($a, $b) use (&$c) {
	return $a + $b;
}

Krótkie funkcje strzałkowe

Za pomocą printera możesz wypisać też krótką funkcję strzałkową:

$closure = new Nette\PhpGenerator\Closure;
$closure->setBody('$a + $b');
$closure->addParameter('a');
$closure->addParameter('b');

echo (new Nette\PhpGenerator\Printer)->printArrowFunction($closure);

Wynik to:

fn($a, $b) => $a + $b;

Sygnatury metod i funkcji

Metody reprezentuje klasa Method. Możesz ustawić widoczność, typ zwracany, dodać komentarze, atrybuty itd.:

$method = $class->addMethod('count')
	->addComment('Count it.')
	->setFinal()
	->setProtected()
	->setReturnType('?int');

Poszczególne parametry reprezentuje klasa Parameter. Znów możesz ustawić wszystkie wyobrażalne właściwości:

$method->addParameter('items', []) // $items = []
	->setReference()           // &$items = []
	->setType('array');        // array &$items = []

// function count(array &$items = [])

Do zdefiniowania parametrów wariadycznych (znanych też jako operator splat) służy setVariadic():

$method = $class->addMethod('count');
$method->setVariadic(true);
$method->addParameter('items');

Generuje to:

function count(...$items)
{
}

Ciała metod i funkcji

Ciało można przekazać naraz metodzie setBody() albo stopniowo (linia po linii) przez wielokrotne wywoływanie addBody():

$function = new Nette\PhpGenerator\GlobalFunction('foo');
$function->addBody('$a = rand(10, 20);');
$function->addBody('return $a;');
echo $function;

Wynik to:

function foo()
{
	$a = rand(10, 20);
	return $a;
}

Do łatwego wstawiania zmiennych możesz używać specjalnych zastępników.

Proste zastępniki ?:

$str = 'any string';
$num = 3;
$function = new Nette\PhpGenerator\GlobalFunction('foo');
$function->addBody('return substr(?, ?);', [$str, $num]);
echo $function;

Wynik to:

function foo()
{
	return substr('any string', 3);
}

Zastępnik dla wariadycznych ...?:

$items = [1, 2, 3];
$function = new Nette\PhpGenerator\GlobalFunction('foo');
$function->setBody('myfunc(...?);', [$items]);
echo $function;

Wynik to:

function foo()
{
	myfunc(1, 2, 3);
}

Możesz też użyć parametrów nazwanych dla PHP 8 za pomocą ...?::

$items = ['foo' => 1, 'bar' => true];
$function->setBody('myfunc(...?:);', [$items]);

// myfunc(foo: 1, bar: true);

Zastępnik escapuje się odwrotnym ukośnikiem \?:

$num = 3;
$function = new Nette\PhpGenerator\GlobalFunction('foo');
$function->addParameter('a');
$function->addBody('return $a \? 10 : ?;', [$num]);
echo $function;

Wynik to:

function foo($a)
{
	return $a ? 10 : 3;
}

Printer i zgodność z PSR

Do generowania kodu PHP służy klasa Printer:

$class = new Nette\PhpGenerator\ClassType('Demo');
// ...

$printer = new Nette\PhpGenerator\Printer;
echo $printer->printClass($class); // to samo co: echo $class

Potrafi generować kod wszystkich pozostałych elementów, oferując metody jak printFunction(), printNamespace() itd.

Jest też klasa PsrPrinter, której wyjście odpowiada stylowi kodowania PSR-2 / PSR-12 / PER:

$printer = new Nette\PhpGenerator\PsrPrinter;
echo $printer->printClass($class);

Musisz dostosować zachowanie? Utwórz własną wersję, dziedzicząc po klasie Printer. Możesz przekonfigurować te zmienne:

class MyPrinter extends Nette\PhpGenerator\Printer
{
	// długość linii, po której następuje zawijanie
	public int $wrapLength = 120;
	// znak wcięcia, można zastąpić sekwencją spacji
	public string $indentation = "\t";
	// liczba pustych linii między właściwościami
	public int $linesBetweenProperties = 0;
	// liczba pustych linii między metodami
	public int $linesBetweenMethods = 2;
	// liczba pustych linii między grupami 'use statement' dla klas, funkcji i stałych
	public int $linesBetweenUseTypes = 0;
	// pozycja otwierającego nawiasu klamrowego funkcji i metod
	public bool $bracesOnNextLine = true;
	// umieszcza pojedynczy parametr w jednej linii, nawet jeśli ma atrybut albo jest promowany
	public bool $singleParameterOnOneLine = false;
	// pomija przestrzenie nazw niezawierające żadnej klasy ani funkcji
	public bool $omitEmptyNamespaces = true;
	// umieszcza declare(strict_types) w tej samej linii co <?php
	public bool $declareOnOpenTag = false;
	// separator między prawym nawiasem a typem zwracanym funkcji i metod
	public string $returnTypeColon = ': ';
}

Jak i dlaczego standardowy Printer i PsrPrinter właściwie się różnią? Dlaczego w pakiecie nie ma tylko jednego printera, PsrPrinter?

Standardowy Printer formatuje kod tak, jak robimy to w całym Nette. Ponieważ Nette powstało znacznie wcześniej niż PSR, a także dlatego, że standardy PSR często pojawiały się z opóźnieniem (czasem lata po wprowadzeniu nowej funkcji PHP), standard kodowania Nette różni się w kilku drobnych szczegółach. Główną różnicą jest używanie tabulatorów zamiast spacji. Wiemy, że używanie tabulatorów w naszych projektach pozwala dostosować szerokość, co jest niezbędne dla osób z wadami wzroku. Przykładem drobnej różnicy jest umieszczanie otwierającego nawiasu klamrowego funkcji i metod zawsze w osobnej linii. Zalecenie PSR wydaje nam się nielogiczne i prowadzi do zmniejszonej przejrzystości kodu.

Typy

Każdy typ albo typ unijny/przecięciowy można przekazać jako ciąg; możesz też używać predefiniowanych stałych dla typów natywnych:

use Nette\PhpGenerator\Type;

$member->setType('array'); // albo Type::Array
$member->setType('?array'); // albo Type::nullable(Type::Array)
$member->setType('array|string'); // albo Type::union(Type::Array, Type::String)
$member->setType('Foo&Bar'); // albo Type::intersection(Foo::class, Bar::class)
$member->setType(null); // usuwa typ

To samo dotyczy metody setReturnType().

Literały

Za pomocą Literal możesz przekazać dowolny kod PHP, na przykład jako wartości domyślne właściwości albo parametrów:

use Nette\PhpGenerator\Literal;

$class = new Nette\PhpGenerator\ClassType('Demo');

$class->addProperty('foo', new Literal('Iterator::SELF_FIRST'));

$class->addMethod('bar')
	->addParameter('id', new Literal('1 + 2'));

echo $class;

Wynik:

class Demo
{
	public $foo = Iterator::SELF_FIRST;

	public function bar($id = 1 + 2)
	{
	}
}

Literal możesz też przekazać parametry i pozwolić sformatować je do poprawnego kodu PHP za pomocą zastępników:

new Literal('substr(?, ?)', [$a, $b]);
// generuje na przykład: substr('hello', 5)

Literał reprezentujący utworzenie nowego obiektu da się łatwo wygenerować metodą new:

Literal::new(Demo::class, [$a, 'foo' => $b]);
// generuje na przykład: new Demo(10, foo: 20)

Atrybuty

Atrybuty PHP 8 można dodawać do wszystkich klas, metod, właściwości, stałych, enumów, funkcji, domknięć i parametrów. Jako wartości parametrów można też używać literałów.

$class = new Nette\PhpGenerator\ClassType('Demo');
$class->addAttribute('Table', [
	'name' => 'user',
	'constraints' => [
		Literal::new('UniqueConstraint', ['name' => 'ean', 'columns' => ['ean']]),
	],
]);

$class->addProperty('list')
	->addAttribute('Deprecated');

$method = $class->addMethod('count')
	->addAttribute('Foo\Cached', ['mode' => true]);

$method->addParameter('items')
	->addAttribute('Bar');

echo $class;

Wynik:

#[Table(name: 'user', constraints: [new UniqueConstraint(name: 'ean', columns: ['ean'])])]
class Demo
{
	#[Deprecated]
	public $list;


	#[Foo\Cached(mode: true)]
	public function count(
		#[Bar]
		$items,
	) {
	}
}

Hooki właściwości

Za pomocą hooków właściwości (reprezentowanych przez klasę PropertyHook) możesz zdefiniować operacje get i set dla właściwości, czyli funkcję wprowadzoną w PHP 8.4:

$class = new Nette\PhpGenerator\ClassType('Demo');
$prop = $class->addProperty('firstName')
    ->setType('string');

$prop->addHook('set', 'strtolower($value)')
    ->addParameter('value')
	    ->setType('string');

$prop->addHook('get')
	->setBody('return ucfirst($this->firstName);');

echo $class;

Generuje to:

class Demo
{
    public string $firstName {
        set(string $value) => strtolower($value);
        get {
            return ucfirst($this->firstName);
        }
    }
}

Właściwości i hooki właściwości mogą być abstrakcyjne albo finalne:

$class->addProperty('id')
    ->setType('int')
    ->addHook('get')
        ->setAbstract();

$class->addProperty('role')
    ->setType('string')
    ->addHook('set', 'strtolower($value)')
        ->setFinal();

Widoczność asymetryczna

PHP 8.4 wprowadza widoczność asymetryczną właściwości. Możesz ustawić różne poziomy dostępu dla odczytu i zapisu.

Widoczność można ustawić albo metodą setVisibility() z dwoma parametrami, albo za pomocą setPublic(), setProtected() czy setPrivate() z parametrem mode podającym, czy widoczność dotyczy odczytu, czy zapisu właściwości. Domyślnym trybem jest 'get'.

$class = new Nette\PhpGenerator\ClassType('Demo');

$class->addProperty('name')
    ->setType('string')
    ->setVisibility('public', 'private'); // public do odczytu, private do zapisu

$class->addProperty('id')
    ->setType('int')
    ->setProtected('set'); // protected do zapisu

echo $class;

Generuje to:

class Demo
{
    public private(set) string $name;

    protected(set) int $id;
}

Przestrzeń nazw

Klasy, traity, interfejsy i enumy (dalej nazywane klasami) można grupować w przestrzeniach nazw reprezentowanych przez klasę PhpNamespace:

$namespace = new Nette\PhpGenerator\PhpNamespace('Foo');

// tworzymy nowe klasy w przestrzeni nazw
$class = $namespace->addClass('Task');
$interface = $namespace->addInterface('Countable');
$trait = $namespace->addTrait('NameAware');

// albo wstawiamy do przestrzeni nazw istniejącą klasę czy funkcję
$class = new Nette\PhpGenerator\ClassType('Task');
$namespace->add($class);

Jeśli klasa o tej samej nazwie już w przestrzeni nazw istnieje, rzucany jest wyjątek.

Możesz definiować klauzule use:

// use Http\Request;
$namespace->addUse(Http\Request::class);
// use Http\Request as HttpReq;
$namespace->addUse(Http\Request::class, 'HttpReq');
// use function iter\range;
$namespace->addUseFunction('iter\range');

Do uproszczenia w pełni kwalifikowanej nazwy klasy, funkcji albo stałej na podstawie zdefiniowanych aliasów albo bieżącej przestrzeni nazw służy metoda simplifyName:

echo $namespace->simplifyName('Foo\Bar'); // 'Bar', bo 'Foo' to bieżąca przestrzeń nazw
echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', dzięki zdefiniowanemu use

Odwrotnie, uproszczoną nazwę klasy, funkcji albo stałej możesz przekształcić z powrotem w nazwę w pełni kwalifikowaną metodą resolveName:

echo $namespace->resolveName('Bar'); // 'Foo\Bar'
echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'

Rozwiązywanie nazw klas

Gdy klasa jest częścią przestrzeni nazw, renderowana jest nieco inaczej: wszystkie typy (np. type hinty, typy zwracane, nazwa klasy nadrzędnej, implementowane interfejsy, używane traity i atrybuty) są automatycznie rozwiązywane (chyba że to wyłączysz, patrz niżej). Oznacza to, że w definicjach musisz używać w pełni kwalifikowanych nazw klas, a w wynikowym kodzie zostaną zastąpione aliasami (na podstawie klauzul use) albo nazwami uproszczonymi (jeśli są w tej samej przestrzeni nazw):

$namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
$namespace->addUse('Bar\AliasedClass');

$class = $namespace->addClass('Demo');
$class->addImplement('Foo\A') // zostanie uproszczone do A
	->addTrait('Bar\AliasedClass'); // zostanie uproszczone do AliasedClass

$method = $class->addMethod('method');
$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // w komentarzach upraszczamy ręcznie
$method->addParameter('arg')
	->setType('Bar\OtherClass'); // zostanie przetłumaczone na \Bar\OtherClass

echo $namespace;

// albo użyj PsrPrinter dla wyjścia zgodnego z PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printNamespace($namespace);

Wynik:

namespace Foo;

use Bar\AliasedClass;

class Demo implements A
{
	use AliasedClass;

	/**
	 * @return D
	 */
	public function method(\Bar\OtherClass $arg)
	{
	}
}

Automatyczne rozwiązywanie można wyłączyć tak:

$printer = new Nette\PhpGenerator\Printer; // albo PsrPrinter
$printer->setTypeResolving(false);
echo $printer->printNamespace($namespace);

Pliki PHP

Klasy, funkcje i przestrzenie nazw można grupować w plikach PHP reprezentowanych przez klasę PhpFile:

$file = new Nette\PhpGenerator\PhpFile;
$file->addComment('This file is auto-generated.');
$file->setStrictTypes(); // dodaje declare(strict_types=1)

$class = $file->addClass('Foo\A');
$function = $file->addFunction('Foo\foo');

// albo
// $namespace = $file->addNamespace('Foo');
// $class = $namespace->addClass('A');
// $function = $namespace->addFunction('foo');

echo $file;

// albo użyj PsrPrinter dla wyjścia zgodnego z PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file);

Wynik:

<?php

/**
 * This file is auto-generated.
 */

declare(strict_types=1);

namespace Foo;

class A
{
}

function foo()
{
}

Do pliku możesz też wstawiać istniejące obiekty klas, funkcji i przestrzeni nazw metodą add():

$file = new Nette\PhpGenerator\PhpFile;
$class = new Nette\PhpGenerator\ClassType('Demo');
$file->add($class);

Zwróć uwagę: do plików nie da się dodać żadnego dodatkowego kodu (jak echo 'hello') poza funkcjami, klasami czy przestrzeniami nazw.

Generowanie z istniejących elementów

Oprócz modelowania klas i funkcji za pomocą opisanego wyżej API możesz też pozwolić wygenerować je automatycznie na podstawie istniejących, za pomocą refleksji:

// tworzy klasę identyczną z klasą PDO
$class = Nette\PhpGenerator\ClassType::from(PDO::class);

// tworzy funkcję identyczną z funkcją trim()
$function = Nette\PhpGenerator\GlobalFunction::from('trim');

// tworzy domknięcie na podstawie podanego
$closure = Nette\PhpGenerator\Closure::from(
	function (stdClass $a, $b = null) {},
);

Domyślnie ciała funkcji i metod są puste. Jeśli chcesz wczytać także je, użyj tej metody (wymaga zainstalowanego pakietu nikic/php-parser):

$class = Nette\PhpGenerator\ClassType::from(Foo::class, withBodies: true);

$function = Nette\PhpGenerator\GlobalFunction::from('foo', withBody: true);

Wczytywanie z plików PHP

Funkcje, klasy, interfejsy i enumy możesz też wczytywać bezpośrednio z ciągu zawierającego kod PHP. Na przykład żeby utworzyć obiekt ClassType:

$class = Nette\PhpGenerator\ClassType::fromCode(<<<XX
	<?php

	class Demo
	{
		public $foo;
	}
	XX);

Przy wczytywaniu klas z kodu PHP jednoliniowe komentarze poza ciałami metod (np. przy właściwościach) są ignorowane, bo ta biblioteka nie ma API do pracy z nimi.

Możesz też wczytać bezpośrednio cały plik PHP, który może zawierać dowolną liczbę klas, funkcji, a nawet przestrzeni nazw:

$file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));

Wczytywany jest też początkowy komentarz pliku i deklaracja strict_types. Cały pozostały kod globalny jest natomiast ignorowany.

Wymaga zainstalowanego nikic/php-parser.

Jeśli potrzebujesz manipulować kodem globalnym w plikach albo poszczególnymi instrukcjami wewnątrz ciał metod, lepiej użyj bezpośrednio biblioteki nikic/php-parser.

Manipulator klas

Klasa ClassManipulator daje narzędzia do manipulowania klasami.

$class = new Nette\PhpGenerator\ClassType('Demo');
$manipulator = new Nette\PhpGenerator\ClassManipulator($class);

Metoda inheritMethod() kopiuje metodę z klasy nadrzędnej albo implementowanego interfejsu do Twojej klasy. Pozwala to nadpisać metodę albo rozszerzyć jej sygnaturę:

$method = $manipulator->inheritMethod('bar');
$method->setBody('...');

Metoda inheritProperty() kopiuje właściwość z klasy nadrzędnej do Twojej klasy. Przydaje się, gdy chcesz mieć w swojej klasie tę samą właściwość, ale ewentualnie z inną wartością domyślną:

$property = $manipulator->inheritProperty('foo');
$property->setValue('new value');

Metoda implement() automatycznie implementuje w Twojej klasie wszystkie abstrakcyjne metody i właściwości z podanego interfejsu albo klasy abstrakcyjnej:

$manipulator->implement(SomeInterface::class);
// Teraz Twoja klasa implementuje SomeInterface i zawiera zaślepki wszystkich jego metod

Dumpowanie zmiennych

Klasa Dumper konwertuje zmienną na parsowalny kod PHP. Daje lepsze i przejrzystsze wyjście niż standardowa funkcja var_export().

$dumper = new Nette\PhpGenerator\Dumper;

$var = ['a', 'b', 123];

echo $dumper->dump($var); // wypisze ['a', 'b', 123]

Tabela kompatybilności

PhpGenerator 4.2 jest kompatybilny z PHP od 8.1 do 8.5.

Jeśli aktualizujesz do nowszej wersji, zajrzyj na stronę aktualizacji.

wersja: 4.x