我有一个控制器,它有插入数据库、更新、删除和其他操作,但几乎所有操作都包含以下行:
$em = $this->getDoctrine()->getEntityManager();
$friend = $em->getRepository('EMMyFriendsBundle:Friend')->find($id);
$user = $this->get('security.context')->getToken()->getUser();
这可以吗,还是代码重复?我试着创建一个名为$em
的属性,并拥有一个类似这样的构造函数:
public function __construct()
{
$this->em = $this->getDoctrine()->getEntityManager();
}
但没有奏效。至于查询,尤其是带有$id
参数的查询,我甚至不知道如何将它们分隔在一个地方,所以每个操作都可以使用它们。一种方式是函数,但这样的函数有意义吗?如果是,它应该返回什么?数组?
请告诉我最佳方式!
对于Symfony2,为了避免代码重复,我在控制器中所做的是创建一个名为Controller.php
的类,在其中放入我经常使用的函数。
例如:
<?php
namespace YourProjectBundleController;
use SymfonyBundleFrameworkBundleControllerController as BaseController;
/**
* Base Controller for xxBundle
*/
class Controller extends BaseController
{
/**
* Get repository
*
* @param string $class class
*
* @return DoctrineORMEntityRepository
*/
protected function getRepository($class)
{
return $this->getDoctrine()->getEntityManager()->getRepository($class);
}
/**
* Set flash
*
* @param string $type type
* @param string $text text
*/
protected function setFlash($type, $text)
{
$this->get('session')->getFlashBag()->add($type, $text);
}
/**
* Returns the pager
*
* @param integer $page Page
* @param integer $perPage Max per page
* @param Doctrine_Query $query Query
*
* @return Pagination
*/
public function getPager($page = 1, $perPage = 10, $query = null)
{
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$this->get('request')->query->get('page', 1),
$perPage
);
return $pagination;
}
创建此控制器后,您需要将应用程序控制器extends
设置为您创建的控制器。
这样,就可以避免流行方法的重复代码和别名。
你可以做:
private $em;
private $friend;
private $user;
private function init($id==null) {
$this->em = $this->getDoctrine()->getEntityManager();
$this->friend = $id?$this->em->getRepository('EMMyFriendsBundle:Friend')->find($id):null;
$this->user = $this->get('security.context')->getToken()->getUser();
}
然后你可以调用你的行动
$this->init($id);
或
$this->init();
你会有
$this->em;
$this->friend;
$this->user;
可用。注意,我允许不设置$id参数,因为我想在某些操作中你不会有它
如果您希望这个init函数在不同的控制器中可用,请创建一个基本控制器并从中进行扩展,如另一个答案中所建议的那样。
您正在寻找的可能是将操作参数直接映射到对象的param转换器。
以下是描述和一些例子:
http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html
编辑:
在一篇有趣的文章中提供更多信息:
http://www.adayinthelifeof.nl/2012/08/04/multiparamconverter-for-symfony2/
如果只有几个控制器中有该代码,则可以将该代码封装到两个控制器的受保护方法中。
如果您认为可以在应用程序的更多部分中重用该代码,那么您应该开始考虑是否需要编写验证器、使用服务或其他类型的设计