Symfony2-使用实体时覆盖默认的Doctrine查询


Symfony2 - Overriding default Doctrine query when working with entities

对于我的项目,我有一个包含许多项目的工作区(有点像用户),我想知道当我调用$workspace->getProjects()仅获取活动项目(而不是存档项目)时,是否有一种方法可以覆盖默认的Doctrine查询。这样,我就不必过滤我的集合,而且它会减少数据库返回数据的大小。

/**
 * Acme'DemoBundle'Entity'Workspace
 *
 * @ORM'Table()
 * @ORM'Entity
 */
class Workspace {
    /**
     * @var integer $id
     *
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
    private $id;
    /**
     * @var ArrayCollection $projects
     * 
     * @ORM'OneToMany(targetEntity="Project", mappedBy="workspace")
     */
    private $projects;

    /**
     * Add projects
     *
     * @param Project $projects
     * @return Workspace
     */
     public function addProject( Project $projects ) {
         $this->projects[] = $projects;
         return $this;
     }
    /**
     * Remove projects
     *
     * @param Project $projects
     */
    public function removeProject( Project $projects ) {
        $this->projects->removeElement( $projects );
    }
    /**
     * Get projects
     *
     * @return Collection 
     */
    public function getProjects() {
        return $this->projects;
    }

您必须在实体库类中编写自己的方法。

http://symfony.com/doc/current/book/doctrine.html#custom-存储库类

要做到这一点,可以使用条件。

以下是条令文档中的一个示例,以适应您的需求

use Doctrine'Common'Collections'Criteria;
$criteria = Criteria::create()
->where(Criteria::expr()->eq("birthday", "1982-02-17"))
->orderBy(array("username" => Criteria::ASC))
->setFirstResult(0)
->setMaxResults(20)
;
$birthdayUsers = $object-getUsers()->matching($criteria);

您可以创建一些监听器,并捕获条令事件:http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/event-listeners.html

并在执行之前根据您的意愿修改您的查询;

Doctrine文档中的示例,用于自定义挂钩删除:

<?php 
class UserListener extends Doctrine_EventListener
{
    /**
     * Skip the normal delete options so we can override it with our own
     *
     * @param Doctrine_Event $event
     * @return void
     */
    public function preDelete( Doctrine_Event $event )
    {
        $event->skipOperation();
    }
    /**
     * Implement postDelete() hook and set the deleted flag to true
     *
     * @param Doctrine_Event $event
     * @return void
     */
    public function postDelete( Doctrine_Event $event )
    {
        $name                       = $this->_options['name'];
        $event->getInvoker()->$name = true;
        $event->getInvoker()->save();
    }
    /**
     * Implement preDqlDelete() hook and modify a dql delete query so it updates the deleted flag
     * instead of deleting the record
     *
     * @param Doctrine_Event $event
     * @return void
     */
    public function preDqlDelete( Doctrine_Event $event )
    {
        $params = $event->getParams();
        $field  = $params['alias'] . '.deleted';
        $q      = $event->getQuery();
        if ( ! $q->contains( $field ) )
        {
            $q->from('')->update( $params['component'] . ' ' . $params['alias'] );
            $q->set( $field, '?', array(false) );
            $q->addWhere( $field . ' = ?', array(true) );
        }
    }
    /**
     * Implement preDqlDelete() hook and add the deleted flag to all queries for which this model
     * is being used in.
     *
     * @param Doctrine_Event $event
     * @return void
     */
    public function preDqlSelect( Doctrine_Event $event )
    {
        $params = $event->getParams();
        $field  = $params['alias'] . '.deleted';
        $q      = $event->getQuery();
        if ( ! $q->contains( $field ) )
        {
            $q->addWhere( $field . ' = ?', array(false) );
        }
    }
}

我认为你可以把你的逻辑放在getter方法本身中

public function getProjects() {
        $filtered_projects = array()
        foreach($this->projects as $project)
        {
           // Your logic here
           // e.g.
           // if($project->getIsActive()){
           //    $filtered_projects[] = $project;
           // } 
        }
        return $filtered_projects;
    }