Q
Q
Qixing2015-04-10 10:24:05
symfony
Qixing, 2015-04-10 10:24:05

How to clear a variable in a repository?

Good afternoon. Tracked down this moment. When executing a certain page, I have two requests from two different controllers to the same repository, but to different methods. It turned out that there is a continuation of the imposition of conditions. Read more:
My repository:

class ItemRepository extends EntityRepository
{
    public $exist = null;

    public function __construct($em, ClassMetadata $class)
    {
        parent::__construct($em, $class);
        $this->exist = $this->createQueryBuilder('i')
            ->where('i.isActive = true');
    }

    public function findOneByUrl($url)
    {
        return $this->exist
            ->andWhere('i.url = :url')
            ->setParameter('url', $url)
            ->getQuery()->getSingleResult();

    }

    public function findTop()
    {
        return $this->exist
            ->getQuery()->getResult();

    }

    public function findAll()
    {
        return $this->exist
            ->getQuery()->getResult();

    }


    public function findByCategory($category)
    {
        return $this->exist
            ->andWhere('i.category = :category')
            ->setParameter('category', $category)
            ->getQuery()->getResult();
    }


}

So the first request goes
to findOneByUrl($url)
And then, when the independent controller calls
findByCategory($category),
then ->andWhere('i.url = :url') is also inherited to all SQL conditions from to findOneByUrl.
Why is the variable not set to zero when the class is created?
Worth php-fpm caching

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Alexey Pavlov, 2015-04-10
@Qixing

Is it within the processing of one request? then everything is clear, no caching has anything to do with it.
You create a query builder in the constructor:
That is, the builder object is stored in memory, and in the future you access this object several times, which already has its own state.
You have two approaches:
1) create a new builder in each method and specify the necessary general parameters for them. In order not to duplicate the code, you can make a private getBuilderExist() method, which will create a builder object and set the basic request settings.
2) either in methods that use an existing builder, clone it and use a copy:

public function findByCategory($category)
    {
        $qb = clone($this->exist);
        return $qb
            ->andWhere('i.category = :category')
            ->setParameter('category', $category)
            ->getQuery()->getResult();
    }

I would choose the first approach so as not to add extra state to the class.

S
Sergey, 2015-04-10
Protko @Fesor

Why is the variable not set to zero when the class is created?

And who told you that the class is created every time?
In general, get into the habit that changing the repository constructor is not ok. And doing any statefull services is also not ok, but sometimes it is necessary.
If you need to stuff some basic condition, you can put it in your factory method, which will create QB for you.
class ItemRepository extends EntityRepository
{

    public function findOneByUrl($url)
    {
        return $this->filterIsActive()
            ->andWhere('i.url = :url')
            ->setParameter('url', $url)
            ->getQuery()->getSingleResult();

    }

    public function findTop()
    {
        return $this->filterIsActive()
            ->getQuery()->getResult();

    }

    public function findAll()
    {
        return $this->filterIsActive()
            ->getQuery()->getResult();

    }


    public function findByCategory($category)
    {
        return $this->filterIsActive()
            ->andWhere('i.category = :category')
            ->setParameter('category', $category)
            ->getQuery()->getResult();
    }

    private function filterIsActive() 
    {
           return $this->createQueryBuilder('i')
                ->where('i.isActive = true');
    }


}

V
Vadim Kharitonov, 2015-04-17
@virtuozzz

If you need to use for all queries 'i.isActive = true, it is better to use Doctrine Filters
As already mentioned above, no new object is created for you and the same QueryBuilder is used in all queries.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question