Skip to content
This repository has been archived by the owner on Feb 5, 2024. It is now read-only.

Fetching referenced (many) documents fails when having multiple fields with the same mappedBy value #99

Open
svenfinitiv opened this issue Sep 1, 2014 · 2 comments

Comments

@svenfinitiv
Copy link

The method UnitOfWork ->assertValidDocumentType will fail, as currently all references are handled by the PersistentViewCollection, not only those matching the targetDocument.

I would suggest the view is extended to provide the type of the referenced document in the key and the related objects are fetched using the the target document in the key filter.

Alternatively the createDocument could be wrapped by a try/catch to filter invalid document type failures.

Best regards,
Sven

@svenfinitiv
Copy link
Author

This goes even further. This simple setup will work:

namespace Entity;

use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @CouchDB\Document
 */
class Customer {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\ReferenceMany(targetDocument="Campaign", mappedBy="customer", cascade={"all"})
     */
    protected $campaigns;
}

class Campaign {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\Index
     * @CouchDB\ReferenceOne(targetDocument="Customer")
     */
    protected $customer;
}

Now we add another entity class referencing the customer, with or without extending the customer doesn't matter:

namespace Entity;

use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Doctrine\Common\Collections\ArrayCollection;

class Order {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\Index
     * @CouchDB\ReferenceOne(targetDocument="Customer")
     */
    protected $customer;
}

Now, when trying to load the campaigns of the customer, it will fail with this InvalidDocumentTypeException: "The class 'Entity\Order' is not of the expected type 'Entity\Campaign".

My first solution thoughts do not resolve this issue. The only chance I currently see is extending the ReferenceOne annotation with a mappedFor attribute as a counterpart to the mappedBy to allow a mapping per field, not document type. With this, the setup would look as follows:

namespace Entity;

use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @CouchDB\Document
 */
class Customer {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\ReferenceMany(targetDocument="Campaign", mappedBy="campaignCustomer", cascade={"all"})
     */
    protected $campaigns;
}

class Campaign {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\Index
     * @CouchDB\ReferenceOne(targetDocument="Customer", mappedFor="campaignCustomer")
     */
    protected $customer;
}

class Order {
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\Index
     * @CouchDB\ReferenceOne(targetDocument="Customer", mappedFor="orderCustomer")
     */
    protected $customer;
}

The associations in the campaign and order would have to be an object (instead of array) to map the entity attribute to a different inverse_associations key (resulting in the key ["customer-1", "campaignCustomer", "campaign-1"]).

@svenfinitiv
Copy link
Author

Last comment for today: My workaround is to use unique (prefixed) fieldnames in the dependent documents (campaignCustomer and orderCustomer in the above example) with an according mappedBy attribute.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant