LiipFunctionalTestBundle icon indicating copy to clipboard operation
LiipFunctionalTestBundle copied to clipboard

mongodb not hydrating references

Open marcusorjames opened this issue 7 years ago • 2 comments

I have a mongodb document with a referenced document:

/**
 * Class User
 *
 * @MongoDB\Document
 */
class User
{

    /**
     * @MongoDB\Field(type="string")
     */
    protected $email;

    /**
     * @var Contact
     * @MongoDB\ReferenceOne(targetDocument="Document\Contact")
     */
    private $contact;

    /**
     * {@inheritdoc}
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @return Contact
     */
    public function getContact(): Contact
    {
        return $this->contact;
    }

    /**
     * @param Contact $contact
     * @return User
     */
    public function setContact(Contact $contact): User
    {
        $this->contact = $contact;

        return $this;
    }
}

When running a test:

public function testSample()
{
        $fixtures = $this->loadFixtures([
            'DataFixtures\UserFixtures',
        ], null, 'doctrine_mongodb');

        $repository = $fixtures->getReferenceRepository();
        /** @var User $user */
        $user  = $repository->getReference('guest-user');
        $user->getEmail(); // Have to do this to hydrate
        $user->getContact();
 }

I have to call getEmail(), if I don't then getContact() returns null. It doesn't seem to be hydrating contact until I call another getter. As soon as I put getEmail() in before getContact() it returns a contact perfectly. Any idea on this? Thank you

marcusorjames avatar Jan 30 '18 15:01 marcusorjames

Can you please show the content of DataFixtures\UserFixtures? Just to check that something like persist() is not missing.

Please note that in your code you call $user->getContact();, this line returns nothing, is an assertion missing?

alexislefebvre avatar Jan 30 '18 15:01 alexislefebvre

As requested. Note I have simplified the namespaces for sensitivity reasons. Persist is not missing :)

The assertion is missing but is irrelevant. It would be something like:

$contact = $user->getContact();
$this->assertInstanceOf(Contact::class,  $contact);
namespace DataFixtures;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Document\Contact;
use Document\User;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserFixtures extends AbstractFixture implements FixtureInterface
{

    /**
     * @var UserPasswordEncoderInterface
     */
    private $encoder;

    public function __construct(UserPasswordEncoderInterface $encoder)
    {
        $this->encoder = $encoder;
    }

    /**
     * Load data fixtures with the passed EntityManager
     *
     * @param ObjectManager $manager
     * @throws \Doctrine\Common\DataFixtures\BadMethodCallException
     */
    public function load(ObjectManager $manager)
    {
        $this->loadContact($manager);
    }

    /**
     * @param ObjectManager $manager
     * @throws \Doctrine\Common\DataFixtures\BadMethodCallException
     */
    private function loadContact(ObjectManager $manager)
    {
        $contact = new Contact();
        $contact
            ->setGivenName('Ed')
            ->setFamilyName('Winchester');

        $manager->persist($contact);

        $user = new User();
        $user
            ->setEmail('[email protected]')
            ->setPassword($this->encoder->encodePassword($user, 'hiemed'))
            ->setContact($contact)
            ->addRole('ROLE_CONTACT');

        $manager->persist($user);
        $manager->flush();

        $this->addReference('guest-user', $user);
    }
}

marcusorjames avatar Jan 30 '18 17:01 marcusorjames