From 20b944e685de996ea84c3010f41dd1f730a09d9c Mon Sep 17 00:00:00 2001 From: Denis Voytyuk Date: Fri, 21 May 2021 22:33:33 +0200 Subject: [PATCH] Add PHP 8 attribute docs --- src/Resources/doc/annotations/cache.rst | 116 +++++-- src/Resources/doc/annotations/converters.rst | 304 ++++++++++++++----- src/Resources/doc/annotations/routing.rst | 41 +++ src/Resources/doc/annotations/security.rst | 189 ++++++++---- src/Resources/doc/annotations/view.rst | 168 +++++++--- src/Resources/doc/index.rst | 127 +++++--- 6 files changed, 695 insertions(+), 250 deletions(-) diff --git a/src/Resources/doc/annotations/cache.rst b/src/Resources/doc/annotations/cache.rst index dbdeb70a..5897b310 100644 --- a/src/Resources/doc/annotations/cache.rst +++ b/src/Resources/doc/annotations/cache.rst @@ -9,40 +9,81 @@ HTTP Expiration Strategies The ``@Cache`` annotation allows to define HTTP caching:: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; +.. configuration-block:: - /** - * @Cache(expires="tomorrow", public=true) - */ - public function index() - { - } + .. code-block:: php-annotations + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; + + /** + * @Cache(expires="tomorrow", public=true) + */ + public function index() + { + } + + .. code-block:: php-attributes + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; + + #[Cache(expired: 'tomorrow', public: true)] + public function index() + { + } You can also use the annotation on a class to define caching for all actions of a controller:: - /** - * @Cache(expires="tomorrow", public=true) - */ - class BlogController extends Controller - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Cache(expires="tomorrow", public=true) + */ + class BlogController extends Controller + { + } + + .. code-block:: php-attributes + + #[Cache(expired: 'tomorrow', public: true)] + class BlogController extends Controller + { + } When there is a conflict between the class configuration and the method configuration, the latter overrides the former:: - /** - * @Cache(expires="tomorrow") - */ - class BlogController extends Controller - { +.. configuration-block:: + + .. code-block:: php-annotations + /** - * @Cache(expires="+2 days") + * @Cache(expires="tomorrow") */ - public function index() + class BlogController extends Controller { + /** + * @Cache(expires="+2 days") + */ + public function index() + { + } } - } + + .. code-block:: php-attributes + + #[Cache(expired: 'tomorrow')] + class BlogController extends Controller + { + #[Cache(expired: '+2 days')] + public function index() + { + } + } + + .. note:: @@ -59,16 +100,31 @@ headers. ``lastModified`` adds a ``Last-Modified`` header to Responses and Both automatically trigger the logic to return a 304 response when the response is not modified (in this case, the controller is **not** called):: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; +.. configuration-block:: - /** - * @Cache(lastModified="post.getUpdatedAt()", Etag="'Post' ~ post.getId() ~ post.getUpdatedAt().getTimestamp()") - */ - public function index(Post $post) - { - // your code - // won't be called in case of a 304 - } + .. code-block:: php-annotations + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; + + /** + * @Cache(lastModified="post.getUpdatedAt()", Etag="'Post' ~ post.getId() ~ post.getUpdatedAt().getTimestamp()") + */ + public function index(Post $post) + { + // your code + // won't be called in case of a 304 + } + + .. code-block:: php-attributes + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; + + #[Cache(lastModified: 'post.getUpdatedAt()', etag: "'Post' ~ post.getId() ~ post.getUpdatedAt().getTimestamp()")] + public function index(Post $post) + { + // your code + // won't be called in case of a 304 + } It's roughly doing the same as the following code:: diff --git a/src/Resources/doc/annotations/converters.rst b/src/Resources/doc/annotations/converters.rst index 23aef326..ce21d726 100644 --- a/src/Resources/doc/annotations/converters.rst +++ b/src/Resources/doc/annotations/converters.rst @@ -8,16 +8,31 @@ The ``@ParamConverter`` annotation calls *converters* to convert request parameters to objects. These objects are stored as request attributes and so they can be injected as controller method arguments:: - use Symfony\Component\Routing\Annotation\Route; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; +.. configuration-block:: - /** - * @Route("/blog/{id}") - * @ParamConverter("post", class="SensioBlogBundle:Post") - */ - public function show(Post $post) - { - } + .. code-block:: php-annotations + + use Symfony\Component\Routing\Annotation\Route; + use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; + + /** + * @Route("/blog/{id}") + * @ParamConverter("post", class="SensioBlogBundle:Post") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + use Symfony\Component\Routing\Annotation\Route; + use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; + + #[Route('/blog/{id}')] + #[ParamConverter('post', class: 'SensioBlogBundle:Post')] + public function show(Post $post) + { + } Several things happen under the hood: @@ -94,23 +109,45 @@ entities fetched from the database. Several different approaches are possible: If your route wildcards match properties on your entity, then the converter will automatically fetch them:: - /** - * Fetch via primary key because {id} is in the route. - * - * @Route("/blog/{id}") - */ - public function showByPk(Post $post) - { - } - - /** - * Perform a findOneBy() where the slug property matches {slug}. - * - * @Route("/blog/{slug}") - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * Fetch via primary key because {id} is in the route. + * + * @Route("/blog/{id}") + */ + public function showByPk(Post $post) + { + } + + /** + * Perform a findOneBy() where the slug property matches {slug}. + * + * @Route("/blog/{slug}") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + /** + * Fetch via primary key because {id} is in the route. + */ + #[Route('/blog/{id}')] + public function showByPk(Post $post) + { + } + + /** + * Perform a findOneBy() where the slug property matches {slug}. + */ + #[Route('/blog/{slug}')] + public function show(Post $post) + { + } Automatic fetching works in these situations: @@ -129,15 +166,29 @@ annotation and using the `@ParamConverter options`_. If automatic fetching doesn't work, use an expression:: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; +.. configuration-block:: - /** - * @Route("/blog/{post_id}") - * @Entity("post", expr="repository.find(post_id)") - */ - public function show(Post $post) - { - } + .. code-block:: php-annotations + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; + + /** + * @Route("/blog/{post_id}") + * @Entity("post", expr="repository.find(post_id)") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; + + #[Route('/blog/{post_id}')] + #[Entity('post', expr: 'repository.find(post_id)')] + public function show(Post $post) + { + } Use the special ``@Entity`` annotation with an ``expr`` option to fetch the object by calling a method on your repository. The @@ -151,13 +202,25 @@ any route wildcards - like ``{post_id}`` are available as variables. This can also be used to help resolve multiple arguments:: - /** - * @Route("/blog/{id}/comments/{comment_id}") - * @Entity("comment", expr="repository.find(comment_id)") - */ - public function show(Post $post, Comment $comment) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/{id}/comments/{comment_id}") + * @Entity("comment", expr="repository.find(comment_id)") + */ + public function show(Post $post, Comment $comment) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/{id}/comments/{comment_id}')] + #[Entity('comment', expr: 'repository.find(comment_id)')] + public function show(Post $post, Comment $comment) + { + } In the example above, the ``$post`` parameter is handled automatically, but ``$comment`` is configured with the annotation since they cannot both follow the default convention. @@ -173,37 +236,74 @@ A number of ``options`` are available on the ``@ParamConverter`` or * ``id``: If an ``id`` option is configured and matches a route parameter, then the converter will find by the primary key:: - /** - * @Route("/blog/{post_id}") - * @ParamConverter("post", options={"id" = "post_id"}) - */ - public function showPost(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/{post_id}") + * @ParamConverter("post", options={"id" = "post_id"}) + */ + public function showPost(Post $post) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/{post_id}')] + #[Entity('post', options: ['id' => 'post_id'])] + public function showPost(Post $post) + { + } * ``mapping``: Configures the properties and values to use with the ``findOneBy()`` method: the key is the route placeholder name and the value is the Doctrine property name:: - /** - * @Route("/blog/{date}/{slug}/comments/{comment_slug}") - * @ParamConverter("post", options={"mapping": {"date": "date", "slug": "slug"}}) - * @ParamConverter("comment", options={"mapping": {"comment_slug": "slug"}}) - */ - public function showComment(Post $post, Comment $comment) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/{date}/{slug}/comments/{comment_slug}") + * @ParamConverter("post", options={"mapping": {"date": "date", "slug": "slug"}}) + * @ParamConverter("comment", options={"mapping": {"comment_slug": "slug"}}) + */ + public function showComment(Post $post, Comment $comment) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/{date}/{slug}/comments/{comment_slug}')] + #[ParamConverter('post', options: ['mapping' => ['date' => 'date', 'slug' => 'slug']])] + #[ParamConverter('comment', options: ['mapping': ['comment_slug' => 'slug']])] + public function showComment(Post $post, Comment $comment) + { + } * ``exclude`` Configures the properties that should be used in the ``findOneBy()`` method by *excluding* one or more properties so that not *all* are used:: - /** - * @Route("/blog/{date}/{slug}") - * @ParamConverter("post", options={"exclude": {"date"}}) - */ - public function show(Post $post, \DateTime $date) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/{date}/{slug}") + * @ParamConverter("post", options={"exclude": {"date"}}) + */ + public function show(Post $post, \DateTime $date) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/{date}/{slug}')] + #[ParamConverter('post', options: ['exclude' => ['date']])] + public function show(Post $post, \DateTime $date) + { + } * ``strip_null`` If true, then when ``findOneBy()`` is used, any values that are ``null`` will not be used for the query. @@ -211,13 +311,25 @@ A number of ``options`` are available on the ``@ParamConverter`` or * ``entity_manager`` By default, the Doctrine converter uses the *default* entity manager, but you can configure this:: - /** - * @Route("/blog/{id}") - * @ParamConverter("post", options={"entity_manager" = "foo"}) - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/{id}") + * @ParamConverter("post", options={"entity_manager" = "foo"}) + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/{id}')] + #[ParamConverter('post', options: ['entity_manager' => 'foo'])] + public function show(Post $post) + { + } * ``evict_cache`` If true, forces Doctrine to always fetch the entity from the database instead of cache. @@ -229,24 +341,48 @@ Converter Name: ``datetime`` The datetime converter converts any route or request attribute into a datetime instance:: - /** - * @Route("/blog/archive/{start}/{end}") - */ - public function archive(\DateTime $start, \DateTime $end) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/archive/{start}/{end}") + */ + public function archive(\DateTime $start, \DateTime $end) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/archive/{start}/{end}')] + public function archive(\DateTime $start, \DateTime $end) + { + } By default any date format that can be parsed by the ``DateTime`` constructor is accepted. You can be stricter with input given through the options:: - /** - * @Route("/blog/archive/{start}/{end}") - * @ParamConverter("start", options={"format": "!Y-m-d"}) - * @ParamConverter("end", options={"format": "!Y-m-d"}) - */ - public function archive(\DateTime $start, \DateTime $end) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/blog/archive/{start}/{end}") + * @ParamConverter("start", options={"format": "!Y-m-d"}) + * @ParamConverter("end", options={"format": "!Y-m-d"}) + */ + public function archive(\DateTime $start, \DateTime $end) + { + } + + .. code-block:: php-attributes + + #[Route('/blog/archive/{start}/{end}')] + #[ParamConverter('start', options: ['format' => '!Y-m-d'])] + #[ParamConverter('end', options: ['format' => '!Y-m-d'])] + public function archive(\DateTime $start, \DateTime $end) + { + } A date in a wrong format like ``2017-21-22`` will return a 404. diff --git a/src/Resources/doc/annotations/routing.rst b/src/Resources/doc/annotations/routing.rst index 9c229894..21f7d096 100644 --- a/src/Resources/doc/annotations/routing.rst +++ b/src/Resources/doc/annotations/routing.rst @@ -29,6 +29,25 @@ annotation, so you only have to update the annotation class namespace: } } +Alternatively, it can be done with the help of the PHP 8 attribute: + +.. code-block:: diff + + -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + +use Symfony\Component\Routing\Annotation\Route; + + class DefaultController extends Controller + { + - /** + - * @Route("/") + - */ + + #[Route('/')] + public function index() + { + // ... + } + } + The main difference is that Symfony's annotation no longer defines the ``service`` option, which was used to instantiate the controller by fetching the given service from the container. In modern Symfony applications, all @@ -61,6 +80,28 @@ restrict the HTTP methods of the route: } } +Alternatively, it can be done with the help of the PHP 8 attribute: + +.. code-block:: diff + + -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; + +use Symfony\Component\Routing\Annotation\Route; + + class DefaultController extends Controller + { + - /** + - * @Route("/show/{id}") + - * @Method({"GET", "HEAD"}) + - */ + + #[Route('/show/{id}', methods: ['GET','HEAD'])] + public function show($id) + { + // ... + } + } + + Read the `chapter about Routing`_ in the Symfony Documentation to learn everything about these and the other annotations available. diff --git a/src/Resources/doc/annotations/security.rst b/src/Resources/doc/annotations/security.rst index 0cdfc265..4234c664 100644 --- a/src/Resources/doc/annotations/security.rst +++ b/src/Resources/doc/annotations/security.rst @@ -6,23 +6,44 @@ Usage The ``@Security`` and ``@IsGranted`` annotations restrict access on controllers:: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; +.. configuration-block:: - class PostController extends Controller - { - /** - * @IsGranted("ROLE_ADMIN") - * - * or use @Security for more flexibility: - * - * @Security("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')") - */ - public function index() + .. code-block:: php-annotations + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; + use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; + + class PostController extends Controller { - // ... + /** + * @IsGranted("ROLE_ADMIN") + * + * or use @Security for more flexibility: + * + * @Security("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')") + */ + public function index() + { + // ... + } + } + + .. code-block:: php-attributes + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; + use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; + + class PostController extends Controller + { + #[IsGranted('ROLE_ADMIN'] + /** or use Security attribute */ + #[Security("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')")] + public function index() + { + // ... + } } - } + @IsGranted ---------- @@ -31,15 +52,28 @@ The ``@IsGranted()`` annotation is the simplest way to restrict access. Use it to restrict by roles, or use custom voters to restrict access based on variables passed to the controller:: - /** - * @Route("/posts/{id}") - * - * @IsGranted("ROLE_ADMIN") - * @IsGranted("POST_SHOW", subject="post") - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Route("/posts/{id}") + * + * @IsGranted("ROLE_ADMIN") + * @IsGranted("POST_SHOW", subject="post") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Route('/posts/{id}')] + #[IsGranted('ROLE_ADMIN'] + #[IsGranted('POST_SHOW', subject: 'post')] + public function show(Post $post) + { + } Each ``IsGranted()`` must grant access for the user to have access to the controller. @@ -50,18 +84,32 @@ Each ``IsGranted()`` must grant access for the user to have access to the contro You can also control the message and status code:: - /** - * Will throw a normal AccessDeniedException: - * - * @IsGranted("ROLE_ADMIN", message="No access! Get out!") - * - * Will throw an HttpException with a 404 status code: - * - * @IsGranted("ROLE_ADMIN", statusCode=404, message="Post not found") - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * Will throw a normal AccessDeniedException: + * + * @IsGranted("ROLE_ADMIN", message="No access! Get out!") + * + * Will throw an HttpException with a 404 status code: + * + * @IsGranted("ROLE_ADMIN", statusCode=404, message="Post not found") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + /** Will throw a normal AccessDeniedException */ + #[IsGranted('ROLE_ADMIN', message: 'No access! Get out!')] + /** Will throw an HttpException with a 404 status code */ + #[IsGranted('ROLE_ADMIN', statusCode: 404, message: 'Post not found')] + public function show(Post $post) + { + } @Security --------- @@ -69,14 +117,25 @@ You can also control the message and status code:: The ``@Security`` annotation is more flexible than ``@IsGranted``: it allows you to pass an *expression* that can contain custom logic:: - /** - * @Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)") - */ - public function show(Post $post) - { - // ... - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)") + */ + public function show(Post $post) + { + // ... + } + + .. code-block:: php-attributes + #[Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")] + public function show(Post $post) + { + // ... + } The expression can use all functions that you can use in the ``access_control`` section of the security bundle configuration, with the addition of the @@ -95,21 +154,43 @@ exception instead of ``Symfony\Component\Security\Core\Exception\AccessDeniedException`` using the ``statusCode`` option:: - /** - * @Security("is_granted('POST_SHOW', post)", statusCode=404) - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Security("is_granted('POST_SHOW', post)", statusCode=404) + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Security("is_granted('POST_SHOW', post)", statusCode: 404)] + public function show(Post $post) + { + } The ``message`` option allows you to customize the exception message:: - /** - * @Security("is_granted('POST_SHOW', post)", statusCode=404, message="Resource not found.") - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Security("is_granted('POST_SHOW', post)", statusCode=404, message="Resource not found.") + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Security("is_granted('POST_SHOW', post)", statusCode: 404, message: 'Resource not found.')] + public function show(Post $post) + { + } .. tip:: diff --git a/src/Resources/doc/annotations/view.rst b/src/Resources/doc/annotations/view.rst index 4eb6b376..b5828800 100644 --- a/src/Resources/doc/annotations/view.rst +++ b/src/Resources/doc/annotations/view.rst @@ -6,18 +6,35 @@ Usage The ``@Template`` annotation associates a controller with a template name:: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +.. configuration-block:: - /** - * @Template("@SensioBlog/post/show.html.twig") - */ - public function show($id) - { - // get the Post - $post = ...; + .. code-block:: php-annotations - return array('post' => $post); - } + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; + + /** + * @Template("@SensioBlog/post/show.html.twig") + */ + public function show($id) + { + // get the Post + $post = ...; + + return array('post' => $post); + } + + .. code-block:: php-attributes + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; + + #[Template('@SensioBlog/post/show.html.twig')] + public function show($id) + { + // get the Post + $post = ...; + + return array('post' => $post); + } When using the ``@Template`` annotation, the controller should return an array of parameters to pass to the view instead of a ``Response`` object. @@ -26,14 +43,25 @@ array of parameters to pass to the view instead of a ``Response`` object. If you want to stream your template, you can make it with the following configuration:: - /** - * @Template(isStreamable=true) - */ - public function show($id) - { - // ... - } + .. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Template(isStreamable=true) + */ + public function show($id) + { + // ... + } + .. code-block:: php-attributes + + #[Template(isStreamable: true)] + public function show($id) + { + // ... + } .. tip:: @@ -43,16 +71,31 @@ array of parameters to pass to the view instead of a ``Response`` object. If the template is named after the controller and action names, which is the case for the above example, you can even omit the annotation value:: - /** - * @Template - */ - public function show($id) - { - // get the Post - $post = ...; +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Template + */ + public function show($id) + { + // get the Post + $post = ...; + + return array('post' => $post); + } + + .. code-block:: php-attributes + + #[Template] + public function show($id) + { + // get the Post + $post = ...; - return array('post' => $post); - } + return array('post' => $post); + } .. tip:: @@ -65,30 +108,65 @@ can use the ``vars`` attribute instead of returning an array. This is very useful in combination with the ``@ParamConverter`` :doc:`annotation `:: - /** - * @ParamConverter("post", class="SensioBlogBundle:Post") - * @Template("@SensioBlog/post/show.html.twig", vars={"post"}) - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @ParamConverter("post", class="SensioBlogBundle:Post") + * @Template("@SensioBlog/post/show.html.twig", vars={"post"}) + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[ParamConverter('post', class: 'SensioBlogBundle:Post')] + #[Template('@SensioBlog/post/show.html.twig"', vars: ['post'])] + public function show(Post $post) + { + } which, thanks to conventions, is equivalent to the following configuration:: - /** - * @Template(vars={"post"}) - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Template(vars={"post"}) + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Template(vars: ['post'])] + public function show(Post $post) + { + } You can make it even more concise as all method arguments are automatically passed to the template if the method returns ``null`` and no ``vars`` attribute is defined:: - /** - * @Template - */ - public function show(Post $post) - { - } +.. configuration-block:: + + .. code-block:: php-annotations + + /** + * @Template + */ + public function show(Post $post) + { + } + + .. code-block:: php-attributes + + #[Template] + public function show(Post $post) + { + } + diff --git a/src/Resources/doc/index.rst b/src/Resources/doc/index.rst index 5ef7be58..3bfb3e99 100644 --- a/src/Resources/doc/index.rst +++ b/src/Resources/doc/index.rst @@ -93,59 +93,112 @@ The following annotations are defined by the bundle: annotations/cache annotations/security -This example shows all the available annotations in action:: - - 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 - { +This example shows all the available annotations in action (here and in all +the other examples both plain old annotations and PHP 8.0 are shown):: + +.. configuration-block:: + + .. code-block:: php-annotations + + 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("/") - * @Template + * @Route("/blog") + * @Cache(expires="tomorrow") */ - public function index() + class AnnotController { - $posts = ...; + /** + * @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("has_role('ROLE_ADMIN') and is_granted('POST_SHOW', post)") + */ + public function show(Post $post) + { + } + } + + .. code-block:: php-attributes + + 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; - return array('posts' => $posts); + #[Route('/blog')] + 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("has_role('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:: + +.. configuration-block:: + + .. code-block:: php-annotations + /** * @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()") + * @Cache(smaxage="15", lastModified="post.getUpdatedAt()", Etag="'Post' ~ post.getId() ~ post.getUpdatedAt()") * @IsGranted("ROLE_SPECIAL_USER") * @Security("has_role('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:: + .. code-block:: php-attributes - /** - * @Route("/{id}") - * @Cache(smaxage="15", lastModified="post.getUpdatedAt()", Etag="'Post' ~ post.getId() ~ post.getUpdatedAt()") - * @IsGranted("ROLE_SPECIAL_USER") - * @Security("has_role('ROLE_ADMIN') and is_granted('POST_SHOW', post)") - */ - public function show(Post $post) - { - } + #[Route('/{id}')] + #[Cache(smaxage: 15, lastmodified: 'post.getUpdatedAt()', etag: "'Post' ~ post.getId() ~ post.getUpdatedAt()")] + #[IsGranted('ROLE_SPECIAL_USER')] + #[Security("has_role('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: