floriansemm / SolrBundle

Solr-Integration into Symfony and Doctrine2
http://floriansemm.github.io/SolrBundle
MIT License
123 stars 73 forks source link

Serious problem with nestedClass collections and doctrine annotation cache #199

Open artur2000 opened 5 years ago

artur2000 commented 5 years ago

Hi, I am evaluating this solr binding for a symfony 4 project with doctrine/orm 2.6, doctrine/doctrine-bundle 1.10 and doctrine-cache-bundle 1.3.5 installed. I have a very simple entity (say Product) with oneToMany relation to an inheriting child entity (say Subroduct) using SINGLE_TABLE inheritance. I was struggling since many hours with faulty data indexing. The database was very simple, one Product related to one Subproduct. Both entities get indexed and correctly related by means of 'childDocuments', but all properties of the (parent) Product were missing.

Those properties get wiped out after line 87 in FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory

   /**
     * @param object|string $entity entity, entity-alias or classname
     *
     * @return MetaInformation
     *
     * @throws SolrMappingException if no declaration for document found in $entity
     */
    public function loadInformation($entity)
    {

    [...]

        $fields = $this->annotationReader->getFields($entity);
        foreach ($fields as $field) {
            if (!$field->nestedClass) {
                continue;
            }

            // here $fields and $metaInformation are correctly showing the data of the parent product

            $nestedObjectMetainformation = $this->loadInformation($field->nestedClass);

            // here $fields and $metaInformation are already corrupted

            [...]

        }

        return $metaInformation;
    }

I debugged for hours, looked for some logic errors, wrong variable scoping/referencing but found none. I debugged deeper to the following code in FS\SolrBundle\Doctrine\Annotation\AnnotationReader

    private function getPropertiesByType($entity, $type)
    {
        $properties = $this->readClassProperties($entity);

        $fields = [];
        foreach ($properties as $property) {
            $annotation = $this->reader->getPropertyAnnotation($property, $type);

            if (null === $annotation) {
                continue;
            }

            $property->setAccessible(true);
            // !!! the values get wiped out here below !!!
            $annotation->value = $property->getValue($entity);
            $annotation->name = $property->getName();

            $fields[] = $annotation;
        }

        return $fields;
    }

$this->reader was a CachedReader from doctrine-cache-bundle. After I disabled the annotation cache with the folowing configuration all problems dissapeared.

framework:
    annotations:
        cache: none

I can not say where the problem is but it needs some rework here. EDIT: I found out, that repeating all field and method declarations/definitions holding the @Solr annotations in the child entity helps as well as a workaround. But the best is to ovveride the original FS\AnnotationReader injecting the uncached doctrine AnnotationReader like this:

services:

    # Override the original service definition for the annotation reader
    # DO NOT USE  the CachedReader (@annotation_reader) but explicitely the simple one (@annotations.reader)
    # because of this https://github.com/floriansemm/SolrBundle/issues/199
    solr.doctrine.annotation.annotation_reader:
        class: FS\SolrBundle\Doctrine\Annotation\AnnotationReader
        arguments: ['@annotations.reader', '@logger']