Frank6
Frank6

Reputation: 1203

Symfony2 - Overriding default Doctrine query when working with entities

For my project, I have a workspace (kind of a user) with many projects and I am wondering if there is a way to override the default Doctrine query for when I call $workspace->getProjects() to only fetch the active projects only (not the archived one). This way I won't have to filter my collection and it will reduce the size of the returned data from the database.

/**
 * 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;
    }

Upvotes: 4

Views: 5342

Answers (4)

Niavlys Bobar
Niavlys Bobar

Reputation: 21

To do that, you can use criteria.

Here is an exemple from the doctrine doc, to adapt to your needs

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);

Upvotes: 2

Rafael Adel
Rafael Adel

Reputation: 7759

I think you can put your logic inside the getter method itself

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;
    }

Upvotes: 0

Eduardo Casas
Eduardo Casas

Reputation: 578

You will have to write your own method in the Entity Repository Class.

http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

Upvotes: 2

pomaxa
pomaxa

Reputation: 1746

You can create some listener, and catch doctrine events: http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/event-listeners.html

And modify your query before execute as you wish;

Example from Doctrine docs, for custom hook on delete:

<?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) );
        }
    }
}

Upvotes: 0

Related Questions