On 10/27/10 12:23 AM, Lukas Kahwe Smith wrote:
Hi,

I think the _format routing magic needs a bit of tweaking to be really useful.

Summary:
2) Make it possible to define some format specific view logic (json_encode(), 
generate pdf/image etc)

You might have noticed that I always say that a controller should return a Response (I never say "must"). That's because you can implement a View if you want/need to. Let me show you a simple example for JSON.

First, instead of returning a Response, the controller can return anything you want, like a View instance for example:

public function someAction()
{
    return new JsonView(array('foo' => 'bar'));
}

Then, define the JsonView class (you can do whatever you want in the toResponse() method):

use Symfony\Component\HttpFoundation\Response;

class JsonView
{
    protected $parameters;

    public function __construct(array $parameters)
    {
        $this->parameters = $parameters;
    }

    public function toResponse()
    {
        return new Response(
            json_encode($this->parameters),
            200,
            array('content-type' => 'application/json')
        );
    }
}

If the controller does not return a Response, you need to implement a core.view listener to convert it to a proper Response instance:

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

class JsonViewListener
{
    public function register(EventDispatcher $dispatcher)
    {
        $dispatcher->connect('core.view', array($this, 'toResponse'));
    }

    public function toResponse(Event $event, $retval)
    {
        if (!$retval instanceof JsonView) {
            return $retval;
        }

        return $retval->toResponse();
    }
}

Eventually, register your listener:

<service id="view.json" class="...\View\JsonViewListener">
    <tag name="kernel.listener" />
</service>

This example show you how you can implement a generic view. The same technique can also be used if you want to define a View for all your controllers. A View can deal with HTTP headers, template choice logic, caching, ... That way, your controller responsibility is just about getting data from the Model and passing them to the View. One of the goal of the FrameworkExtraBundle (http://bundles.symfony-reloaded.org/frameworkextrabundle/) is to avoid View implementation for simple/common use cases. By providing annotations for common Response tweaking, it allows you to have a clean controller without the need for implementing a View (see the tip on the doc page).

Of course, you can argue that it would be a good idea to "standardize" the way generic View classes are defined. For instance, we might have an interface like this one in the Symfony2 core:

interface ViewInterface
{
    public function toResponse();
}

For Views implementing this interface, we can then have a generic listener that will work for all implementation:

class GenericViewListener
{
    public function register(EventDispatcher $dispatcher)
    {
        $dispatcher->connect('core.view', array($this, 'toResponse'));
    }

    public function toResponse(Event $event, $retval)
    {
        if (!$retval instanceof ViewInterface) {
            return $retval;
        }

        return $retval->toResponse();
    }
}

With that code in the core, we can also probably provide some generic View class implementations in the core (like the JSON one).

That's a possibility... and something I wanted to talk about and play with for quite some time now... but I just hadn't the time to do so...

So, your question is good way to get the discussion started on that topic :) Comments welcomed...

Fabien

--
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-devs?hl=en

Reply via email to