Γεννήτρια κώδικα 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("Περιγραφή κλάσης.\nΔεύτερη γραμμή\n")
->addComment('@property-read Nette\Forms\Form $form');
// μπορείτε εύκολα να παράγετε τον κώδικα κάνοντας cast σε string ή χρησιμοποιώντας το echo:
echo $class;
Επιστρέφει το ακόλουθο αποτέλεσμα:
/**
* Περιγραφή κλάσης
* Δεύτερη γραμμή
*
* @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() // ορατότητα σταθερών
->setType('int')
->setFinal();
$class->addProperty('items', [1, 2, 3])
->setPrivate() // ή setVisibility('private')
->setStatic()
->addComment('@var int[]');
$class->addProperty('list')
->setType('?array')
->setInitialized(); // εκτυπώνει '= 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') // τύποι επιστροφής για μεθόδους
->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 είναι δυνατόν να προσθέσετε ένα σχόλιο ή attributes χρησιμοποιώντας 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;
// ή χρησιμοποιήστε το PsrPrinter για έξοδο συμβατή με 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;
// ή χρησιμοποιήστε το PsrPrinter για έξοδο συμβατή με 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); // το ίδιο με: 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
{
// μήκος γραμμής μετά το οποίο γίνεται αναδίπλωση γραμμής
public int $wrapLength = 120;
// χαρακτήρας εσοχής, μπορεί να αντικατασταθεί από μια ακολουθία κενών
public string $indentation = "\t";
// αριθμός κενών γραμμών μεταξύ properties
public int $linesBetweenProperties = 0;
// αριθμός κενών γραμμών μεταξύ μεθόδων
public int $linesBetweenMethods = 2;
// αριθμός κενών γραμμών μεταξύ ομάδων 'use statements' για κλάσεις, συναρτήσεις και σταθερές
public int $linesBetweenUseTypes = 0;
// θέση του αριστερού άγκιστρου για συναρτήσεις και μεθόδους
public bool $bracesOnNextLine = true;
// τοποθετήστε μια παράμετρο ανά γραμμή, ακόμα κι αν έχει attribute ή είναι promoted
public bool $singleParameterOnOneLine = false;
// παραλείπει namespaces που δεν περιέχουν καμία κλάση ή συνάρτηση
public bool $omitEmptyNamespaces = true;
// διαχωριστικό μεταξύ της δεξιάς παρένθεσης και του τύπου επιστροφής συναρτήσεων και μεθόδων
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'); // ή Type::Array;
$member->setType('?array'); // ή Type::nullable(Type::Array);
$member->setType('array|string'); // ή Type::union(Type::Array, Type::String)
$member->setType('Foo&Bar'); // ή Type::intersection(Foo::class, Bar::class)
$member->setType(null); // αφαιρεί τον τύπο
Το ίδιο ισχύει και για τη μέθοδο 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]);
// παράγει για παράδειγμα: substr('hello', 5);
Ένα literal που αντιπροσωπεύει τη δημιουργία ενός νέου αντικειμένου
μπορεί εύκολα να παραχθεί χρησιμοποιώντας τη μέθοδο new
:
Literal::new(Demo::class, [$a, 'foo' => $b]);
// παράγει για παράδειγμα: new Demo(10, foo: 20)
Attributes
Μπορείτε να προσθέσετε attributes της PHP 8 σε όλες τις κλάσεις, μεθόδους, ιδιότητες, σταθερές, enums, συναρτήσεις, closures και παραμέτρους. Μπορείτε επίσης να χρησιμοποιήσετε literals ως τιμές παραμέτρων.
$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 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 για ανάγνωση, private για εγγραφή
$class->addProperty('id')
->setType('int')
->setProtected('set'); // protected για εγγραφή
echo $class;
Παράγει:
class Demo
{
public private(set) string $name;
protected(set) int $id;
}
Namespace
Οι κλάσεις, οι ιδιότητες, τα interfaces και τα enums (εφεξής κλάσεις) μπορούν να ομαδοποιηθούν σε namespaces που αντιπροσωπεύονται από την κλάση PhpNamespace:
$namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
// δημιουργούμε νέες κλάσεις στο namespace
$class = $namespace->addClass('Task');
$interface = $namespace->addInterface('Countable');
$trait = $namespace->addTrait('NameAware');
// ή εισάγουμε μια υπάρχουσα κλάση στο 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', επειδή το 'Foo' είναι το τρέχον namespace
echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', λόγω του ορισμένου 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') // θα απλοποιηθεί σε A
->addTrait('Bar\AliasedClass'); // θα απλοποιηθεί σε AliasedClass
$method = $class->addMethod('method');
$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // στα σχόλια, απλοποιούμε χειροκίνητα
$method->addParameter('arg')
->setType('Bar\OtherClass'); // θα μεταφραστεί σε \Bar\OtherClass
echo $namespace;
// ή χρησιμοποιήστε το PsrPrinter για έξοδο συμβατή με 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; // ή PsrPrinter
$printer->setTypeResolving(false);
echo $printer->printNamespace($namespace);
Αρχεία PHP
Οι κλάσεις, οι συναρτήσεις και τα namespaces μπορούν να ομαδοποιηθούν σε αρχεία PHP που αντιπροσωπεύονται από την κλάση PhpFile:
$file = new Nette\PhpGenerator\PhpFile;
$file->addComment('Αυτό το αρχείο παράγεται αυτόματα.');
$file->setStrictTypes(); // προσθέτει declare(strict_types=1)
$class = $file->addClass('Foo\A');
$function = $file->addFunction('Foo\foo');
// ή
// $namespace = $file->addNamespace('Foo');
// $class = $namespace->addClass('A');
// $function = $namespace->addFunction('foo');
echo $file;
// ή χρησιμοποιήστε το PsrPrinter για έξοδο συμβατή με PSR-2 / PSR-12 / PER
// echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file);
Αποτέλεσμα:
<?php
/**
* Αυτό το αρχείο παράγεται αυτόματα.
*/
declare(strict_types=1);
namespace Foo;
class A
{
}
function foo()
{
}
Προειδοποίηση: Δεν είναι δυνατόν να προσθέσετε επιπλέον κώδικα στα αρχεία εκτός από συναρτήσεις και κλάσεις.
Παραγωγή βάσει υπαρχόντων
Εκτός από τη δυνατότητα να μοντελοποιήσετε κλάσεις και συναρτήσεις χρησιμοποιώντας το API που περιγράφηκε παραπάνω, μπορείτε επίσης να τις παράγετε αυτόματα βάσει υπαρχόντων προτύπων:
// δημιουργεί μια κλάση ίδια με την κλάση PDO
$class = Nette\PhpGenerator\ClassType::from(PDO::class);
// δημιουργεί μια συνάρτηση ίδια με τη συνάρτηση trim()
$function = Nette\PhpGenerator\GlobalFunction::from('trim');
// δημιουργεί ένα closure βάσει του παρεχόμενου
$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()
αντιγράφει μια ιδιότητα από τη γονική
κλάση στην κλάση σας. Είναι χρήσιμο όταν θέλετε να έχετε την ίδια
ιδιότητα στην κλάση σας, αλλά ίσως με διαφορετική
προεπιλεγμένη τιμή:
$property = $manipulator->inheritProperty('foo');
$property->setValue('new value');
Η μέθοδος implement()
υλοποιεί αυτόματα όλες τις μεθόδους και τις
ιδιότητες από το δοθέν interface ή την abstract κλάση στην κλάση σας:
$manipulator->implement(SomeInterface::class);
// Τώρα η κλάση σας υλοποιεί το SomeInterface και περιέχει όλες τις μεθόδους του
Έξοδος μεταβλητών
Η κλάση Dumper
μετατρέπει μια μεταβλητή σε αναλύσιμο κώδικα PHP.
Παρέχει καλύτερη και σαφέστερη έξοδο από την τυπική συνάρτηση
var_export()
.
$dumper = new Nette\PhpGenerator\Dumper;
$var = ['a', 'b', 123];
echo $dumper->dump($var); // εκτυπώνει ['a', 'b', 123]
Πίνακας συμβατότητας
Το PhpGenerator 4.1 είναι συμβατό με PHP 8.0 έως 8.4.