Doctrine ODM DocumentManager not found – založení projektu s MongoDB a Doctrine ODM

d3tr1tus
Člen | 52
+
0
-

Ahoj zakládám si nový projekt, kde chci využívat MongoDB a Doctrine ODM. Samotné Mongo mi funguje bez problému. Podle návodu na Doctrine dokumentaci jsem udělal vše co se tam píše. A do bootstrap.php jsem přidal kód:

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

if ( ! file_exists($file = __DIR__ . '/../vendor/autoload.php')) {
	throw new RuntimeException('Install dependencies to run this script.');
}

$loader = require_once $file;
$loader->add('Documents', __DIR__);

$connection = new Connection();

$config = new Configuration();
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$config->setHydratorDir(__DIR__ . '/Hydrators');
$config->setHydratorNamespace('Hydrators');
$config->setDefaultDB('zupa');
$config->setMetadataDriverImpl(AnnotationDriver::create(__DIR__ . '/Documents'));

AnnotationDriver::registerAnnotationClasses();

$dm = DocumentManager::create($connection, $config);

ale když chci založit například nového uživatele v modelu vyhodí to exception

Service '24_App_Model_UserModel' (type of App\Model\UserModel): Service of type Doctrine\ODM\MongoDB\DocumentManager needed by $odm in App\Model\BaseModel::__construct() not found. Did you register it in configuration file?

v BaseModelu jsem dal do konstruktoru

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

protože jinak to psalo undefined variable $odm.

mohl by jste mi někdo poradit jak by to mohlo fungovat prosím?

Mysteria
Člen | 797
+
0
-

Takhle ti to fungovat nebude, protože je sice pěkný, že si v bootstrapu vytvoříš instanci DocumentManageru, ale nikde jej neregistruješ jako službu do Nette DI kontejneru, takže o ní Nette neví a tudíž ti jej nemůže předat do tvého modelu.

Řešení jsou prakticky dvě. Buď zkusíš najít nějakou existující extension pro Nette, která to udělá za tebe jako existuje například pro ORM. Pokud žádná neexistuje, tak je to horší a musíš si ji zkonfigurovat sám.

Pro inspiraci takhle si registruju EntityManager pro ORM sám bez použití extension, pro ODM to bude hodně podobné:

services:
    -
        create: Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain
        setup:
            - addDriver(Doctrine\ORM\Mapping\Driver\AnnotationDriver(Doctrine\Common\Annotations\AnnotationReader(), [%appDir%/Model/Entity]), 'Model\Entity')

    -
        create: Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration([%appDir%/Model/Entity], FALSE, '%tempDir%/cache/Doctrine2.ORM', Doctrine\Common\Cache\FilesystemCache('%tempDir%/cache/Doctrine2.ORM'))
        setup:
            - setAutoGenerateProxyClasses(Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS)
            - setMetadataDriverImpl(@Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain)
            - setNamingStrategy(Doctrine\ORM\Mapping\UnderscoreNamingStrategy())
            - setProxyNamespace(Proxy)

    - Doctrine\ORM\EntityManager::create([
        driver: pdo_mysql
        host: project-mariadb
        user: root
        password: root
        dbname: project
        charset: utf8
     ])
d3tr1tus
Člen | 52
+
0
-

Díky za radu @Mysteria. Extension jsem našel pouze tuhle Document manager extension , ale píše mi to, že není stabilní. Tak se to snažím nastavit ručně podle návodu co si mi poslal a mám dotaz. V bootstrapu.php jsem si to zaregistroval, jak jsem psal výše. V configu jsem si zaregistroval

- Doctrine\ODM\MongoDB\DocumentManager::create()

ale píše mi to error

You must configure a hydrator directory. See docs for details.

Jak můžu předat tohle z bootstrapu

AnnotationDriver::registerAnnotationClasses();

$dm = DocumentManager::create($connection, $config);

do configu?

Mysteria
Člen | 797
+
0
-

Mohlo by to být zhruba takhle (nestestoval jsem):

services:
    - Doctrine\MongoDB\Connection
    -
        create: Doctrine\ODM\MongoDB\Configuration
        setup:
            - setMetadataDriverImpl(Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::create([%appDir%/Model/Documents]))
            - setProxyDir('%tempDir%/cache/Doctrine2.ODM')
            - setProxyNamespace(Proxy)
            - setHydratorDir('%tempDir%/cache/Doctrine2.ODM')
            - setHydratorNamespace(Hydrator)
    - Doctrine\ODM\MongoDB\DocumentManager::create

Editoval Mysteria (10. 8. 2018 18:39)

d3tr1tus
Člen | 52
+
0
-

@Mysteria moc ti děkuju za pomoc s tímhle už mi to neházelo žádnou chybu a vracelo to záznamy uživatele jako kdyby fungoval persist, ale když jsem na to zavolal flush tak to záznam neuložilo. Nakonec jsem to vyřešil celý následovně.

Vytvořil jsem si BaseModel, který bude rozšiřovat všechny podmodely a vložil do konstruktoru

		$connection = new Connection();

$config = new Configuration();
$config->setProxyDir(__DIR__ . '/../temp/Proxies');
$config->setProxyNamespace('Proxies');
$config->setHydratorDir(__DIR__ . '/../temp/Hydrators');
$config->setHydratorNamespace('Hydrators');
$config->setDefaultDB('name_database');
$config->setMetadataDriverImpl(AnnotationDriver::create(__DIR__ . '/Documents'));
$this->dm = DocumentManager::create($connection, $config);

teď už mi stačí v podmodelu zavolat jen nějaký dokument například User a nadefinovat mu všechny parametry a nakonec zavolat

$this->dm->persist($user);
$this->dm->flush();

a všechno běží jako na drátkách :D

Díky moc za trpělivost :)