Sorry if this has already come up earlier in the thread, but I just realized I 
sometimes have multiple routes that point to the same symfony 1 action. Will 
this be possible Symfony 2, or is it required that route and action parameters 
match exactly?

For example, I might have two distinct routes, homepage and category, that both 
point to an action that lists blog articles. I would assume I could direct each 
of these routes to this Symfony 2 action:

public function listArticles($category = null)
{
}

Will it be possible to point a route that doesn't have a category parameter at 
this action?

Thanks,
Kris

--

Kris Wallsmith | Release Manager
[email protected]
Portland, Oregon USA

http://twitter.com/kriswallsmith

On Mar 30, 2010, at 1:24 AM, Fabien Potencier wrote:

> Hi all,
> 
> Last week, I took the time to play with the implementation of the main 
> approaches discussed in the controllers RFC. I also wrote some unit tests to 
> see how it feels. During this journey, I discovered that writing a RFC 
> without any implementation is quite difficult (my apologizes for this). But I 
> learned a lot, and discovered that some approaches look rather impractical in 
> real-world scenarios.
> 
> This email is an attempt to explain my findings and my concerns about some 
> approaches and why they are not as good as they seem to be in the RFC. If you 
> don't want to read the whole email, which is quite long, let me give you the 
> main conclusions right away:
> 
> * For the common cases, the controller needs the Container object (if not, 
> you loose a lot of shortcuts provided by the Controller base class, or you 
> are forced to inject a lot of services you don't need because they are used 
> by the parent class methods);
> 
> * Approach 1 (yes, the one currently implemented) is the best implementation 
> (simple, fast, easy);
> 
> * If you like to have the Request object in the controller signatures instead 
> of just the routing variables, then Approach 1, where we change the 
> controller method arguments to just the Request objet, is also a working 
> approach (see my previous email to understand why I think it is a less 
> attractive approach);
> 
> * Other approaches are not exciting anymore as the Container should be 
> injected at some point. So, injecting services in the controller constructor 
> or methods is just a convenient shortcut, nothing more.
> 
> Now, for the longer story.
> 
> My initial point of view was to be able to test a controller as any other 
> method; just by calling it and checking the result. That's possible for 
> simple controllers like the following one:
> 
>  public function showAction($name)
>  {
>    return new Response('Hello '.$name);
>  }
> 
> If you like to have the Request object injected, here is the equivalent:
> 
>  public function showAction(Request $request)
>  {
>    return new Response('Hello '.$request->getPathParameter('name'));
>  }
> 
> With such a controller, writing a unit test is straightforward:
> 
> class HelloControllerTest extends \PHPUnit_Framework_TestCase
> {
>  public function testShowAction()
>  {
>    $container = new Container();
>    $controller = new HelloController($container);
> 
>    $response = $controller->indexAction('Fabien');
> 
>    $this->assertRegexp('/Hello/', $response->getContent());
>  }
> }
> 
> The controller only relies on the request, and as such, if you use some 
> approaches where you inject services manually, it will still be easy (or even 
> easier to test as we remove the need for the container):
> 
> class HelloControllerTest extends \PHPUnit_Framework_TestCase
> {
>  public function testShowAction()
>  {
>    $request = new Request();
>    $request->setPathParameters(array('name' => 'Fabien'));
> 
>    $container = new Container();
>    $controller = new HelloController($container);
> 
>    $controller = new HelloController($container);
> 
>    $response = $controller->indexAction($request);
> 
>    $this->assertRegexp('/Hello/', $response->getContent());
>  }
> }
> 
> Also, if you need a database connection to do your job, it's still easy 
> enough:
> 
> public function showAction(Request $request, DatabaseConnection $conn)
> {
>  // do something with the $conn
> 
>  return new Response('Hello '.$request->getPathParameter('name'));
> }
> 
> In such cases, testing is also still easy:
> 
> class HelloControllerTest extends \PHPUnit_Framework_TestCase
> {
>  public function testShowAction()
>  {
>    $request = new Request();
>    $request->setPathParameters(array('name' => 'Fabien'));
>    $conn = new DatabaseConnection(...);
> 
>    $controller = new HelloController();
> 
>    $response = $controller->indexAction($request, $conn);
> 
>    $this->assertRegexp('/Hello/', $response->getContent());
>  }
> }
> 
> But easiness stops here. As soon as you write "richer" controllers, problems
> comes very fast. The main problem is with "hidden" dependencies. Consider the
> following example:
> 
> public function indexAction()
> {
>  return $this->render('BlogBundle:Post:index');
> }
> 
> Behind the scene, the `render()` method needs the `templating` service; no 
> big deal. And if you want to forward to another action, you need the 
> `controller_loader` service. That's easy enough, even if it feels a bit magic 
> as the end user controller does not really use the service directly:
> 
> public function __construct($templating)
> {
>  $this->templating = $templating;
> }
> 
> public function indexAction()
> {
>  return $this->render('BlogBundle:Post:index');
> }
> 
> But when it comes to testing, things are much more complex. Because the 
> templating needs a loader, helpers, and some more services. So, re-creating 
> the dependency graph (with mock objects or not) is a more difficult. At this 
> point, you will probably just use the container in your test to create the 
> dependencies automatically (with a special configuration for the test 
> environment of course).
> 
> For this reason, and after having played with all approaches and their 
> corresponding unit tests, I think that a controller needs the full container 
> object. With this in mind, testing becomes easy again no matter what:
> 
> public function setUp()
> {
>  $kernel = new \BlogKernel('dev', true);
>  $kernel->boot();
> 
>  $this->container = $kernel->getContainer();
> }
> 
> public function testIndexAction()
> {
>  $controller = new PostController($this->container);
>  $response = $controller->indexAction();
> 
>  $this->assertRegexp('/Hello/', $response->getContent());
> }
> 
> Of course, the boilerplate code can be abstracted in a sub-class of the 
> PHPUnit Test Case class.
> 
> That works for most controllers. And if you want to do "functional" tests, 
> it's as easy as unit tests, as you can just ask the request handler to handle 
> the request for you.
> 
> public function setUp()
> {
>  $this->kernel = new \BlogKernel('dev', true);
>  $this->kernel->boot();
> }
> 
> public function testIndexAction()
> {
>  $request = new Request($get, $post, $...);
>  $response = $this->kernel->handle($request);
> 
>  $this->assertRegexp('/Archives/', $response->getContent());
> }
> 
> As before, we will provide a sub-class of Test Case to abstract the 
> boilerplate code.
> 
> Sorry for the very long post but the controller implementation is at the 
> heart of an MVC framework and as such the final decision about which approach 
> to use should be taken carefully.
> 
> As always all comments are very welcome.
> 
> Fabien
> 
> --
> Fabien Potencier
> Sensio CEO - symfony lead developer
> sensiolabs.com | symfony-project.org | fabien.potencier.org
> Tél: +33 1 40 99 80 80
> 
> -- 
> 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
> 
> To unsubscribe from this group, send email to 
> symfony-devs+unsubscribegooglegroups.com or reply to this email with the 
> words "REMOVE ME" as the subject.

-- 
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

To unsubscribe from this group, send email to 
symfony-devs+unsubscribegooglegroups.com or reply to this email with the words 
"REMOVE ME" as the subject.

Reply via email to