Лучшая практика для организации повторных запросов DBAL в Symfony2?

В настоящий момент я работаю над проектом Symfony2. По большей части это стандартно; Я использую слой ORM для взаимодействия с базой данных через мои сущности. Проблем нет.

Тем не менее, мне нужно сделать нечетные запросы к небольшой части таблиц в существующей схеме в другом месте в системе, которая содержит то, что я бы назвал «ссылкой»: такие вещи, как коэффициенты конверсии валют и т. Д. У меня есть только SELECT доступ к этой схеме.

Я установил другое соединение, и я перешел на уровень DBAL, чтобы сделать запросы на эту схему, которая до сих пор работает очень хорошо.

Моя проблема заключается в том, что, хотя это редкость, я думаю, что мне нужно будет повторить некоторые из моих запросов DBAL в более чем одном месте в моем приложении; Я хотел бы реорганизовать эти запросы в какой-то репозиторий, где их легче использовать / проверять / и т. Д. Я думал о создании сущностей для таблиц, но я чувствую, что в этом случае это слишком много. Правильно ли я полагаю, что вам нужны сущности для создания репозитория?

Вместо этого мне интересно, есть ли способ «Symfony» для этого? Что-то приятное и элегантное 🙂

Благодаря! Дарраг

Обновить

2013-10-03

Простите меня за редактирование двухлетнего ответа … Однако несколько человек поставили под сомнение существующий подход, и хотя он работает (и хорошо работал для моего конкретного случая использования), определение сервисов – это, конечно, способ Symfony .

Никто не привел пример, поэтому для справки / полноты я обновлю свой ответ. Я должен признать, что я не был действительно уверен в определении пользовательских сервисов, когда я изначально опубликовал этот ответ, но мы живем и учимся.

Исходный ответ сохраняется ниже.

1. Создайте дополнительное соединение DBAL

  • Создайте соединение foo в app/config/config.yml .
  • Аргумент wrapper_class в этом случае не требуется (см. Оригинальный ответ).
 doctrine: dbal: connections: default: driver: %database_driver% host: %database_host% dbname: %database_name% user: %database_user% foo: driver: %foo_driver% host: %foo_host% dbname: %foo_name% user: %foo_user% 

2. Настроить службу

  • Предполагая формат YAML.
  • Добавьте конфигурацию в src/Acme/TestBundle/Resources/config/services.yml .
  • Обратите внимание, что мы foo_connection указанное выше DBAL foo_connection в службу.
 services: foo_query_service: class: Acme\TestBundle\Services\FooQueryService arguments: - @doctrine.dbal.foo_connection 

3. Создайте класс для настроенной службы

  • Создайте следующий класс в src/Acme/TestBundle/Services/FooQueryService.php :
 <?php namespace Acme\TestBundle\Services; use DateTime; use Doctrine\DBAL\Connection; class FooQueryService { private $connection; public function __construct(Connection $connection) { $this->connection = $connection; } public function findBarByDate(DateTime $date) { $stmt = $this->connection->prepare('SELECT * FROM bar WHERE date = :date'); $stmt->bindValue('date', $date, 'datetime'); $stmt->execute(); return $stmt->fetch(); } } 

4. Наконец, используйте ваши запросы, где бы вы ни нуждались в них!

Например, в контроллере …

 /** * @Route("/", name="home") * @Template() */ public function indexAction() { $date = new \DateTime(); $result = $this->get('foo_query_service') ->findBarByDate($date); return array(); } 

Совершено 🙂 Спасибо Acayra и koskoz за отзывы.


Хорошо, я думаю, что нашел решение, которое работает для меня в этом случае.

У меня на самом деле был другой взгляд на создание сущностей / менеджеров – на самом деле, как представляется, недостатка в документации Symfony2 в сопоставлении определенных объектов с несколькими менеджерами. В этом случае это по-прежнему кажется переполняющим подходом (а схемы ссылок – довольно грязные).

К счастью, здесь можно указать класс-оболочку для соединения DBAL и абстрактных запросов в определенные методы.

  1. Создайте дополнительное соединение DBAL с классом-оболочкой в config.yml :
 doctrine: orm: connections: default: driver: %driver% host: %host% dbname: %name% user: %user% foo: wrapper_class: 'Acme\TestBundle\Doctrine\DBAL\FooConnection' driver: %foo_driver% host: %foo_host% dbname: %foo_name% user: %foo_user% 
  1. Создайте класс оболочки по указанному пути:
 <?php namespace Acme\TestBundle\Doctrine\DBAL\FooConnection; use Doctrine\DBAL\Connection; class FooConnection extends Connection { // custom query... public function findBarByDate(\DateTime $date) { $stmt = $this->prepare('SELECT * FROM bar WHERE date = :date'); $stmt->bindValue('date', $date, 'datetime'); $stmt->execute(); return $stmt->fetch(); } } 

Обратите внимание, что класс-оболочка должен расширять \Doctrine\DBAL\Connection .

  1. Используйте свои запросы там, где они вам нужны:
 $date = new \DateTime(); $conn = $this->getDoctrine()->getConnection('foo'); $result = $conn->findBarByDate($date); 

Надеюсь это поможет!

Вау, ваш ответ подразумевает, что у вас есть все ваши запросы в тех же местах для каждой таблицы.

Мне не нравится эта оболочка, я предпочитаю иметь услуги. Одна услуга за стол или пакет, это зависит от того, сколько у вас большого количества таблиц и как вы хотите, чтобы ваши запросы были организованы.

Затем я передаю требуемое соединение как аргументы службы, и все.