0

I have an abstract class:

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({
 *     "LegalInsuranceProof" = "LegalInsuranceProofDocument",
 *     "SalesReceipt" = "SalesReceiptDocument"
 * })
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="document_abstract")
 * @ORM\Entity(repositoryClass="App\Repository\DocumentRepository")
 */
abstract class AbstractDocument implements CreateFolderInterface
{
.
.
.
}

and the class, that extends this abstract class:

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="document_sales_receipt")
 */
class SalesReceiptDocument extends AbstractDocument
{
.
.
. 
}

In the repo, I have defined the method getReviewListPaginator:

class DocumentRepository extends ServiceEntityRepository {

    use PaginatorTrait;

    public function __construct(RegistryInterface $registry) {
        parent::__construct($registry, AbstractDocument::class);
    }

    public function getReviewListPaginator($limit, $offset) {
        $this->assertQueryParameters($offset, $limit, "asc");

        $qb = $this
            ->createQueryBuilder('d')
            ->select('PARTIAL d.{id, pageCount}')
            ->innerJoin('d.case', 'c')
            ->addSelect('PARTIAL c.{id}')
            ->setFirstResult($offset)
            ->setMaxResults($limit);

        return new Paginator(
            $qb->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY),
            true
        );
    }
}

If I do

$this->em->getRepository(AbstractDocument::class)->getReviewListPaginator(5,2);

the method getReviewListPaginator is called.

But If I do

$paginator = $this->em->getRepository(SalesReceiptDocument::class)->getReviewListPaginator(5,2);

I get en error message:

BadMethodCallException : Undefined method 'getReviewListPaginator'. The method name must start with either findBy, findOneBy or countBy!

But why? Should I define a repo for the SalesReceiptDocument entity, that extends the App\Repository\DocumentRepository?

malarzm
  • 2,831
  • 2
  • 15
  • 25
olek07
  • 513
  • 2
  • 7
  • 21

2 Answers2

1

Your @Entity annotations do not have the repository specified, change them to:

@Entity(repositoryClass="..namespace..\DocumentRepository")

See the @Entity documentation.

Edit 1:
I just noticed your AbstractDocument has duplicate @Entity annotation, you can just delete the empty one

Edit 2:
To select different document types you need separate repositories, to keep your code simple and non-repeating, you can use the $_entityName attribute of EntityRepository if you are extending it or have your own private attribute that would indicate the entity name for a repository and then use this entity name in the getReviewListPaginator to dynamically query the type of entity you want.
As far as I can tell, you cannot achieve this without having separate repositories for each type of document - even if each is empty, just extending the base repository and doing the parametrized query building as I described.

m1n0
  • 609
  • 5
  • 16
  • Is the annotation `@ORM\Entity(repositoryClass="App\Repository\DocumentRepository")`not inherited? – olek07 Feb 26 '19 at 09:48
  • If I do that `@ORM\Entity(repositoryClass="App\Repository\DocumentRepository")`in the SalesReceiptDocument entity, getReviewListPaginator returns ALL entities. Not only the ones of SalesReceiptDocument – olek07 Feb 26 '19 at 10:15
  • But $_entityName has always App\Entity\Document\AbstractDocument . I created the repo: `class SalesReceiptDocumentRepository extends DocumentRepository { }` And then I do `$paginator = $this->em->getRepository(SalesReceiptDocument::class)->getReviewListPaginator(5,2);` – olek07 Feb 26 '19 at 11:51
  • 1
    I've created the class with an own attribute, like this: class SalesReceiptDocumentRepository extends DocumentRepository { public function __construct(RegistryInterface $registry) { $this->entityName = SalesReceiptDocument::class; parent::__construct($registry); } } – olek07 Feb 26 '19 at 12:05
  • Please look here. I have a strange problem. https://stackoverflow.com/questions/55172359/symfony-4-inheritancetypejoined-and-paramconverter-strange-phenomenon Do you have an idea? – olek07 Mar 15 '19 at 08:10
1

I don't think the Repository are extended by default.

I think you need to do a SalesReceiptReporsitory that explicitly exteands your DocumentRepository And add the repositoryClass options to your @Entity on SalesReceiptDocument.

Etshy
  • 870
  • 7
  • 25
  • @m1n0 You are right. And I need the where-clause, like WHERE entity INSTANCE OF SalesReceiptDocument. Not good :-( I think, doctrine could do it for me. – olek07 Feb 26 '19 at 10:52
  • 1
    @olek07 yes indeed, but its not bad, just do it the way I described, you will have one abstract repository with all logic in it and multiple empty repositories that will just inherit from that abstract repository - good old standard OOP abstraction and inheritance. Please accept my answer as I believe it addresses your issue correctly. – m1n0 Feb 26 '19 at 10:55
  • @olek07, If your get the `SalesReceiptRepository` and your `SalesReceiptDocument` have the `repositoryClass=SalesReceiptRepository` you should not have to add the `WHERE entity INSTANCE OF SalesReceiptDocument`. With your code `$paginator = $this->em->getRepository(SalesReceiptDocument::class)->getReviewListPaginator(5,2);` it should be good, as you get the Repository for `SalesReceiptDocument` (`SalesReceiptRepository`) and this repository extends your `DocumentRepository`. I work mostly with doctrine ODM and i works like that for me. – Etshy Feb 26 '19 at 15:27
  • @olek07, maybe you should make your `DocumentRepository` abstract and always extends it, to make sure you NEVER call that repository alone. It will prevent having all sort of Document in the query. Also you should use more Dependency Injection, and less the container (the `get(service)` method). – Etshy Feb 26 '19 at 15:30
  • but if I need all documents, I need the DocumentRepository – olek07 Feb 27 '19 at 10:45
  • True, but actually I can't see any use case when someone need ALL the documents available in an app. I don't know your app, but why would you like to have all `Users` and all `Articles` in the same request ? But like I said, even if you `BaseRepository` is not abstract it should work if you extend it and get the child Repository. – Etshy Feb 27 '19 at 16:08