Γεννήτρια κώδικα PHP

Ψάχνετε για ένα εργαλείο για την παραγωγή κώδικα PHP για κλάσεις, συναρτήσεις ή ολόκληρα αρχεία;
  • Υποστηρίζει όλα τα τελευταία χαρακτηριστικά της PHP (όπως property hooks, enums, attributes κ.λπ.)
  • Σας επιτρέπει να τροποποιήσετε εύκολα υπάρχουσες κλάσεις
  • Ο κώδικας εξόδου συμμορφώνεται με το PSR-12 / PER coding style
  • Ώριμη, σταθερή και ευρέως χρησιμοποιούμενη βιβλιοθήκη

Εγκατάσταση

Μπορείτε να κατεβάσετε και να εγκαταστήσετε τη βιβλιοθήκη χρησιμοποιώντας το Composer:

composer require nette/php-generator

Μπορείτε να βρείτε τη συμβατότητα με την PHP στον πίνακα.

Κλάσεις

Ας ξεκινήσουμε με ένα παράδειγμα δημιουργίας μιας κλάσης χρησιμοποιώντας την 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');

// you can easily generate the code by casting to a string or using echo:
echo $class;

Επιστρέφει το ακόλουθο αποτέλεσμα:

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

Μπορούμε επίσης να χρησιμοποιήσουμε έναν λεγόμενο printer για την παραγωγή κώδικα, τον οποίο, σε αντίθεση με το echo $class, θα μπορούμε να διαμορφώσουμε περαιτέρω:

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

Μπορούμε να προσθέσουμε σταθερές (κλάση Constant) και μεταβλητές (κλάση Property):

$class->addConstant('ID', 123)
	->setProtected() // visibility of constants
	->setType('int')
	->setFinal();

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

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

Παράγει:

final protected const int ID = 123;

/** @var int[] */
private static $items = [1, 2, 3];

public ?array $list = null;

Και μπορούμε να προσθέσουμε μεθόδους:

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

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

Το αποτέλεσμα είναι:

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

Οι προωθημένες παράμετροι που εισήχθησαν στην PHP 8.0 μπορούν να περάσουν στον κατασκευαστή:

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

Το αποτέλεσμα είναι:

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

Οι ιδιότητες και οι κλάσεις μόνο για ανάγνωση μπορούν να επισημανθούν χρησιμοποιώντας τη συνάρτηση setReadOnly().


Αν η ιδιότητα, η σταθερά, η μέθοδος ή η παράμετρος που προστίθεται ήδη υπάρχει, ρίχνεται μια εξαίρεση.

Τα μέλη της κλάσης μπορούν να αφαιρεθούν χρησιμοποιώντας removeProperty(), removeConstant(), removeMethod() ή removeParameter().

Μπορείτε επίσης να προσθέσετε υπάρχοντα αντικείμενα Method, Property ή 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);

Μπορείτε επίσης να κλωνοποιήσετε υπάρχουσες μεθόδους, ιδιότητες και σταθερές με διαφορετικό όνομα χρησιμοποιώντας το cloneWithName():

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

Interface ή trait

Μπορείτε να δημιουργήσετε interfaces και traits (κλάσεις InterfaceType και TraitType):

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

Χρήση traits:

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

Αποτέλεσμα:

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

Enums

Μπορείτε εύκολα να δημιουργήσετε enums, που εισήχθησαν στην PHP 8.1, ως εξής: (κλάση EnumType):

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

echo $enum;

Αποτέλεσμα:

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

Μπορείτε επίσης να ορίσετε ισοδύναμα scalar και να δημιουργήσετε ένα “backed” enum:

$enum->addCase('Clubs', '♣');
$enum->addCase('Diamonds', '♦');

Σε κάθε case είναι δυνατόν να προσθέσετε ένα σχόλιο ή atributy χρησιμοποιώντας addComment() ή addAttribute().

Ανώνυμες κλάσεις

Περνάμε null ως όνομα και έχουμε μια ανώνυμη κλάση:

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

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

Αποτέλεσμα:

