what's wrong with this?

$engine->render('models/user', $data);

every engine takes a logical template name, and applies whatever convention
it uses - which for
most engines would mean adding the appropriate root path and file
extension, while other engines
might use the first part of the logical name to map to one of several
registered root paths.

> the only viable approach I've heard is to not do that and instead use
view models, so the
> type system becomes the abstraction

this doesn't really change anything though - under the hood, that
view-model name still needs to
be resolved to an engine-specific absolute template path with a file
extension.

so you still have the exact same problem - now it's just one layer below
the thing you're looking at.

the ViewModelRenderer needs to do everything a TemplateRenderer would need
to do, and more.

I don't think there's any way around that - but that's probably okay?
depending on what you think
this kind of abstraction buys you in the first place? :-)

for me, it would be something like: I can ship a login service module, and
this module can send a
password recovery email - that service can call
$engine->render('login-service/lost-password', $data)
and by injecting a different $engine you can choose the template syntax
you'd like to use in your
project for that service, with the path/filename conventions appropriate
for that engine.

in terms of interoperability, what else were you hoping for? :-)

Rasmus


On Fri, Jan 12, 2024 at 6:05 PM Larry Garfield <la...@garfieldtech.com>
wrote:

> On Fri, Jan 12, 2024, at 4:19 PM, Rasmus Schultz wrote:
> >> The problem there is that if you want to add a constructor argument to
> one of the child classes, PHP itself now makes that really ugly to do.
> (This is a PHP limitation.) It also means an explosion of child classes
> even if you don't add properties; Adding a new output type to an existing
> system with 300 view models means adding 300 classes. That's not good.
> >>
> >> If we instead did:
> >>
> >> $engine->render($articleView, format: 'rss')
> >
> > for the record, this is precisely what we ended up doing, for exactly
> > that reason - to avoid the potential view-model explosion.
> >
> > if anyone is interested in trying it out, it's available here:
> > https://github.com/mindplay-dk/kisstpl
> >
> > it's been used at scale in a large modular codebase with many
> > contributors - people liked it, it worked and held up very well over
> > time.
> >
> > I will emphasize this again though:
> >
> > 1. changing this library to internally compose an $engine and call
> > $engine->render($path) would be extremely easy
> > 2. the simpler $engine->render($path) approach aligns perfectly with
> > most engines and provides all the interoperability we need
> >
> > the $engine->render($path) approach is a more low-level approach than
> > the $engine->render($viewModel, "format") approach.
> >
> > I obviously prefer the view-model approach - but personal preferences
> > and opinions doesn't really mean much here.
> >
> > PSR interfaces are supposed to provide interoperability, and the fact
> > is that the $engine->render($path) approach, being a near
> > perfect match for existing template engines, does that better.
> >
> > if we went with the more opinionated view-model approach, I can
> > practically guarantee, the PSR will see much less adoption,
> > because it won't fit existing engines very well, and it won't align
> > well with "end user" developer expectations - they will basically
> > all need to individually implement something similar to my view-finder
> > package above, because that's really like a more high-level
> > abstraction than the more low-level $engine->render($path) approach,
> > which is easy to add on top.
> >
> > I would compare this situation to the PSR cache situation - and the
> > outcome would very likely be the same. If we standardize on
> > the more high-level $engine->render($viewModel, "path") approach, as
> > the original PSR-6 caching interface did, we would almost
> > definitely end up with a second "Simple Template Renderer" PSR later
> > on, like how PSR-16 simplified caching.
> >
> > if you're really adamant about pushing the view-model approach on the
> > community, I would actually suggest you consider
> > including *both* interfaces in the PSR: the low-level TemplateRenderer
> > and high-level ViewModelRenderer.
> >
> > I could definitely see benefits to standardizing both.
> >
> > but standardizing on just the ViewModelRenderer would be almost
> > poignant - there is my package and maybe one or two others
> > using that approach (?) so maybe it has a bit of value in terms of
> > interoperability, but for the majority of template engines, it would
> > just be a hassle to implement, whereas TemplateRenderer would be an
> > easy slam dunk for practically every engine out there.
> >
> > another case for two interfaces would be composability - since most
> > template engines support something like TemplateRenderer
> > already, those implementations could focus on just the "template name
> > to path" convention, while a ViewModelRenderer implementation
> > could compose a TemplateRenderer implementation, focusing on just the
> > "view model and format to template name" convention.
> >
> > I actually don't see these as competing ideas, but potentially as
> > complimentary ideas.
> >
> > in my opinion, this approach makes for better architecture, better
> > separation of concerns. ("do one thing and do it well".)
> >
> > having two interfaces with a shared concept of "template names" might
> > make a lot of sense here?
> >
> > community wise, I think that putting both ideas out there and letting
> > nature decide would be a lot less biased than trying to pick one?
> >
> > Rasmus
>
> I fully agree about the adoption challenge of a view-model-centric
> approach, and have said as much repeatedly. :-)  A dual-design is an
> option, but it doesn't resolve the primary blocker of a path-based approach:
>
> $engine->render('models/user.twig', $data);
> $engine->render('models/user.latte', $data);
> $engine->render('models/user.blade', $data);
> $engine->render('models/user.smarty', $data);
>
> Absent some good way to standardize the path string in an
> engine-independent way, I don't see how that can ever be a meaningful
> abstraction.  Just accepting TemplateInterface in my class doesn't make it
> portable if I still have to specify ".twig" in the path.  That is the
> problem that has to be solved, to the satisfaction of the big players,
> before that approach is viable at all.
>
> So far, the only viable approach I've heard is to not do that and instead
> use view models, so the type system becomes the abstraction.  Which it
> seems the consensus is "that would be really cool, but nobody actually does
> that so transitioning would be awful."
>
> So I still don't see a viable way forward, much as I wish I did.
>
> What we really need is for someone from Twig or Blade to weigh in.
> Unfortunately, that seems unlikely.
>
> --Larry Garfield
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "PHP Framework Interoperability Group" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/php-fig/X4e1z5IaG9E/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> php-fig+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/4dcd1e45-239a-45ce-8bb8-8332406bd4d5%40app.fastmail.com
> .
>

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to php-fig+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/CADqTB_iYBUF97wJr42JOOP2gfGzRWyr7z9BKjDEUbh2sXLrQiw%40mail.gmail.com.

Reply via email to