控制器

编辑本页

警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 2.3,现已不再维护。

本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

控制器

欧宝娱乐app下载地址Symfony遵循的哲学“瘦控制器和胖模型”.这意味着控制器应该只保留薄薄的一层胶水代码需要协调应用程序的不同部分。

根据经验,你应该遵循5-10-20规则,即控制器应该只定义5个或更少的变量,包含10个或更少的动作,每个动作中包含20行或更少的代码。这不是一门精确的科学,但它应该帮助您认识到何时应该将代码从控制器重构到服务中。

最佳实践

让您的控制器扩展FrameworkBundle基础控制器,并尽可能使用注释来配置路由、缓存和安全性。

将控制器与底层框架耦合,可以利用其所有特性并提高工作效率。

因为你的控制器应该很薄,只包含几行胶水代码从长远来看,花费数小时试图将它们从框架中解耦并不会给您带来好处。时间的数量浪费了不值得你这么做。

此外,使用注释进行路由、缓存和安全可以简化配置。您不需要浏览以不同格式(YAML, XML, PHP)创建的数十个文件:所有配置都只是在您需要的地方,它只使用一种格式。

总的来说,这意味着您应该积极地将业务逻辑与框架解耦,同时积极地耦合控制器和路由框架,以便最大限度地利用它。

路由配置

要在控制器中加载定义为注解的路由,请将以下配置添加到主路由配置文件中:

1 2 3 4
# app / config / routing.yml应用:资源:“@AppBundle /控制器/”类型:注释

对象中存储的任何控制器都会加载注释src / AppBundle /控制器/目录,甚至从其子目录。因此,如果你的应用程序定义了很多控制器,将它们重新组织到子目录中是完全可以的:

12 3 4 5 6 7 8 9 10 11 12 13 14

                 
                  /├─…├─src/├─AppBundle/├─…├─Controller/├─DefaultController.php├─…├─Api/│├─…│├─……├─后端/├─…└─……

模板配置

最佳实践

不要使用@Template注释来配置控制器使用的模板。

@Template注释是有用的,但也涉及到一些魔力。我们不认为它的好处是值得魔法,所以建议不要使用它。

大多数时候,@Template使用时不带任何参数,这使得更难以知道正在呈现哪个模板。它还使初学者不太明显,控制器应该总是返回一个响应对象(除非你使用的是视图层)。

控制器的外观

考虑到这些,这里有一个控制器应该如何寻找我们的应用程序主页的例子:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
名称空间AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle控制器控制器使用Sensio赞助FrameworkExtraBundle配置路线DefaultController扩展控制器/ * * *@Route("/", name="首页")*/公共函数indexAction()的帖子->getDoctrine ()->getRepository (“AppBundle:文章”->findLatest ();返回->呈现(“违约/ index.html.twig”数组“文章”= >的帖子));}}

使用ParamConverter

如果你用的是教义,那就可以(可选)使用ParamConverter自动查询一个实体并将其作为参数传递给控制器。

最佳实践

在简单方便的情况下,使用ParamConverter技巧自动查询Doctrine实体。

例如:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
使用AppBundle实体帖子使用Sensio赞助FrameworkExtraBundle配置路线/ * * *@Route("/{id}", name="admin_post_show") */公共函数showAction(文章帖子deleteForm->createDeleteForm (帖子);返回->呈现(“管理/ post / show.html.twig”数组“职位”= >帖子“delete_form”= >deleteForm->createView ()));}

通常情况下,你会期望$ id参数showAction ().相反,通过创建一个新参数(美元的帖子),然后用帖子类(Doctrine实体),ParamConverter自动查询对象$ id属性匹配{id}价值。如果没有,它还会显示404页面帖子可以找到。

当事情变得更高级

上面的例子不需要任何配置,因为通配符名{id}与实体上的属性名称匹配。如果这不是真的,或者您有更复杂的逻辑,那么最简单的方法就是手动查询实体。在我们的应用中,我们有这种情况CommentController

12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ * * *@Route(“/评论/ {postSlug} /新”,name = " comment_new ") * /公共函数newAction(请求请求postSlug帖子->getDoctrine ()->getRepository (“AppBundle:文章”->findOneBy (数组“鼻涕虫”= >postSlug));如果(!帖子){->createNotFoundException ();}/ /……

你也可以使用@ParamConverter构型,具有无限的灵活性:

12 3 4 5 6 7 8 9 10 11 12 13
使用AppBundle实体帖子使用Sensio赞助FrameworkExtraBundle配置路线使用Sensio赞助FrameworkExtraBundle配置ParamConverter使用欧宝娱乐app下载地址组件HttpFoundation请求/ * * *@Route("/comment/{postSlug}/new", name = "comment_new") *@ParamConverter(“文章”,选项={“映射”:{“postSlug”:“鼻涕虫”}})* /公共函数newAction(请求请求,后帖子/ /……

关键在于:ParamConverter快捷方式对于简单的情况非常有用。但是您不应该忘记直接查询实体仍然非常容易。

前后钩

如果你需要在控制器执行之前或之后执行一些代码,你可以使用EventDispatcher组件来执行设置前后过滤器

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。