$obj = new class ($val) {

	public function __construct($foo)
	{
	}
};

Καθολικές συναρτήσεις

Ο κώδικας των συναρτήσεων παράγεται από την κλάση GlobalFunction:

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

// or use PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printFunction($function);

Αποτέλεσμα:

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

Ανώνυμες συναρτήσεις

Ο κώδικας των ανώνυμων συναρτήσεων παράγεται από την κλάση Closure:

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

// or use PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printClosure($closure);

Αποτέλεσμα:

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

Συντομευμένες συναρτήσεις βέλους

Μπορείτε επίσης να εκτυπώσετε μια συντομευμένη ανώνυμη συνάρτηση χρησιμοποιώντας τον printer:

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

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

Αποτέλεσμα:

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

Υπογραφές μεθόδων και συναρτήσεων

Οι μέθοδοι αντιπροσωπεύονται από την κλάση Method. Μπορείτε να ορίσετε την ορατότητα, την τιμή επιστροφής, να προσθέσετε σχόλια, attributes κ.λπ.:

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

Οι μεμονωμένες παράμετροι αντιπροσωπεύονται από την κλάση Parameter. Και πάλι, μπορείτε να ορίσετε όλες τις πιθανές ιδιότητες:

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

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

Για τον ορισμό των λεγόμενων variadic παραμέτρων (ή αλλιώς τελεστής splat) χρησιμοποιείται το setVariadic():

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

Παράγει:

function count(...$items)
{
}

Σώματα μεθόδων και συναρτήσεων

Το σώμα μπορεί να περαστεί ολόκληρο στη μέθοδο setBody() ή διαδοχικά (ανά γραμμή) με επαναλαμβανόμενη κλήση της addBody():

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

Αποτέλεσμα

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

Μπορείτε να χρησιμοποιήσετε ειδικούς χαρακτήρες υποκατάστασης για εύκολη εισαγωγή μεταβλητών.

Απλοί χαρακτήρες υποκατάστασης ?

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

Αποτέλεσμα

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

Χαρακτήρας υποκατάστασης για variadic ...?

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

Αποτέλεσμα:

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

Μπορείτε επίσης να χρησιμοποιήσετε ονομασμένες παράμετροι για την PHP 8 χρησιμοποιώντας ...?:

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

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

Ο χαρακτήρας υποκατάστασης διαφεύγει με κάθετο \?

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

Αποτέλεσμα:

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

Printer και συμμόρφωση με το PSR

Για την παραγωγή κώδικα PHP χρησιμοποιείται η κλάση Printer:

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

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

Μπορεί να παράγει κώδικα για όλα τα άλλα στοιχεία, προσφέρει μεθόδους όπως printFunction(), printNamespace(), κ.λπ.

Υπάρχει επίσης η κλάση PsrPrinter, της οποίας η έξοδος συμμορφώνεται με το PSR-2 / PSR-12 / PER coding style:

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

Χρειάζεστε να προσαρμόσετε τη συμπεριφορά στις ανάγκες σας; Δημιουργήστε τη δική σας έκδοση κληρονομώντας την κλάση Printer. Μπορείτε να επαναδιαμορφώσετε αυτές τις μεταβλητές:

class MyPrinter extends Nette\PhpGenerator\Printer
{
	// line length after which line wrapping occurs
	public int $wrapLength = 120;
	// indentation character, can be replaced by a sequence of spaces
	public string $indentation = "\t";
	// number of empty lines between properties
	public int $linesBetweenProperties = 0;
	// number of empty lines between methods
	public int $linesBetweenMethods = 2;
	// number of empty lines between groups of 'use statements' for classes, functions, and constants
	public int $linesBetweenUseTypes = 0;
	// position of the opening curly brace for functions and methods
	public bool $bracesOnNextLine = true;
	// place a single parameter on one line, even if it has an attribute or is promoted
	public bool $singleParameterOnOneLine = false;
	// omits namespaces that do not contain any class or function
	public bool $omitEmptyNamespaces = true;
	// separator between the right parenthesis and the return type of functions and methods
	public string $returnTypeColon = ': ';
}

Πώς και γιατί διαφέρει ο τυπικός Printer από τον PsrPrinter; Γιατί δεν υπάρχει μόνο ένας printer στο πακέτο, και αυτός να είναι ο PsrPrinter;

Ο τυπικός Printer μορφοποιεί τον κώδικα όπως το κάνουμε σε όλο το Nette. Επειδή το Nette δημιουργήθηκε πολύ νωρίτερα από το PSR, και επίσης επειδή το PSR για πολλά χρόνια δεν παρείχε πρότυπα έγκαιρα, αλλά ίσως με καθυστέρηση αρκετών ετών από την εισαγωγή ενός νέου χαρακτηριστικού στην PHP, συνέβη το πρότυπο κωδικοποίησης να διαφέρει σε μερικές λεπτομέρειες. Η μεγαλύτερη διαφορά είναι μόνο η χρήση tabs αντί για κενά. Γνωρίζουμε ότι η χρήση tabs στα έργα μας επιτρέπει την προσαρμογή του πλάτους, η οποία είναι απαραίτητη για άτομα με προβλήματα όρασης. Ένα παράδειγμα μικρής διαφοράς είναι η τοποθέτηση του άγκιστρου σε ξεχωριστή γραμμή για συναρτήσεις και μεθόδους, και αυτό πάντα. Η σύσταση του PSR μας φαίνεται παράλογη και οδηγεί σε μείωση της σαφήνειας του κώδικα.

Τύποι

Κάθε τύπος ή union/intersection τύπος μπορεί να περαστεί ως string, μπορείτε επίσης να χρησιμοποιήσετε προκαθορισμένες σταθερές για εγγενείς τύπους:

use Nette\PhpGenerator\Type;

$member->setType('array'); // or Type::Array;
$member->setType('?array'); // or Type::nullable(Type::Array);
$member->setType('array|string'); // or Type::union(Type::Array, Type::String)
$member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class)
$member->setType(null); // removes the type

Το ίδιο ισχύει και για τη μέθοδο setReturnType().

Literals

Με το Literal μπορείτε να περάσετε οποιονδήποτε κώδικα PHP, για παράδειγμα για προεπιλεγμένες τιμές ιδιοτήτων ή παραμέτρων κ.λπ.:

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;

Αποτέλεσμα:

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

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

Μπορείτε επίσης να περάσετε παραμέτρους στο Literal και να τις μορφοποιήσετε σε έγκυρο κώδικα PHP χρησιμοποιώντας χαρακτήρες υποκατάστασης:

new Literal('substr(?, ?)', [$a, $b]);
// generates for example: substr('hello', 5);

Ένα literal που αντιπροσωπεύει τη δημιουργία ενός νέου αντικειμένου μπορεί εύκολα να παραχθεί χρησιμοποιώντας τη μέθοδο new:

Literal::new(Demo::class, [$a, 'foo' => $b]);
// generates for example: new Demo(10, foo: 20)

Attributes

Μπορείτε να προσθέσετε attributes της PHP 8 σε όλες τις κλάσεις, μεθόδους, ιδιότητες, σταθερές, enums, συναρτήσεις, closures και παραμέτρους. Μπορείτε επίσης να χρησιμοποιήσετε literály ως τιμές παραμέτρων.

$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;

Αποτέλεσμα:

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


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

Property Hooks

Χρησιμοποιώντας τα property hooks (που αντιπροσωπεύονται από την κλάση PropertyHook), μπορείτε να ορίσετε τις λειτουργίες get και set για τις ιδιότητες, ένα χαρακτηριστικό που εισήχθη στην 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;

Παράγει:

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

Οι property και τα property hooks μπορούν να είναι abstract ή final:

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

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

Ασύμμετρη ορατότητα

Η PHP 8.4 εισάγει την ασύμμετρη ορατότητα για τις ιδιότητες. Μπορείτε να ορίσετε διαφορετικά επίπεδα πρόσβασης για ανάγνωση και εγγραφή.

