J'ai un module personnalisé qui extrait des données de plusieurs bases de données externes différentes qui ont été définies comme connexions dans settings.php. La configuration actuelle comprend une série de contrôleurs qui ont un service que j'ai créé appelé DataAccess injecté en eux. Mon service DataAccess a plusieurs méthodes qui acceptent un $schema
paramètre et sur cette base, j'utilise à chaque fois ce qui suit:
$connection = Database::getConnection('default', $schema);
Je peux alors interroger chaque base de données selon les besoins avec cette configuration. J'ai pensé à injecter Database dans mon service à partir du conteneur Drupal, mais j'aurais alors besoin d'une classe de base comme la méthode create de ControllerBase pour obtenir ce service en premier lieu. Quelle serait la bonne façon de faire ceci car ce n'est pas un contrôleur - est-ce que j'utiliserais une classe de base différente ici? Je suis nouveau dans le développement Drupal 8 et j'essaye de m'assurer que je suis les meilleures pratiques, mais en même temps fois je ne veux pas trop compliquer les choses.
Aucun conseil?
Vous ne pouvez pas injecter Drupal\Core\Database\Database
, c'est un conteneur de fonctions statiques, constantes et variables pour les fonctions de base de données.
Si vous souhaitez injecter l'objet Connection
, cela est possible et ressemble plus à quelque chose que vous voulez (sauf si vous avez un scénario où setting.php est dynamique et toutes les valeurs possibles de $schema
ne peut pas être connu).
Vous pouvez suivre l'exemple Drupal définit avec la valeur par défaut @database
classe dans core.services.yml :
database:
class: Drupal\Core\Database\Connection
factory: Drupal\Core\Database\Database::getConnection
arguments: [default]
Dans votre mymodule.services.yml , vous pouvez définir la fabrique/arguments pour chaque connexion à la base de données que vous avez, plus votre classe de service DataAccess
avec les connexions injectées.
services:
mymodule.database_schema:
class: Drupal\Core\Database\Connection
factory: Drupal\Core\Database\Database::getConnection
arguments: [default, schema]
mymodule.database_schema2:
class: Drupal\Core\Database\Connection
factory: Drupal\Core\Database\Database::getConnection
arguments: [default, schema2]
mymodule.data_access:
class: Drupal\mymodule\DataAccess
arguments: ['@mymodule.database_schema', '@mymodule.database_schema2']
De là, vous pouvez stocker les connexions à la base de données dans le constructeur de DataAccess
et les référencer comme requis par les méthodes de DataAccess
.
Comme commenté une autre réponse, la réponse ici est probablement, vous ne pouvez pas.
L'API de base de données n'est pas entièrement convertie pour utiliser les services. J'ai essayé de le faire pendant un certain temps, en https://www.drupal.org/node/18117 , mais je n'ai pas réussi et les autres non plus.
Donc, pour l'instant, vous devez utiliser les méthodes statiques. Le mieux que vous puissiez faire est de l'envelopper dans une méthode ou un autre service qui ne fait que cela pour simplifier le mocking lorsque vous souhaitez écrire des tests unitaires.
En ce moment, j'utilise ce code pour injecter le service de base de données:
*. services.yml
services:
onlyone:
class: Drupal\onlyone\OnlyOne
arguments: ['@entity_type.manager', '@database', '@language_manager']
Drupal\onlyone\OnlyOne
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Language\LanguageManagerInterface;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $connection, LanguageManagerInterface $language_manager) {
$this->entityTypeManager = $entity_type_manager;
$this->connection = $connection;
$this->languageManager = $language_manager;
}