SensioFrameworkExtraBundle
The default Symfony FrameworkBundle
implements a basic but robust and
flexible MVC framework. SensioFrameworkExtraBundle extends it to add sweet
conventions and annotations. It allows for more concise controllers.
Installation
An official Symfony recipe is available for this bundle. To automatically install and configure it run:
1
$ composer require sensio/framework-extra-bundle
You're done!
Configuration
All features provided by the bundle are enabled by default when the bundle is registered in your Kernel class.
The default configuration is as follow:
1 2 3 4 5 6
sensio_framework_extra:
router: { annotations: true } # Deprecated; use routing annotations of Symfony core instead
request: { converters: true, auto_convert: true }
view: { annotations: true }
cache: { annotations: true }
security: { annotations: true }
1 2 3 4 5 6 7 8
<!-- xmlns:sensio-framework-extra="http://symfony.com/schema/dic/symfony_extra" -->
<sensio-framework-extra:config>
<router annotations="true" />
<request converters="true" auto_convert="true" />
<view annotations="true" />
<cache annotations="true" />
<security annotations="true" />
</sensio-framework-extra:config>
1 2 3 4 5 6 7 8
// load the profiler
$container->loadFromExtension('sensio_framework_extra', array(
'router' => array('annotations' => true),
'request' => array('converters' => true, 'auto_convert' => true),
'view' => array('annotations' => true),
'cache' => array('annotations' => true),
'security' => array('annotations' => true),
));
You can disable some annotations and conventions by defining one or more
settings to false
.
Annotations for Controllers
Annotations are a great way to easily configure your controllers, from the routes to the cache configuration.
Even if annotations are not a native feature of PHP, it still has several advantages over the classic Symfony configuration methods:
- Code and configuration are in the same place (the controller class);
- Simple to learn and to use;
- Concise to write;
- Makes your Controller thin (as its sole responsibility is to get data from the Model).
Tip
If you use view classes, annotations are a great way to avoid creating view classes for simple and common use cases.
The following annotations are defined by the bundle:
This example shows all the available annotations in action (here and in all the other examples both plain old annotations and PHP 8 attributes are shown):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
/**
* @Route("/blog")
* @Cache(expires="tomorrow")
*/
class AnnotController
{
/**
* @Route("/")
* @Template
*/
public function index()
{
$posts = ...;
return array('posts' => $posts);
}
/**
* @Route("/{id}")
* @Method("GET")
* @ParamConverter("post", class="SensioBlogBundle:Post")
* @Template("@SensioBlog/annot/show.html.twig", vars={"post"})
* @Cache(smaxage="15", lastmodified="post.getUpdatedAt()", etag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
* @IsGranted("ROLE_SPECIAL_USER")
* @Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")
*/
public function show(Post $post)
{
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
#[Route('/blog')]
#[Cache(expired: 'tomorrow')]
class AnnotController
{
#[Route('/')]
#[Template]
public function index()
{
$posts = ...;
return array('posts' => $posts);
}
#[Route('/{id}')]
#[Method('GET')]
#[ParamConverter('post', class: 'SensioBlogBundle:Post')]
#[Template('@SensioBlog/annot/show.html.twig", vars: ['post'])]
#[Cache(smaxage: 15, lastmodified: 'post.getUpdatedAt()', etag: "'Post' ~ post.getId() ~ post.getUpdatedAt()")]
#[IsGranted('ROLE_SPECIAL_USER')]
#[Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")]
public function show(Post $post)
{
}
}
As the showAction
method follows some conventions, you can omit some
annotations:
1 2 3 4 5 6 7 8 9
/**
* @Route("/{id}")
* @Cache(smaxage="15", lastModified="post.getUpdatedAt()", Etag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
* @IsGranted("ROLE_SPECIAL_USER")
* @Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")
*/
public function show(Post $post)
{
}
1 2 3 4 5 6 7
#[Route('/{id}')]
#[Cache(smaxage: 15, lastmodified: 'post.getUpdatedAt()', etag: "'Post' ~ post.getId() ~ post.getUpdatedAt()")]
#[IsGranted('ROLE_SPECIAL_USER')]
#[Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")]
public function show(Post $post)
{
}
The routes need to be imported to be active as any other routing resources, for example:
1 2 3 4 5 6
# config/routes/annotations.yaml
# import routes from a controller directory
annot:
resource: "@AnnotRoutingBundle/Controller"
type: annotation