Η ορατότητα μπορεί να οριστεί είτε με τη μέθοδο setVisibility() με δύο παραμέτρους, είτε με τις setPublic(), setProtected() ή setPrivate() με μια παράμετρο mode που καθορίζει αν η ορατότητα εφαρμόζεται στην ανάγνωση ή την εγγραφή της ιδιότητας. Η προεπιλεγμένη λειτουργία είναι 'get'.

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

$class->addProperty('name')
    ->setType('string')
    ->setVisibility('public', 'private'); // public for reading, private for writing

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

echo $class;

Παράγει:

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

    protected(set) int $id;
}

Namespace

Οι κλάσεις, οι ιδιότητες, τα interfaces και τα enums (εφεξής κλάσεις) μπορούν να ομαδοποιηθούν σε namespaces που αντιπροσωπεύονται από την κλάση PhpNamespace:

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

// create new classes in the namespace
$class = $namespace->addClass('Task');
$interface = $namespace->addInterface('Countable');
$trait = $namespace->addTrait('NameAware');

// or insert an existing class into the namespace
$class = new Nette\PhpGenerator\ClassType('Task');
$namespace->add($class);

Αν η κλάση ήδη υπάρχει, ρίχνεται μια εξαίρεση.

Μπορείτε να ορίσετε use clauses:

// 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');

Για να απλοποιήσετε το πλήρως πιστοποιημένο όνομα μιας κλάσης, συνάρτησης ή σταθεράς σύμφωνα με τα ορισμένα ψευδώνυμα, χρησιμοποιήστε τη μέθοδο simplifyName:

echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is the current namespace
echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', because of the defined use-statement

Αντίθετα, μπορείτε να μετατρέψετε το απλοποιημένο όνομα μιας κλάσης, συνάρτησης ή σταθεράς στο πλήρως πιστοποιημένο όνομα χρησιμοποιώντας τη μέθοδο resolveName:

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

Μεταφράσεις ονομάτων κλάσεων

Όταν μια κλάση είναι μέρος ενός namespace, αποδίδεται ελαφρώς διαφορετικά: όλοι οι τύποι (για παράδειγμα, typehints, τιμές επιστροφής, όνομα γονικής κλάσης, υλοποιημένα interfaces, χρησιμοποιημένες ιδιότητες και attributes) μεταφράζονται αυτόματα (εκτός αν το απενεργοποιήσετε, δείτε παρακάτω). Αυτό σημαίνει ότι πρέπει να χρησιμοποιείτε πλήρη ονόματα κλάσεων στους ορισμούς και αυτά θα αντικατασταθούν με ψευδώνυμα (σύμφωνα με τις use clauses) ή με πλήρως πιστοποιημένα ονόματα στον τελικό κώδικα:

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

$class = $namespace->addClass('Demo');
$class->addImplement('Foo\A') // will be simplified to A
	->addTrait('Bar\AliasedClass'); // will be simplified to AliasedClass

$method = $class->addMethod('method');
$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // in comments, we simplify manually
$method->addParameter('arg')
	->setType('Bar\OtherClass'); // will be translated to \Bar\OtherClass

echo $namespace;

// or use PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printNamespace($namespace);

Αποτέλεσμα:

namespace Foo;

use Bar\AliasedClass;

