Oh, forgot to mention. `ReadableResourceInterface 
<https://github.com/Dhii/io-resource-interface/blob/task/initial-interfaces/src/ReadableResourceInterface.php>`,
 
and this whole new standard, was originally created because I thought that 
it should be possible to stream templates for *reading*. Thanks for 
pointing out that it is a good idea to stream the output, too!

$file = new Stream('my-mustache-template');
$template = new MustacheTemplate($file);
$context = new DataObject(['name' => 'Xedin']);
$outputStream = $template->render($context);


On Sunday, September 24, 2017 at 9:09:37 PM UTC+2, David Négrier wrote:
>
> Hey Thomas,
>
> Absolutely +1 with you regarding the need of "renderer" PSR.
>
> @Xedin: I just saw your work and I very much like the path you are 
> following with the TemplateInterface (
> https://github.com/Dhii/output-renderer-interface/blob/develop/src/TemplateInterface.php
> )
>
> @Thomas, @Hari, in the interfaces you propose, you introduce the notion of 
> a "$templatePath" (or template name in Zend). That is, your objects are 
> responsible for 2 things:
> 1 => fetching the template
> 2 => rendering the template
>
> These are 2 separate concerns and when it comes to a PSR, I believe that 
> we should only focus on the rendering part.
>
> Let me explain.
>
> Let's assume I have some code that renders a page using Twig:
>
> $this->renderer->render('path/to/index.twig', $data);
>
> If I want to switch my renderer implementation to a Plate template, I 
> cannot simply switch the renderer, I also need to change the path to the 
> template:
>
> $this->renderer->render('path/to/index.plate', $data);
>
> OR, I need to go in great details to invent a convention that 
> automatically adds the file extension to the template....
>
> Like this:
>
> $this->renderer->render('path/to/index', $data);
>
> Notice that this is something that Zend is doing: 
> https://github.com/zendframework/zend-expressive-template/blob/master/src/TemplateRendererInterface.php#L23-L24
>
> I believe that instead of representing a "renderer", we should focus on 
> objects that represents the template (like what Xedin Unknown is doing).
>
> This way, you can switch from one template to another, using simple 
> dependency injection!
>
> The interface should therefore be:
>
> interface TemplateInterface {
>     public functiion render(array $context): string
> }
>
> Now, I have 2 additional comments to make.
>
> By type-hinting to "array", we cannot use a context that would implement 
> "ArrayAccess". This can be useful in order to lazily evaluate the context. 
> Si I would switch this to;
>
> interface TemplateInterface {
>     /**
>      * @param array|ArrayAccess $context
>      */
>     public functiion render($context): string
> }
>
> Finally, regarding the return type, Hari is completely right to say that 
> we don't want a ResponseInterface (because this is not necessarily related 
> to an HTTP response). We could very well be rendereding a static HTML page 
> stored on disk, or rendering an email.
> However, we could improve over a simple "string" by using PSR-7 
> StreamInterface. That would allow for big responses that do not fit in 
> memory.
>
> So my ideal interface would be:
>
> interface TemplateInterface {
>     /**
>      * @param array|ArrayAccess $context
>      */
>     public functiion render($context): StreamInterface
> }
>
> ++
> David.
>
>
>
> Le dimanche 24 septembre 2017 15:16:06 UTC+2, Xedin Unknown a écrit :
>>
>> The changes that were pending are now merged, and can be found on the 
>> `develop` branch of the repos I mentioned. I hope this helps.
>>
>> The next step for be is to create package with base abstract 
>> implementations, which still lack the key logic, but save time for the 
>> implementors by including concrete logic for common things, like throwing 
>> exceptions, normalization, etc. It would be great to get an opinion from 
>> the honorable participants of this group :)
>>
>> On Sunday, September 24, 2017 at 10:32:17 AM UTC+2, Xedin Unknown wrote:
>>>
>>> Hi all,
>>>
>>> This is a good idea, and we are already working on this for the project 
>>> that is being built. Please take a look at 
>>> dhii/output-renderer-interface 
>>> <https://github.com/Dhii/output-renderer-interface/tree/develop>. The 
>>> readme should explain most of the things. I will try to describe how things 
>>> will work below. Please note that this is a work in progress; however, many 
>>> hours have been dedicated to making this standard as useful as possible. I 
>>> hope that it will be a good inspiration for a PSR.
>>>
>>> To put things simply, you have a `RendererInterface`, which is anything 
>>> that can produce output. This requires it to already have access to all 
>>> data that is necessary for rendering. A `BlockInterface` is a renderer that 
>>> can be cast to string, which is possible if it has sufficient data. 
>>> Interoperability is ensured via `StringableInterface`. A 
>>> `ContextRendererInterface` is something that can use a context, i.e. 
>>> additional data, for rendering. This is great for renderers, the instances 
>>> of which can be re-used to render the same "template" multiple times with 
>>> different data. The "aware" interfaces are for greater interop between 
>>> consumers of the main interfaces. Exception interfaces provide access to 
>>> aspects of the rendering, which allows obtaining information about the 
>>> rendering process without being aware of the internals of the 
>>> implementation, and without having prior reference to the instance, which 
>>> is very helpful and is a rule that we use in all standards.
>>>
>>> dhii/output-renderer-abstract 
>>> <https://github.com/Dhii/output-renderer-abstract/tree/task/initial-classes>
>>>  is 
>>> an abstract implementation, and a work in progress as well. Blocks are free 
>>> to produce output in any way they wish, so this package has just the most 
>>> abstract functionality. Right now, I am working on an 
>>> `AbstractTemplateBlock`, which uses a template to get rendered. While 
>>> designing this class, I realised (and this is a very important point) that 
>>> very good SoC can be achieved by encapsulating templates in a class that 
>>> represents a template. Without this, it doesn't seem practical to 
>>> standardize block logic to work with different templates. With templates as 
>>> a class, it's possible to render a template that works in any way inside a 
>>> block (or elsewhere). A template IMHO is just a way of saying "a form for 
>>> output that can be filled with values". In this case, a value is a 
>>> rendering context, and there is already an interface that does this - the 
>>> `ContextRendererInterface`. This is why a rename of this interface to 
>>> `TemplateInterface` is pending - because this is exactly what it is, and 
>>> it's more concise and expressive. I will be pushing the rename, as well as 
>>> the `AbstractTemplateBlock`, in a couple of hours, so that you can see the 
>>> usage.
>>>
>>> If a workgroup is being assembled to work on this standard, I would very 
>>> much like to be part of it. I have spent a lot of time standardizing output 
>>> mechanisms, and other things, very much inspired by the spirit and letter 
>>> of FIG. I will also gladly share my plans for the future standards and 
>>> implementations, as well as present other standards which I have been 
>>> working on. Many of them are being used in production by me and my team, 
>>> and are working very well so far.
>>>
>>>
>>>
>>> On Saturday, September 23, 2017 at 7:45:53 PM UTC+2, Thomas Gnandt wrote:
>>>>
>>>> With the upcoming http-middleware PSR which defines the 
>>>> RequestHandlerInterface it becomes possible to write framework independent 
>>>> modules that include ready-to-use actions (instances of 
>>>> RequestHandlerInterface). However this is not possible, until a common 
>>>> interface to render a template exists.
>>>> Any action that should work in multiple applications has to render the 
>>>> body of the response using templates, that are not part of the module 
>>>> itself. While example templates may be included in the module, these are 
>>>> generally not usable by the application that uses the module.
>>>> It therefore doesn't make sense to include a specific template engine 
>>>> as a requirement of the module. Since templates are written using engine 
>>>> specific syntax it is not feasible to use multiple template engines.
>>>> Consequently an application could only use modules that support the 
>>>> engine the application wants to use.
>>>>
>>>> In order to make the used template engine interchangeable a simple 
>>>> interface could be defined:
>>>>
>>>> interface TemplateRendererInterface
>>>> {
>>>>     public function render(ResponseInterface $response, string 
>>>> $templatePath, array $data = null): ResponseInterface;
>>>> }
>>>>
>>>> This would render the defined template with any data provided and write 
>>>> it to the body of the response.
>>>> Alternatively the following interface could be defined:
>>>>
>>>> interface TemplateRendererInterface
>>>> {
>>>>     public function render( string $templatePath, array $data = null): 
>>>> string;
>>>> }
>>>>
>>>> This provides greater flexibilty while the first interface provides 
>>>> easier usage in the specified use case (for request handlers).
>>>>
>>>

-- 
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 post to this group, send email to php-fig@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/cc62c26e-e072-4c1b-9080-163235085878%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to