Search code examples
symfonyselectdoctrinerepositoryentities

Related Entities and their Repository - selectively loading entities


I have a few entities that have a few associations. They are loading up fine now. So I basically have a customer entity, that relates to an address entity. I also have a receipt transaction that relates to a customer.

When I retrieve a small set of customers I want to retrieve their related receipts but that set is huge. I want just the receipts from the last 2 weeks.

I thought that I could use a custom repository then use a function like customer->getRecentReceipts() but that doesn't work since the customer entity doesn't know about the repository. And from reading on this forum, people seem to say not to use the repository this way. How should I structure things to limit the loading of my receipt entities. I'm trying to avoid loading all then sorting them with a php routine.


Solution

  • There's nothing wrong with making a repository method to do this. You don't have to deal directly with the customer entity to get its receipts.

    I'd just create a simple method in ReceiptRepository like (Syntax might be not quite right, I don't have an IDE handy right now)

    getReceiptsForCustomerByDate(Customer $customer, \DateTime $createdAfter=null) {
    
        if (!$createdAfter instanceof \DateTime) {
    
            $createdAfter = new \DateTime('now -2 weeks');
        }
    
        $qb = $this->getEntityManager()->createQueryBuilder();
    
        return $qb->select('c, r')
            ->from('YourBundle:Customer', 'c')
            ->join('c.receipt', 'r')
            ->where($qb->expr()->eq('c', ':customer')
            ->andWhere($qb->expr()->gt('r.createdAt', ':createdAfter')
            ->setParameter('createdAfter', $createdAfter)
            ->setParameter('customer', $customer)
            ->getQuery()->getResult();
    
    }
    

    The above means your fetched customer entities will only have the relevant receipts. Because we haven't lazy loaded the receipts, $customer->getReceipts() will only return the receipts we have specified by date.

    No, you can't call this from your Customer entity, but there's no reason you can't call it in a controller method. This is a perfectly valid way to get things done in Symfony.

    You could easily modify this to get many customer receipts by passing an array of customers.