Novinky v PhpGenerator v3.5

před 4 lety od David Grudl  

PhpGenerator se naučil všechny vymoženosti PHP 8. Pojďme se podívat, jak je můžete hned začít používat.

Constructor Property Promotion

Velmi sympatickou novinkou PHP 8 je constructor property promotion, tedy syntaktický cukr, který ušetří dvojí psaní typu a čtyřnásobné psaní proměnné. „Promoted“ parametry přidáme pomocí addPromotedParameter() a lze je kombinovat s klasickými parametry přidávanými metodou addParameter():

use Nette\PhpGenerator\ClassType;

$class = new ClassType('Facade');
$method = $class->addMethod('__construct');

$method->addPromotedParameter('db')
	->setPrivate()
	->setType(Nette\Database\Connection::class);

$method->addPromotedParameter('mailer')
	->setPrivate()
	->setType(Nette\Mail\Mailer::class);

$method->addParameter('foo');

echo $class;

Výsledek:

class Facade
{
	public function __construct(
		private Nette\Database\Connection $db,
		private Nette\Mail\Mailer $mailer,
		$foo,
	) {
	}
}

Můžete si všimnout další novinky, že PhpGenerator vypisuje koncovou čárku v definici parametrů, když je použita PHP 8 syntax.

Atributy

PHP 8 atributy přinášejí zcela nový způsob, jak zapisovat strukturovaná metadata ke třídám a všem jejím členům, taktéž funkcím, closurám a jejich parametrům. Tohle vše podporuje také PhpGenerator a každý prvek disponuje nově metodami addAttribute(string $name, array $args = []), setAttributes(Attribute[] $attrs) a getAttributes(): Attribute[].

use Nette\PhpGenerator\PhpNamespace;
use Nette\PhpGenerator\Literal;

$namespace = new PhpNamespace('');
$namespace->addUse(Nette\Application\Attributes::class);

$class = $namespace->addClass('SomePresenter');

$class->addAttribute('FooBar', [
	'foo' => new Literal('Foo::BAR'),
	'bar' => [1, 2, 3]
]);

$class->addProperty('page')
	->setType('int')
	->addAttribute(Nette\Application\Attributes\Persistent::class);

echo $class;

Vygeneruje:

#[FooBar(foo: Foo::BAR, bar: [1, 2, 3])]
class SomePresenter
{
	#[Attributes\Persistent]
	public int $page;
}

Jak vidíte, pro atributy se využívají use statements. A dokonce je lze kombinovat i s promoted parametry.

Typy

Na místech všech typehintů lze nově uvádět union typy a to v podobě řetězce se svislítky. Řetězec si můžete nechat vygenerovat také pomocí Type::union().

use Nette\PhpGenerator\Type;
use Nette\PhpGenerator\GlobalFunction;

$function = (new GlobalFunction('twice'))
	->setReturnType('int|float')
	->setBody('return $a * 2;');

$function->addParameter('a')
	->setType(Type::union(Type::INT, Type::FLOAT));

echo $function;

Vypíše:

function twice(int|float $a): int|float
{
	return $a * 2;
}

Pokud parametru nastavíme setNullable(), vygeneruje se korektně int|float|null.

Podporovány jsou i všechny další datové typy, jako například mixed atd.

Pojmenované parametry

Při generování PHP kódu pomocí addBody(), setBody() nebo Dumper::format() lze používat i pojmenované parametry. Klasické poziční parametry vložíme přes placeholder ...?

$items = [1, 2, 3];
$function->setBody('myfunc(...?);', [$items]);
// myfunc(1, 2, 3);

Pro pojemnované parametry se používá ...?:

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