Symfony 4 / Sonata : gérer une interface d'admin multi serveur

Nous allons voir comment gérer une interface d’admin qui se connecte à plusieurs serveurs.
Dans notre exemple nous avons monté un serveur mysql par défaut qui gère notre interface d’admin. Les utilisateurs, les médias, etc.
Et nous avons monté un serveur postgreSql qui contient une table que nous souhaitons administrer.
Nous pouvons ajouter autant de serveurs que nous souhaitons.

Notre serveur Mysql

Nous avons classiquement monté une instance symfony sonata par défaut avec une connexion mysql classique. On peut donc créer notre base, le schéma, et l’utilisateur par défaut de notre interface d’admin.

php bin/console doctrine:database:create
php bin/console doctrine:schema:update --force
php bin/console fos:user:create --super-admin
Sélection_162

Notre serveur postgreSql

Nous avons d’un autre coté un serveur postgreSql qui contient une table « test ».

Sélection_161-1

Les connexions

Depuis les dernières versions de symfony les crédentials des connexions sont gérées dans le fichier .env à la racine de de votre projet.
Nous allons créer 1 connexions pour chaque serveur.

DATABASE_URL_PGSQL=pgsql://tbourdin:123456@127.0.0.1:5432/test?
DATABASE_URL_MYSQL=mysql://root:toor@127.0.0.1:3306/symfony-sonata-skeleton?serverVersion=5.7

Nous allons ensuite configurer notre paramétrage doctrine en créant une connexion par défaut (mysql) et une connexion additionnelle pour notre serveur postgreSql.
Attention, pour éviter les confusions, on utilise un nommage avec des underscores « _ » au lieu des tirets « – » car symfony va ensuite convertir nos « – » en « _ » et le mapping ne va pas bien se faire.

Nous spécifions que toutes nos entités par défaut seront gérées dans src/entity/ServerMysql et que les entités qui doivent se connecter à Pgsql seront toutes stockées dans le répertoire /src/Entity/ServerPgsql

doctrine:
    dbal:
        default_connection: db_mysql_local
        types:
            json: Sonata\Doctrine\Types\JsonType   
        connections:
            db_mysql_local:
                url: '%env(resolve:DATABASE_URL_MYSQL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8

                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                    
            db_pgsql_local:
                url: '%env(resolve:DATABASE_URL_PGSQL)%'
                driver: 'pdo_pgsql'
                server_version: '9.6.11'
                charset: utf8
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                                    

        
        # IMPORTANT: You MUST configure your server version,
        # either here or in the DATABASE_URL env var (see .env file)
        #server_version: '5.7'
    orm:
        auto_generate_proxy_classes: true
        
        default_entity_manager: App
        
        entity_managers:
        #default code, the sonata admin, that use the default connexion (no need to define it here)
            App:
                connection: db_mysql_local
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: true
                mappings:
                    ApplicationSonataMediaBundle: ~
                    SonataMediaBundle: ~
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/ServerMysql'
                        prefix: 'App\Entity\ServerMysql'
                        alias: App       
        
        #our pgSql entities that use our pgsql connexion       
            app-pgsql:
                connection: db_pgsql_local
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: false
                mappings:
                    AppPgsql:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/ServerPgsql'
                        prefix: 'App\Entity\ServerPgsql\'
                        alias: AppPgsql           



Et pour vérifier notre procédure on tente d’administrer notre interface test

image-4

Et forcément, ça ne fonctionne pas. Car notre entité est stockés dans notre répertoire par défaut.
On la déplace donc dans notre répertoire « /src/Entity/ServerPgsql »
On doit juste modifier le service et la définition de l’entité, et on est bon !

#/config/services.yaml 
   admin.table1:
        class: App\Admin\Table1Admin
        arguments: [~, App\Entity\ServerPgsql\Table1, App\Controller\Table1AdminController]
        tags:
            - { name: sonata.admin, manager_type: orm, group: admin, label: Table1 }
        public: true

<?php

namespace App\Entity\ServerPgsql;

use Doctrine\ORM\Mapping as ORM;

/**
 * Table1
 *
 * @ORM\Table(name="table1")
 * @ORM\Entity
 */
class Table1
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="table1_id_seq", allocationSize=1, initialValue=1)
     */
    private $id;

    /**
     * @var string|null
     *
     * @ORM\Column(name="var1", type="string", length=250, nullable=true)
     */
    private $var1;

    /**
     * @var json|null
     *
     * @ORM\Column(name="var2", type="json", nullable=true)
     */
    private $var2;

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

    public function getVar1(): ?string
    {
        return $this->var1;
    }

    public function setVar1(?string $var1): self
    {
        $this->var1 = $var1;

        return $this;
    }

    public function getVar2(): ?array
    {
        return $this->var2;
    }

    public function setVar2(?array $var2): self
    {
        $this->var2 = $var2;

        return $this;
    }


}

image-5