Podpora PHP 8.1 enumeration v Latte a Presenterech
- m.brecher
- Generous Backer | 863
Ahoj,
PHP 8.1 přinesla enumeration které nabízejí typovou kontrolu nad parametry, kde potřebujeme několik konkrétních hodnot. Kupříkladu mám formulář, kde ve 3 po sobě jdoucích krocích provádím nějaké akce. Stav formuláře chci řídit parametrem akce v presenteru, který bude mít přesně tři string hodnoty.
Rád bych použil enum v parametrech akce stejně jako se dnes používá integer parametr $id, který Nette správně přetypuje na string do url (v odkazech) a zase zpět přetypuje na int (v metodě akce v presenteru, nebo parametrech s atributem #[Parameter] a #[Persistent]).
Zkusil jsem využít backed enum:
namespace App\Presenters\Ledger;
enum Step: string // definice enumu:
{
case SelectBookUnit = 'selectBookUnit';
case SelectInvoice = 'selectInvoice';
case SelectInvoiceItem = 'selectInvoiceItem';
}
namespace App\Presenters\Ledger;
class LedgerPresenter extends BasePresenter // presenter
{
public function actionCreate(?Step $step = null) // enum Step
{
$this->template->Step = $step;
}
}
{* šablona akce *}
{varType App\Presenters\Ledger\Step $Step}
{block 'content'}
<nav class="menu">
<a n:href=":create, step: $Step::SelectBook">vyber účetnictví</a> {* enum jako parametr odkazu *}
</nav>
{/block}
Narazil jsem na tyto výjimky:
Po ručním zadání do url: localhost/project/ledger/create?step=selectBook Nette automaticky nepřetypuje string na enum:
Nette\Application\BadRequestException #404
Argument $step passed to App\Presenters\Ledger\LedgerPresenter::actionCreate()
must be App\Presenters\Ledger\Step, string given.
Použití enum v odkazech v Latte dopadlo podobně:
{varType App\Presenters\Ledger\Step $Step}
<a n:href=":create, step: $Step::SelectBook">vyber účetnictví</a>
Latte vyhodí výjimku když narazí v odkaze na enum hodnotu:
Error
Class name must be a valid object or a string
Závěr: PHP enum není v Nette jako parametr odkazu podporován. Podpora enum typu je ale zajímavá nová feature, která by přinesla vyšší preciznost a snížila riziko chyb.
Jaký máte názor, využili by jste podporu enumu v Latte a presenterech ?
Editoval m.brecher (8. 1. 16:01)
- nightfish
- Člen | 516
Jaký máte názor, využili by jste podporu enumu v Latte a presenterech ?
Tak určitě.
Enumy sice jde v klidu použít už teď, ale je k tomu holt potřeba boilerplate:
public function actionDefault(?string $stepValue = null): void
{
$step = Step::tryFrom($stepValue);
if ($step === null) {
$this->error();
}
// práce se $step typu Step
}
Šablona
<a n:href=":create, stepValue: App\Presenters\Ledger\Step::SelectBook->value">vyber účetnictví</a>
- m.brecher
- Generous Backer | 863
@nightfish
Tak určitě.
tak super !
<a n:href=":'create', stepValue: App\Presenters\Ledger\Step::SelectBook->value"> {* funkční ale nečitelné *}
<a n:href=":'create', step: $Step::SelectBook"> {* čitelné, ale nefunkční :( *}
<a n:href=":'create', step: 'selectBook'"> {* string klasika nyní nejlepší řešení *}
Smyslem enumu je zpřehlednit kód, a snížit riziko chyb. To že jde enum použít přes boilerplate to vím, ale smysl má použít jednoduchý čitelný zápis, protože boilerplate kód znepřehledňuje a naopak si myslím, že funkční, ale nečitelný zápis enumu je víc náchylný na chybu než použití normálního stringu.
- Lumeriol
- Generous Backer | 62
Za mně používám asi trochu krkolomné řešení s definicí proměnné:
{var App\Model\Enum\Ledger $ledger = App\Model\Enum\Ledger::class}
...
<a n:href=":'create', stepValue: $ledger::SelectBook->value">
Není to ideál, ale nemusím psát stringy/čísla a nemusím psát celý namespace pokud to potřebuju na víc místech. Navíc lze případně použít i statickou funkci definovanou v daném Enumu.
- David Grudl
- Nette Core | 8218
BTW tohle v Latte je ok, ale musíš do proměnné $Step dat jméno třídy:
{var $Step = App\Presenters\Ledger\Step::class}
<a n:href=":create, step: $Step::SelectBook">vyber účetnictví</a>
- Pavel Kravčík
- Člen | 1194
Boiler plate je v pohodě. Škoda, že to nejde bez něj. Včera jsem na to koukal, ale asi by to potřebovalo větší zásah.