目前,我正在从事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
  • 注意,我们正在将上面定义的DBAL foo_connection注入(inject)服务。

  • 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.最后,在任何需要的地方使用您的查询!

    例如,在 Controller 中...

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

    完成:)感谢Acayrakoskoz的反馈。

    好的,我想我找到了在这种情况下适用于我的解决方案。

    实际上,我还对创建实体/管理器有了另一种看法-实际上似乎缺少有关将特定实体映射到多个管理器的Symfony2文档。在这种情况下,它似乎仍然是一种过大的方法(并且“引用”模式非常困惑)。

    幸运的是,可以为DBAL连接指定一个包装器类,然后将查询抽象到特定的方法中。
  • config.yml中的包装类创建一个附加的DBAL连接:

  • 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%
    
  • 在指定的路径上创建包装器类:

  • <?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
  • 在需要的地方使用查询:

  • $date   = new \DateTime();
    $conn   = $this->getDoctrine()->getConnection('foo');
    $result = $conn->findBarByDate($date);
    

    希望这可以帮助!

    关于php - 在Symfony2中组织可重用DBAL查询的最佳实践?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8241084/

    10-12 16:03