10

I am trying to retrieve the object from MongoDB but I am facing an issue that it is returning the element of base type instead of child and it is causing trouble, I figured out that it is somehow dependent on a property's value.

/**
 * @MongoDB\Document(
 *     collection="zoo",
 *     repositoryClass="ZooRepository",
 * )
 */
class Zoo
{
    /**
     * @MongoDB\ReferenceMany(targetDocument="Animal", inversedBy="zoo", strategy="addToSet")
     * @var \Doctrine\Common\Collections\ArrayCollection
     */
    protected $animals;


    /**
     * @return mixed
     */
    public function getAnimals()
    {
        return $this->animals->toArray();
    }

    //Some more code

}


/**
 * @MongoDB\Document(
 *     repositoryClass="AnimalRepository",
 *     collection="animals"
 * )
 * @MongoDB\InheritanceType("SINGLE_COLLECTION")
 * @MongoDB\DiscriminatorField("discriminator")
 * @MongoDB\DiscriminatorMap({
 *     "animal"="Animal",
 *     "birds"="Bird",
 *     "mamals"="Mamals"})
 */
class Animal
{
    /**
     * @MongoDB\ReferenceMany(targetDocument="Location", mappedBy="animals", simple=true, cascade={"persist"})
     *
     * @Assert\Count(min="0", max="1")
     */
    protected $locations;
}


/**
 * @MongoDB\Document(repositoryClass="AnimalRepository")
 */
class Bird extends Animal
{

}

/**
 * @MongoDB\Document(repositoryClass="AnimalRepository")
 */
class Mamals extends Animal
{

}

The problem is: when I call getAnimals() from ZooHandler it returns the object of type Animal. What I want is the type of Mamals or Bird. The strange thing is, if I have an element in Animals->location then I got it right (Mamal/Bird) and if it does not have the element then I got the base type.

If I get the list of all Animals directly from AnimalRepository in AnimalHandler, I am getting the objects of Mamals/Bird accordingly.

EDITED: Zoo object

> db.zoo.findOne()
{
    "_id" : ObjectId("5822bd23085f753b5a5a2408"),
    "name" : "Zoo 2",
    "active" : true,
    "archived" : false,
    "animals" : [
        DBRef("animals", ObjectId("556cc7adec045b1a0c8b4567"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" }),
        DBRef("animals", ObjectId("556cb3b0ec045bbf068b4582"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" })
    ]
}

For sure there are some more properties that are not shown, as they're irrelevant.

Hassan
  • 930
  • 3
  • 16
  • 35
  • Issue seems weird, could you post what's stored in database for a Zoo object? Please mind that DBRef that is used in database will by default not show any additional fields ODM should have added (like discriminator) and in these we're most interested – malarzm Dec 20 '16 at 17:47
  • @malarzm please check my edit. – Hassan Dec 22 '16 at 10:37
  • we're interested in what DBRefs are hiding as I pointed out in previous comment, you may use https://github.com/TylerBrock/mongo-hacker which changes the way it's printed or check http://stackoverflow.com/a/14633601/5982920 how to print them – malarzm Dec 22 '16 at 11:03
  • Ah, finally got your point and updated the snippet. Now I got what the problem is. But I dont know how I reached with this problem. :( – Hassan Dec 22 '16 at 13:11
  • And this base reference is set only for a specific type, say Bird. If I add an object of type Mamals it works fine. any idea where should I look into? – Hassan Dec 22 '16 at 13:13
  • I'm not sure if discriminated documents plays well with `targetDocument` in reference mapping... The best would be if you could reproduce wrong behaviour as a failing test case (like https://github.com/doctrine/mongodb-odm/blob/master/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH971Test.php). If the test will be failing then we may have bug in ODM :) – malarzm Dec 22 '16 at 21:26
  • Ah ok. :( I will try to write about it soon. – Hassan Dec 28 '16 at 09:56

2 Answers2

0

If I understand your issue correctly, you need PHP's built-in get_class() or get_called_class() functions.

Note : Objects themselves shouldn't forget which class they belong to, even if they are being returned by a function/method that only "knows" they are returning some instance of the superclass or one of its subclasses. So you should always be able to query which class an instance belongs to, via the get_class($instance) function.

LuFFy
  • 8,799
  • 10
  • 41
  • 59
Matthew Slyman
  • 346
  • 3
  • 9
0

I figured out that if I save an entity as a base class object than it will returns the object of base class and so in the above example if I need to get the desired results, I have to save it appropriately.

Hassan
  • 930
  • 3
  • 16
  • 35