doctrine / mongodb-odm

The Official PHP MongoDB ORM/ODM
https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/
MIT License
1.09k stars 502 forks source link

GridFs HydratorException : Expected association field "metadata" to be of type "array", "object" received #2599

Closed Webixel closed 9 months ago

Webixel commented 9 months ago

Bug Report

Q A
BC Break no
Version 2.6.1

Summary

When I want to retrieve the metadata of the newly inserted file, I get a hydrator error that returns to me.

Current behavior

Throws a fatal error when property is accessed: Fatal error: Uncaught Doctrine\ODM\MongoDB\Hydrator\HydratorException: Expected association for field "metadata" in document of type "Documents\Fichier" to be of type "array", "object" received.

How to reproduce

Controller

$uploadOptions = new UploadOptions();
$fm = new Fichiermetadata(['mydata' => 'testdata']);
$uploadOptions->metadata = $fm;

$repository = $this->dm->getRepository('Documents\Fichier');
$file = $repository->uploadFromFile(__DIR__ . '/../../public/images/news.jpg', 'news.jpg', $uploadOptions);
$this->dm->detach($file);

$image = $this->dm->getRepository('Documents\Fichier')->find($file->getId());
$metadata = $image->getMetadata();

Fichier Document

<?php
declare(strict_types=1);

namespace Documents;

use Doctrine\ODM\MongoDB\Mapping\Annotations\File;
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;

/** @File(bucketName="Fichier") */
class Fichier
{

    /** @Id */
    private $id;

    /** @File\Filename */
    private $name = '';

    /** @File\UploadDate */
    private $uploadDate = null;

    /** @File\Length */
    private $length = 0;

    /** @File\ChunkSize */
    private $chunkSize = 0;

    /** @File\Metadata(targetDocument=Fichiermetadata::class) */
    private $metadata;

    public function getId()
    {   
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }
    public function getChunkSize()
    {
        return $this->chunkSize;
    }
    public function getLength()
    {
        return $this->length;
    }   
    public function getUploadDate()
    {
        return $this->uploadDate;
    }   
    public function getMetadata(): ?Fichiermetadata
    {
        return $this->metadata;
    }
}

Fichiermetadata Document

<?php
namespace Documents;

use Doctrine\ODM\MongoDB\Mapping\Annotations\EmbeddedDocument;
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
use Doctrine\ODM\MongoDB\Mapping\Annotations\HasLifecycleCallbacks;
use Doctrine\ODM\MongoDB\Mapping\Annotations\PreLoad;

/** @EmbeddedDocument */
class Fichiermetadata
{

    /** @Field(type="hash") */
    private $datas;

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

}

Expected behavior

I want to retrieve an array or an object with the different metadata of the file saved previously

alcaeus commented 9 months ago

Hi @Webixel,

what version of the driver are you running? You can find out the version of the MongoDB library by running composer show mongodb/mongodb, and the extension version by running php --ri mongodb. Also, this error shouldn't occur as we're always assigning an array type map (i.e. embedded documents are always returned as PHP arrays), so I'd be curious to know how you create the DocumentManager and the MongoDB\Client instance it takes. Can you show the code you use to bootstrap the ODM?

Webixel commented 9 months ago

Hi @alcaeus , thank you for the quick reply.

composer show mongodb/mongodb
name     : mongodb/mongodb
descrip. : MongoDB driver library
keywords : database, driver, mongodb, persistence
versions : * 1.17.0
type     : library
license  : Apache License 2.0 (Apache-2.0) (OSI approved) https://spdx.org/licenses/Apache-2.0.html#licenseText
homepage : https://jira.mongodb.org/browse/PHPLIB
source   : [git] https://github.com/mongodb/mongo-php-library.git 9d9c917cf7ff275ed6bd63c596efeb6e49fd0e53
php --ri mongodb

mongodb

MongoDB support => enabled
MongoDB extension version => 1.17.0
MongoDB extension stability => stable
libbson bundled version => 1.25.1
libmongoc bundled version => 1.25.1
...
<?php

use Doctrine\MongoDB\Connection,
    Doctrine\ODM\MongoDB\Configuration,
    Doctrine\ODM\MongoDB\DocumentManager,
    Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;

use MongoDB\Client;
...
private function setDocumentManager(){
        $documentsDirectory = __DIR__ . '/Documents';
        $serverAddress = 'mongodb://127.0.0.1:27017';

        $config = new Configuration();
        $config->setProxyDir(sys_get_temp_dir() . '/proxies');
        $config->setProxyNamespace('Proxies');
        $config->setHydratorDir(sys_get_temp_dir() . '/hydrators');
        $config->setHydratorNamespace('Hydrators');
        $config->setMetadataDriverImpl(AnnotationDriver::create($documentsDirectory));
        $config->setDefaultDB('mydb');

        return  DocumentManager::create(new Client($serverAddress), $config); 
}
...
alcaeus commented 9 months ago

Thanks for the information. It took me a moment to find this, as our tests still manually set a typeMap, which wasn't required since #2288. Once I removed that type map I was able to reproduce the issue and fix it: #2600. This will be released in 2.6.2.

Webixel commented 9 months ago

Yes, thanks. It works by modifying in the mongo client

return DocumentManager::create(new Client($serverAddress, [], ['typeMap' => DocumentManager::CLIENT_TYPEMAP]), $config);