Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC]: Massive BC Break and Simplification of laminas-view #149

Open
gsteel opened this issue Feb 23, 2022 · 5 comments
Open

[RFC]: Massive BC Break and Simplification of laminas-view #149

gsteel opened this issue Feb 23, 2022 · 5 comments
Labels
Milestone

Comments

@gsteel
Copy link
Member

gsteel commented Feb 23, 2022

With the approaching 3.0 release, I'd like to propose a significant simplification of the laminas-view rendering architecture so that it consists of fewer components with smaller apis.

  • A Template resolver (of which there should remain a number of implementations to satisfy the use case of different resolution mechanisms and directory layouts) becomes a hard dependency of the template renderer.
  • Remove the concept of rendering strategies
  • Remove all renderers but the PHP renderer.
  • The helper plugin manager becomes a hard dependency of the concrete renderer.
  • Potentially, View and PhpRenderer become the same thing.

Effectively setting up a complete, fully functioning template renderer would then become:

$templateResolver = new TemplateResolver('/template-directory');
$pluginManager = new ViewHelperManager([/** configuration */]);
$renderer = new PhpRenderer($templateResolver, $pluginManager);

$viewModel = new ViewModel(/** Stuff **/);

$content = $renderer->renderSomething('template', $viewModel);

// Much like Mezzio…

The existing render($nameOrModel, $vars = null) could be preserved with additional methods such as renderModel(ViewModel $model): string - where the view model is reponsible for exposing the template to render and renderTemplate(string $name, iterable $variables)

Removals

  • Renderer\FeedRenderer and Strategy\FeedStrategy can go in the bin. If you have a feed, what do you need a templating engine for? Surely laminas-feed has your back there?
  • Renderer\JsonRenderer and Strategy\JsonStrategy are surely dead? It is much simpler to return a Json encoded Response from Middleware/Controller that to muck about in the view layer…
  • Console rendering is already deprecated for removal in 3.0 - Remove laminas-console dependency #126
  • Anything that mentions a request or a response.

The renderer…

…itself should be vastly simplified, removing all property and method overloading and any non-essential state. Runtime mutation such as setting the template resolver, filter chain etc should be removed.

Filtering content post render

Can be satisfied by laminas-filter as it is now, or made implementation agnostic by providing a way to register callbacks.

MVC

Obviously, this will all be thoroughly incompatible with MVC, but 2.x isn't going anywhere.

Events

May become moot - in MVC for example, given a renderer it can populate its response body with the output on its own terms.

View Helpers

Should not be initialised at runtime with anything - i.e. setView and getView. If they need access to the renderer for any reason, define a factory and consume it in the constructor. The same goes for collaborating helpers. Rather than $this->getView()?->plugin('maybe-the-right-thing')?->doStuff(), require that any helper will need to declare all its dependencies up-front.

URLs

One of the most important jobs view does is of course $this->url('route-name') for which I'd propose providing a view helper that depends on laminas-router - I believe that BaseUrls and Base Paths should be handled by configuration so that there is a consistent and reliable way of generating absolute uris when you're on or off the web.

Placeholders and Stateful View Helpers

Are a great feature, allowing you to modify from within nested templates, but bring a lot of state problems.

Initially, I think that this could be solved by a view-specific plugin manager implementation (#123) that tears down all the plugins/view helpers for each complete, outermost render.

@gsteel gsteel added the RFC label Feb 23, 2022
@froschdesign
Copy link
Member

@gsteel
First: I like the direction, but I the massiv BC break is a big problem and this should be discussed at the next TSC meeting. Please put this on the agenda. Thanks! 👍

@froschdesign
Copy link
Member

That is one point why I think we need some more discussions:

  • Renderer\FeedRenderer and Strategy\FeedStrategy can go in the bin. If you have a feed, what do you need a templating engine for? Surely laminas-feed has your back there?

Unfortunately, you are overlooking a crucial point here, because it is all about ease of use. In the current version of laminas-mvc and laminas-view you can write:

use Laminas\Feed\Writer\Feed;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\FeedModel;

class AlbumController extends AbstractActionController
{
    public function feedAction(): FeedModel
    {
        $feed = new Feed();

        // add entries…

        return (new FeedModel())->setFeed($feed);
    }
}

What is the current alternative? Right, it is ugly and user-unfriendly.

That was the goal of the original implementation, ease of use.
Can it be solved better? Definitely, but before throwing this away, a simple alternative should also be available. And staying with an old version does not sound like the right strategy to me. Especially when we look at laminas-mvc.

@gsteel
Copy link
Member Author

gsteel commented Feb 24, 2022

IMO, removal of features like this is part of the whole idea. I'm a bit out of touch with MVC these days, but I would personally solve the same problem with something like:

public function feedAction(): Response
{
    $feed = new Feed();
    
    // add entries, assuming content is markup…
    foreach ($entries as $entry) {
        $entry->setDescription(
           $this->templateRenderer->render('entry-template', $entryModel)
        );
    }

    $response = new Response(); // or getResponse() ??
    $response->setBody($feed->getXml());
    $response->setHeadersToWhatever();
    
    return $response;
}

Things like rendering json and xml content just feel completely out of scope for primarily a templating library and I think that if rendering Feed responses is required to be easy in MVC, then it should be MVCs problem, not view's ??

@froschdesign
Copy link
Member

but I would personally solve the same problem with something like:

$response = new Response(); // or getResponse() ??
$response->setBody($feed->getXml());
$response->setHeadersToWhatever();

But this is not user-friendly! 😄

Things like rendering json and xml content just feel completely out of scope for primarily a templating library and I think that if rendering Feed responses is required to be easy in MVC, then it should be MVCs problem, not view's ??

That's why I also wrote, it can definitely be solved better, but it must be simple. Setting a header yourself is not easy! The information that it is an RSS or Atom feed, including the encoding, is already present, so why should the user add the header themselves?

return new FeedResponse($feed);

Like with laminas-diactoros and the custom response.


With this, I just want to point out that it is not so easy to throw an existing solution that serves the ease of use without having an alternative.

@froschdesign
Copy link
Member

The results of the meeting can be read in the minutes from the 2022-04-04.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants