Skip to content

How to set up Mappers for multiple databases? #760

@xpavp03

Description

@xpavp03

I managed to get it working but it seems rather clunky to me. Is there a better way? Could you please advise?
nextras/orm:dev-main

extensions:
    nextras.dbal: Nextras\Dbal\Bridges\NetteDI\DbalExtension
    nextras.orm: Nextras\Orm\Bridges\NetteDI\OrmExtension
    nextras.dbalLog: Nextras\Dbal\Bridges\NetteDI\DbalExtension
    nextras.ormLog: Nextras\Orm\Bridges\NetteDI\OrmExtension

nextras.orm:
    repositoryFinder: App\Orm\FilteredDIRepositoryFinder
    connection: @nextras.dbal.connection
    model: App\Orm\MainOrmModel

nextras.ormLog:
    repositoryFinder: App\Orm\FilteredDIRepositoryFinder
    connection: @nextras.dbalLog.connection
    model: App\OrmLog\LogOrmModel
    autowiredInternalServices: false

nextras.dbal:
    driver: mysqli
    host: %db.host%
    port: %db.port%
    database: %db.database%
    username: %db.user%
    password: %db.password%
    connectionTz: Europe/Prague

nextras.dbalLog:
    driver: mysqli
    host: %db.host%
    port: %db.port%
    database: %db.databaseLog%
    username: %db.user%
    password: %db.password%
    connectionTz: Europe/Prague
    autowired: false
    debugger: false

search:
       orm:
              in: %appDir%/Orm
              classes:
                   - *Repository
                   - *Mapper
        ormLog:
              in: %appDir%/OrmLog
              classes:
                   - *Repository
                   - *Mapper

Then for the main db I have mappers/repositories as by documentation:

namespace App\Orm\Mapper;

class BannerMapper extends \Nextras\Orm\Mapper\Dbal\DbalMapper {}
namespace App\Orm\Repository;

class BannerRepository extends \Nextras\Orm\Repository\Repository
{
    public function __construct(
        BannerMapper $mapper,
        IDependencyProvider $dependencyProvider = null
    )
    {
        parent::__construct($mapper, $dependencyProvider);
    }


    public static function getEntityClassNames(): array
    {
        return [Banner::class];
    }

}

But in order to force OrmLog mappers to use the secondary connection, I had to define my own Connection and MapperCoordinator:

services:
    -
        create: App\OrmLog\Mapper\Connection::from(@nextras.dbalLog.connection)
        setup:
            - Nextras\Dbal\Bridges\NetteTracy\ConnectionPanel::install(@self, true, 100)
        autowired: self
    -
        create: App\OrmLog\Mapper\MapperCoordinator
        autowired: self
namespace App\OrmLog\Mapper;

abstract class AbstractMapper extends \Nextras\Orm\Mapper\Dbal\DbalMapper
{

    public function __construct(
        Connection $connection,    // this is my own class
        MapperCoordinator $mapperCoordinator,   // this is my own class
        \Nette\Caching\Cache $cache
    )
    {
        parent::__construct($connection, $mapperCoordinator, $cache);
    }

}



namespace App\OrmLog\Mapper;

class Connection extends \Nextras\Dbal\Connection
{

    public static function from(\Nextras\Dbal\Connection $connection): self
    {
        return new self($connection->getConfig());
    }

}

namespace App\OrmLog\Mapper;

class MapperCoordinator extends \Nextras\Orm\Mapper\Dbal\DbalMapperCoordinator
{

    public function __construct(Connection $connection)     // Connection is my own class
    {
        parent::__construct($connection);
    }

}

Is there a way to make mappers in OrmLog namespace use the secondary connection without the workaround with custom classes?

I'm not sure if it's related but I don't use the Orm model class to fetch repositories. I prefer to pass repositories directly via constructor or #[Inject].

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions