Skip to content
This repository has been archived by the owner on Jul 4, 2018. It is now read-only.

Commit

Permalink
added a way to get the Application in a Controller without using 'use…
Browse files Browse the repository at this point in the history
…' (that also allows the usage of class methods as controllers)
  • Loading branch information
fabpot committed Aug 9, 2011
1 parent 5609fb8 commit 934bf3e
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 16 deletions.
39 changes: 27 additions & 12 deletions doc/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Dynamic routing
Now, you can create another controller for viewing individual blog
posts::

$app->get('/blog/show/{id}', function ($id) use ($app, $blogPosts) {
$app->get('/blog/show/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
if (!isset($blogPosts[$id])) {
$app->abort(404, "Post $id does not exist.");
}
Expand Down Expand Up @@ -152,11 +152,10 @@ feedback form. We will use `Swift Mailer

require_once __DIR__.'/vendor/swiftmailer/lib/swift_required.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

$app->post('/feedback', function () use ($app) {
$request = $app['request'];

$app->post('/feedback', function (Request $request) {
$message = \Swift_Message::newInstance()
->setSubject('[YourSite] Feedback')
->setFrom(array('noreply@yoursite.com'))
Expand All @@ -173,9 +172,8 @@ feedback form. We will use `Swift Mailer
It is pretty straight forward. We include the Swift Mailer library,
set up a message and send that message.

The current ``request`` service is retrieved using the array key syntax.
You can find more information about services in the *Services* chapter.
The request is an instance of `Request
The current ``request`` is automatically injected by Silex to the Closure
thanks to the type hinting. It is an instance of `Request
<http://api.symfony.com/2.0/Symfony/Component/HttpFoundation/Request.html>`_,
so you can fetch variables using the request's ``get`` method.

Expand Down Expand Up @@ -239,6 +237,21 @@ While it's not suggested, you could also do this (note the switched arguments)::
...
});

You can also ask for the current Request and Application object::

$app->get('/blog/show/{id}', function (Application $app, Request $request, $id) {

This comment has been minimized.

Copy link
@igorw

igorw Aug 9, 2011

Contributor

We need to be consistent about Silex\\Application vs Application vs use ($app).

...
});

.. note::

Note for the Application and Request objects, Silex does the injection
based on the type hinting and not on the variable name::

$app->get('/blog/show/{id}', function (Application $foo, Request $bar, $id) {
...
});

Route variables converters
~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -405,7 +418,7 @@ once a response is returned, the following handlers are ignored.

use Symfony\Component\HttpFoundation\Response;

$app->error(function (\Exception $e, $code) {
$app->error(function (\Exception $e, $code) use ($app) {
if ($app['debug']) {
return;
}
Expand All @@ -416,7 +429,7 @@ once a response is returned, the following handlers are ignored.
The error handlers are also called when you use ``abort`` to abort a request
early::

$app->get('/blog/show/{id}', function ($id) use ($app, $blogPosts) {
$app->get('/blog/show/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
if (!isset($blogPosts[$id])) {
$app->abort(404, "Post $id does not exist.");
}
Expand All @@ -430,7 +443,9 @@ Redirects
You can redirect to another page by returning a redirect response, which
you can create by calling the ``redirect`` method::

$app->get('/', function () use ($app) {
use Silex\Application;

$app->get('/', function (Silex\Application $app) {
return $app->redirect('/hello');
});

Expand All @@ -451,7 +466,7 @@ correctly, to prevent Cross-Site-Scripting attacks.
* **Escaping HTML**: PHP provides the ``htmlspecialchars`` function for this.
Silex provides a shortcut ``escape`` method::

$app->get('/name', function () use ($app) {
$app->get('/name', function (Silex\Application $app) {
$name = $app['request']->get('name');
return "You provided the name {$app->escape($name)}.";
});
Expand All @@ -464,7 +479,7 @@ correctly, to prevent Cross-Site-Scripting attacks.

use Symfony\Component\HttpFoundation\Response;

$app->get('/name.json', function () use ($app) {
$app->get('/name.json', function (Silex\Application $app) {
$name = $app['request']->get('name');
return new Response(
json_encode(array('name' => $name)),
Expand Down
6 changes: 3 additions & 3 deletions src/Silex/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
Expand All @@ -36,6 +35,7 @@
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Silex\RedirectableUrlMatcher;
use Silex\ControllerResolver;

/**
* The Silex framework class.
Expand Down Expand Up @@ -82,8 +82,8 @@ public function __construct()
return $dispatcher;
});

$this['resolver'] = $this->share(function () {
return new ControllerResolver();
$this['resolver'] = $this->share(function () use ($app) {
return new ControllerResolver($app);
});

$this['kernel'] = $this->share(function () use ($app) {
Expand Down
52 changes: 52 additions & 0 deletions src/Silex/ControllerResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Silex;

use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
* ControllerResolver.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ControllerResolver extends BaseControllerResolver
{
protected $app;

/**
* Constructor.
*
* @param Application $app An Application instance
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(Application $app, LoggerInterface $logger = null)
{
$this->app = $app;

parent::__construct($logger);
}

protected function doGetArguments(Request $request, $controller, array $parameters)
{
foreach ($parameters as $param) {
if ($param->getClass() && $param->getClass()->isInstance($this->app)) {
$request->attributes->set($param->getName(), $this->app);

break;
}
}

return parent::doGetArguments($request, $controller, $parameters);
}
}
17 changes: 17 additions & 0 deletions tests/Silex/Tests/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,21 @@ public function escapeProvider()
array('abc', 'abc'),
);
}

public function testControllersAsMethods()
{
$app = new Application();
unset($app['exception_handler']);

This comment has been minimized.

Copy link
@igorw

igorw Aug 9, 2011

Contributor

Indentation.

This comment has been minimized.

Copy link
@fabpot

fabpot Aug 9, 2011

Author Member

oops, this was a leftover. removed now.

$app->get('/{name}', 'Silex\Tests\FooController::barAction');

$this->assertEquals('Hello Fabien', $app->handle(Request::create('/Fabien'))->getContent());
}
}

class FooController
{
public function barAction(Application $app, $name)
{
return 'Hello '.$app->escape($name);
}
}
35 changes: 35 additions & 0 deletions tests/Silex/Tests/ControllerResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Silex\Tests;

use Silex\ControllerResolver;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;

/**
* ControllerResolver test cases.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ControllerResolverTest extends \PHPUnit_Framework_TestCase
{
public function testGetArguments()
{
$app = new Application();
$resolver = new ControllerResolver($app);

$controller = function (Application $app) {};

$args = $resolver->getArguments(Request::create('/'), $controller);
$this->assertSame($app, $args[0]);
}
}
2 changes: 1 addition & 1 deletion vendor/Symfony/Component/HttpKernel

0 comments on commit 934bf3e

Please sign in to comment.