class Demo implements A
{
	use AliasedClass;

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

Η αυτόματη μετάφραση μπορεί να απενεργοποιηθεί με αυτόν τον τρόπο:

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

Αρχεία PHP

Οι κλάσεις, οι συναρτήσεις και τα namespaces μπορούν να ομαδοποιηθούν σε αρχεία PHP που αντιπροσωπεύονται από την κλάση PhpFile:

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

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

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

echo $file;

// or use PsrPrinter for output compliant with PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file);

Αποτέλεσμα:

<?php

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

declare(strict_types=1);

namespace Foo;

class A
{
}

function foo()
{
}

Προειδοποίηση: Δεν είναι δυνατόν να προσθέσετε επιπλέον κώδικα στα αρχεία εκτός από συναρτήσεις και κλάσεις.

Παραγωγή βάσει υπαρχόντων

Εκτός από τη δυνατότητα να μοντελοποιήσετε κλάσεις και συναρτήσεις χρησιμοποιώντας το API που περιγράφηκε παραπάνω, μπορείτε επίσης να τις παράγετε αυτόματα βάσει υπαρχόντων προτύπων:

// creates a class identical to the PDO class
$class = Nette\PhpGenerator\ClassType::from(PDO::class);

// creates a function identical to the trim() function
$function = Nette\PhpGenerator\GlobalFunction::from('trim');

// creates a closure based on the provided one
$closure = Nette\PhpGenerator\Closure::from(
	function (stdClass $a, $b = null) {},
);

Τα σώματα των συναρτήσεων και των μεθόδων είναι κενά από προεπιλογή. Αν θέλετε να τα φορτώσετε επίσης, χρησιμοποιήστε αυτόν τον τρόπο (απαιτεί την εγκατάσταση του πακέτου nikic/php-parser):

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

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

Φόρτωση από αρχεία PHP

Μπορείτε επίσης να φορτώνετε συναρτήσεις, κλάσεις, interfaces και enums απευθείας από ένα string που περιέχει κώδικα PHP. Για παράδειγμα, έτσι δημιουργούμε ένα αντικείμενο ClassType:

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

	class Demo
	{
		public $foo;
	}
	XX);

Κατά τη φόρτωση κλάσεων από κώδικα PHP, τα σχόλια μιας γραμμής εκτός των σωμάτων των μεθόδων αγνοούνται (π.χ. σε properties κ.λπ.), καθώς αυτή η βιβλιοθήκη δεν διαθέτει API για την εργασία μαζί τους.

Μπορείτε επίσης να φορτώσετε απευθείας ένα ολόκληρο αρχείο PHP, το οποίο μπορεί να περιέχει οποιονδήποτε αριθμό κλάσεων, συναρτήσεων ή ακόμα και namespaces:

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

Φορτώνεται επίσης το εισαγωγικό σχόλιο του αρχείου και η δήλωση strict_types. Αντίθετα, όλος ο υπόλοιπος καθολικός κώδικας αγνοείται.

Απαιτείται να είναι εγκατεστημένο το nikic/php-parser.

Αν χρειάζεστε να χειριστείτε τον καθολικό κώδικα σε αρχεία ή τις μεμονωμένες εντολές στα σώματα των μεθόδων, είναι καλύτερο να χρησιμοποιήσετε απευθείας τη βιβλιοθήκη nikic/php-parser.

Class Manipulator

Η κλάση ClassManipulator παρέχει εργαλεία για τον χειρισμό κλάσεων.

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

Η μέθοδος inheritMethod() αντιγράφει μια μέθοδο από τη γονική κλάση ή το υλοποιημένο interface στην κλάση σας. Αυτό σας επιτρέπει να αντικαταστήσετε τη μέθοδο ή να επεκτείνετε την signature της:

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

Η μέθοδος `inheritProperty()` αντιγράφει μια ιδιότητα από τη γονική κλάση στην κλάση σας. Είναι χρήσιμο όταν θέλετε να έχετε την ίδια ιδιότητα στην κλάση σας, αλλά ίσως με διαφορετική προεπιλεγμένη τιμή:

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

Η μέθοδος implement() υλοποιεί αυτόματα όλες τις μεθόδους και τις ιδιότητες από το δοθέν interface ή την abstract κλάση στην κλάση σας:

$manipulator->implement(SomeInterface::class);
// Now your class implements SomeInterface and contains all its methods

Έξοδος μεταβλητών

Η κλάση Dumper μετατρέπει μια μεταβλητή σε αναλύσιμο κώδικα PHP. Παρέχει καλύτερη και σαφέστερη έξοδο από την τυπική συνάρτηση var_export().

$dumper = new Nette\PhpGenerator\Dumper;

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

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

Πίνακας συμβατότητας

Το PhpGenerator 4.1 είναι συμβατό με PHP 8.0 έως 8.4.

έκδοση: 4.0