Object of class App\Presenters\ArticlePresenter could not be converted to string – chyba v Latte?
- m.brecher
- Generous Backer | 864
Zkoušel jsem tohle a narazil na chybu v šabloně latte:
Založil jsem si v presenteru konstantu – id, abych ji následně použil pro označení sekce, na kterou by měly vést odkazy:
abstract class PublicPresenter extends BasePresenter
{
public const PRICELIST_SECTION_ID = 'sekce-cenik';
.....
}
mainMenu.latte – tohle funguje:
{var $hash = $presenter::PRICELIST_SECTION_ID}
<a n:href="Article:homepage#$hash, url: null">Ceník</a>
mainMenu.latte – tohle nefunguje:
<a n:href="Article:homepage#$presenter::PRICELIST_SECTION_ID, url: null">Ceník</a>
Vyhodí to výjimku Object of class App\Presenters\ArticlePresenter could not be converted to string
Myslím si, že chybu v syntaxi nedělám a že by latte mělo zvládnout přeložit v n:href makru výraz $presenter::PRICELIST_SECTION_ID, takže dávám podnět pro případnou opravu.
- Polki
- Člen | 553
V makru n:href
je znak :
brán jako oddělovač
Modulů, Presenterů a Akcí.
Místo libovolného modulu/presenteru/akce můžeš dát string proměnnou,
která se do názvu přeloží.
Ovšem jak by podle tebe měla tedy fungovat interpretace toho, co jsi
napsal?
Editoval Polki (12. 12. 2021 0:14)
- nightfish
- Člen | 517
@mbrecher
Obsah makra n:href
se jako řetězec předává do metody
link()
, ve tvém případě by volání vypadalo následovně:
$this->global->uiControl->link("Article:homepage#$presenter::PRICELIST_SECTION_ID, url: null")
A protože PHP nepodporuje interpolaci konstant v rámci řetězců, ani
když je uzavřeš do složených závorek (viz dokumentaci – část „Complex (curly) syntax“ a
poznámku v této sekci), tak při zpracovávání argumentu metody
link()
vidí PHP proměnnou $presenter
, pokusí se ji
nahradit za řetězcovou reprezentaci a selže. Kdybys měl na presenteru
implementovanou metodu __toString()
, tak to sice neselže, ale
výsledný odkaz by tě stejně neuspokojil, protože by obsahovat
/clanky#text_z_metody_toString_presenteru::PRICELIST_SECTION_ID
.
Obávám se, že uvedený problém není na úrovni Latte řešitelný, takže nezbývá než si pomoct uložením hashe do samostatné proměnné.
- Kamil Valenta
- Člen | 815
nightfish napsal(a):
…takže nezbývá než si pomoct uložením hashe do samostatné proměnné.
Nebo si v tom presenteru napsat getter té konstanty.
- m.brecher
- Generous Backer | 864
Dík za vysvětlení problematiky Latte. Pokud PHP nepodporuje statické konstanty v řetězcích, je logické že Latte také ne.
Navíc „injektovat“ konstanty z presenteru do šablony nebude best practice. V presenteru by takovéto konstanty být neměly a do šablony by se měly všechny data předávat ideálně vždy přes presenter/komponentu – pak je pořádek.
Přesunul jsem konstantu do třídy AppUtils, a v presenteru ji injektuji standardním způsobem do proměnné v šabloně latte:
a ) konstantu do třídy AppUtils:
class AppUtils
{
public const PRICELIST_SECTION_ID = 'sekce-cenik';
.......
}
b ) pomocnou třídu AppUtils předat jako závislost do presenteru
c ) v presenteru injektovat konstantu do šablony
abstract class FrontPresenter extends BasePresenter
{
#[Inject] public AppUtils $appUtils;
public function beforeRender()
{
parent::beforeRender();
$this->template->pricelistSectionId = $this->appUtils::PRICELIST_SECTION_ID;
}
}
d ) v latte použít obyčejnou proměnnou
<a n:href="Article:homepage#$pricelistSectionId, url: null">Ceník</a>
O malinko více kódu, ale zato estetičtější ;)
- Kamil Valenta
- Člen | 815
m.brecher napsal(a):
O malinko více kódu, ale zato estetičtější ;)
Zůstal presenter / model přenositelný, aniž by člověk musel extrahovat patřičné konstanty z AppUtils? Neklade to na člověka nároky vědět které konstanty k požadovanému presenteru / modelu patří a které ne?
- m.brecher
- Generous Backer | 864
Polki napsal(a):
V makru
n:href
je znak:
brán jako oddělovač Modulů, Presenterů a Akcí.Místo libovolného modulu/presenteru/akce můžeš dát string proměnnou, která se do názvu přeloží.
Ovšem jak by podle tebe měla tedy fungovat interpretace toho, co jsi napsal?
Ahoj
Ohledně interpretace dvojtečky v n makru by konflikt mezi voláním statické proměnné přes dvě dvojtečky, nebo označením modulu/presenteru jednou dvojtečkou být nemusel. Čistě intuitivně jsem předpokládal, že stejný výraz který píšu v makru {var …} můžu napsat i v makru n:href.
Jak ale napsal jeden z kolegů na můj příspěvěk – ani PHP nepodporuje statickou konstantu v řetězcích – i když si myslím, že pro to není důvod a že by to PHP podporovat mělo. Pak je celkem logické, že Latte, které z PHP ideově vychází to také nepodporuje.
On je to nakonec asi antipattern volat nějakou svoji konstantu někde uprostřed šablony – obchází se tím důležitý princip dependency injection.
Jak řešíš Ty integritu takovýchto pomocných dat – kdy máš nějakou konstantu, obvykle řetězec který použiješ na dvou/třech místech v kódu – např. jako zde html kotva pro odrolování a stejný řetězec použít v odkazu, nebo javascriptu?
- m.brecher
- Generous Backer | 864
Kamil Valenta napsal(a):
m.brecher napsal(a):
O malinko více kódu, ale zato estetičtější ;)
Zůstal presenter / model přenositelný, aniž by člověk musel extrahovat patřičné konstanty z AppUtils? Neklade to na člověka nároky vědět které konstanty k požadovanému presenteru / modelu patří a které ne?
Tato konstanta má jediný účel – zajistit integritu mezi kotvou v html elementu (id) a hashem v url, které na tu kotvu odroluje (popř. v javascriptu), dá se tam napsat řetězec, ale při překlepu se chybu nedozvím.
Hodnota té kotvy je libovolná, je to hodně málo důležitá konstanta. Řekl bych, že je to konstanta pro vykreslování – v odkazu a v příslušné sekci na kterou se roluje, popř. v javascriptu, do kterého se opět nainjektuje v latte. Takže do modelu určitě nepatří. Jako property v presenteru také nemá co dělat – nic neovlivňuje, nic neřídí.
- Kamil Valenta
- Člen | 815
Já to myslel obecně, že sesypávat konstanty na jedno místo není úplně šťastné.
V případě odkazu (než to cpát do každé šablony v beforeRender()) bych zvážil připravit si odkaz v @layout.latte v blocku a pak už jen dle potřeby vykreslovat.
Nebo pokud je to využíváno někdy jako odkaz, někdy jako něco v JS, zvážil bych umístění do komponenty.
- m.brecher
- Generous Backer | 864
Kamil Valenta napsal(a):
Já to myslel obecně, že sesypávat konstanty na jedno místo není úplně šťastné.
V případě odkazu (než to cpát do každé šablony v beforeRender()) bych zvážil připravit si odkaz v @layout.latte v blocku a pak už jen dle potřeby vykreslovat.
Nebo pokud je to využíváno někdy jako odkaz, někdy jako něco v JS, zvážil bych umístění do komponenty.
Já to cpu v beforeRender() v abstraktním presenteru jenom jednou.
Konstantu používám:
- jako hodnotu id html elementu kam se má odrolovat stránka
- jako hash v html odkazu
- jako id html elementu který se javascriptem scroluje aby byl vidět htmlElement.scrollIntoView()
ve všech třech případech to vykresluje šablona – i javascript, takže se to používá v různých šablonách a ideální je injektovat to v abstraktním presenteru, který obsluhuje všechny šablony. Nejde o kus html kódu ale jen a jen o jeden string, který se vejde do jedné proměnné. Dát to do bloku v layout.latte by asi bylo komplikovanější na použití – do latte teprve pronikám, ale myslím, že proměnná vytvořená v jedné šabloně se automaticky do jiných šablon nepřenáší. Přenos proměnných mezi šablonami nějak jde, ale musí se ručně ty proměnné zapisovat.
Nakonec, je možné i to zapsat jednoduše jako string a dát si pozor, aby tam člověk neudělal chybu.
Editoval m.brecher (13. 12. 2021 0:16)