作为服务的DBAL连接引发错误

时间:2014-09-06 10:55:53

标签: php symfony doctrine-orm

我跟着this SO answer建立了我的DBAL连接作为服务。

我有以下配置:

在我的服务类文件" Doctrine.php"中,我有

<?php
namespace Acme\BookBundle\Services;

use Doctrine\Common\ClassLoader;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\DriverManager;


class Doctrine
{
    // Just rename __construct to create and make it static
    static function create(){
        $doctrineLoader = new ClassLoader('Doctrine');
        $doctrineLoader->register();

        $doctrineConfig = new Configuration();
        $doctrineParams = [
            'driver' => 'pdo_mysql',
            'dbname' => 'book_enterprise_hub',
            'host' => 'localhost',
            'user' => 'root',
            'password' => '',
        ];
        return DriverManager::getConnection($doctrineParams, $doctrineConfig);
    }

}
?>

在我的services.yml中,我有以下内容:

parameters:
    dbal_connection: book_enterprise_hub

services:
    doctrine:
        class: Doctrine\DBAL\Connection
        factory_class:  'Acme\BookBundle\Services\Doctrine'
        factory_method: 'create'

在我的CompanyController.php中,我有以下代码,

<?php
use Acme\BookBundle\Services\Doctrine;

class CompanyController extends Controller
{
    public function createAction()
    {
        $con = $this->get('doctrine');
        $sqlQuery = "CREATE TABLE book_info (id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, label TEXT, created_on DATETIME) ENGINE = INNODB";
        $stmt = $con->prepare($sqlQuery);
        $stmt->execute();
    }
}   

调用此行时 $ con&gt; prepare($ sqlQuery)

我收到以下错误,

尝试调用方法&#34;准备&#34; on class&#34; Doctrine \ Bundle \ DoctrineBundle \ Registry&#34;在C:\ wamp \ www \ symfony \ src \ Acme \ BookBundle \ Controller \ CompanyController.php

实际上,我使用工厂方法获取DBAL连接作为服务,但一直收到此错误。我可以在service.yml中编写参数,如上所述,或者我应该只在parameters.yml中写入?我究竟做错了什么?

3 个答案:

答案 0 :(得分:2)

您链接的问题OP不使用Symfony2 Framework,他问如何使用Symfony配置组件设置Doctrine服务。

当您使用Symfony2时,您不需要执行任何操作,您可以这样做:

<?php
use Acme\BookBundle\Services\Doctrine;

class CompanyController extends Controller
{
    public function createAction()
    {
        $con = $this->get('doctrine.dbal.default_connection');
        $sqlQuery = "CREATE TABLE book_info (id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, label TEXT, created_on DATETIME) ENGINE = INNODB";
        $stmt = $con->prepare($sqlQuery);
        $stmt->execute();
    }
}   

至于错误。抛出它是因为已经在Symfony中注册了一个名为doctrine的服务,默认情况下它会解析为ManagerRegistry的实例。

那就是说,我不认为直接在控制器中使用连接是个好主意。

答案 1 :(得分:1)

您不必将教条配置为Symfony中的服务。它已作为服务提供,可以从控制器中的服务容器中检索:$this->getDoctrine()$this->get('some-service-id')。您可以通过运行以下控制台命令来查看可用的服务及其相应的ID:

php app/console container:debug

您还可以将--show-private选项添加到该命令以查看私有服务。一般来说,我认为最常见的学说服务将是学习实体管理器(doctrine.orm.entity_manager),您可以使用它来存储/检索/删除数据库中的对象,以及用于查询数据的实体存储库,您可以设置作为单独注入其他服务的服务。

如果您只是尝试为应用程序构建表(即实体),则不需要/不应该在控制器中运行直接SQL查询。你应该做的是:

1)在捆绑包的Entity目录中创建您的学说Entity类。例如:

// src/Acme/BookBundle/Entity/BookInfo.php
namespace Acme\BookBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="book_info")
 */
class BookInfo
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    ...
}

2)运行php app/console doctrine:schema:update --force控制台命令。这将指示doctrine在您为项目设置的数据库中创建实体表(连接信息应在app/config/parameters.yml中)。

例如,要在数据库中存储BookInfo对象 $ myBookInfo ,就像在控制器中执行此操作一样简单:

...
$em = $this->getDoctrine()->getManager();
$em->persist($myBookInfo);
$em->flush;
...

当然,这是一个非常基本的例子,只是为了帮助您理解。

阅读Databases and Doctrine in Symfony了解更多详情。

答案 2 :(得分:1)

最后,我在symfony doc中非常仔细地阅读了服务容器,并使用了另一篇文章中某人给出的答案,并得到了以下配置为我工作:

在我的 services.yml 中,

parameters:
    dbal_connection: book_enterprise_hub
    bookservice.class:   Acme\BookBundle\Services\BookService

services:
    bookservice:
        class:      %bookservice.class%

**注意,我没有在这里传递参数,因为当它通过时,它抛出了这个错误“你已经请求了一个不存在的服务”doctrine.dbal.book_enterprise_hub“,所以,我通过了这个数据库信息在 bookservice __construct方法中。“。

在我的服务档案 BookService.php

<?php
namespace Acme\BookBundle\Services;

//1st method (not working)
//use Doctrine\DBAL\Connection;

//second method
use Doctrine\Common\ClassLoader;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\DriverManager;

class BookService
{
    private $connection;

    //1st method (not working)
    // public function __construct(Connection $connection)  {
    //     $this->connection = $connection;
    // }


    //second method
    public function __construct()  {
        $doctrineLoader = new ClassLoader('BookService');
        $doctrineLoader->register();

        $doctrineConfig = new Configuration();
        $doctrineParams = array(
            'driver' => 'pdo_mysql',
            'dbname' => 'book_enterprise_hub',
            'host' => 'localhost',
            'user' => 'root',
            'password' => '',
        );
        $this->connection = DriverManager::getConnection($doctrineParams, $doctrineConfig);
    }


    public function createTable($tableName){

        $sqlQuery = "CREATE TABLE ".$tableName." (id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, label TEXT, created_on DATETIME) ENGINE = INNODB";
        $stmt = $this->connection->prepare($sqlQuery);
        if($stmt->execute())
        {
            return true;
        }
    }
}

在我的 BookController.php 中,我可以像这样的服务访问DBAL,

<?php
use Acme\BookBundle\Services\BookService;

class BookController extends Controller
{
    /**
     * Creates a new Book entity.
     *
     */
    public function createAction()
    {
        $tableName = $form->get('entityId')->getData();
        $obj = $this->get('bookservice');
        if($obj->createTable($tableName) == true){
            // some code.
        }
    }
}   

使用此配置,“您已请求不存在的服务.500内部服务器错误 - ServiceNotFoundException ”已解决。