使用 Doctrine 2 执行原始 SQL

问题描述 投票:0回答:10

我想使用 Doctrine 2 执行原始 SQL

我需要截断数据库表并使用默认测试数据初始化表。

php sql doctrine
10个回答
183
投票

这是我正在执行的原则 2 中的原始查询示例:

public function getAuthoritativeSportsRecords()
{   
    $sql = " 
        SELECT name,
               event_type,
               sport_type,
               level
          FROM vnn_sport
    ";

    $em = $this->getDoctrine()->getManager();
    $stmt = $em->getConnection()->prepare($sql);
    $stmt->execute();
    return $stmt->fetchAll();
}   

59
投票
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );

54
投票

假设您正在使用 PDO,我通过这样做使其工作。

//Place query here, let's say you want all the users that have blue as their favorite color
$sql = "SELECT name FROM user WHERE favorite_color = :color";

//set parameters 
//you may set as many parameters as you have on your query
$params['color'] = blue;


//create the prepared statement, by getting the doctrine connection
$stmt = $this->entityManager->getConnection()->prepare($sql);
$stmt->execute($params);
//I used FETCH_COLUMN because I only needed one Column.
return $stmt->fetchAll(PDO::FETCH_COLUMN);

您可以更改 FETCH_TYPE 以满足您的需要。


19
投票

Doctrine DBAL 2.13 起,这里的大多数答案现已被弃用。例如,execute 已被弃用,fetchAll 将在 2022 年被删除

/**
 * BC layer for a wide-spread use-case of old DBAL APIs
 *
 * @deprecated This API is deprecated and will be removed after 2022
 *
 * @return list<mixed>
 */
public function fetchAll(int $mode = FetchMode::ASSOCIATIVE): array

不再建议先使用

execute
,然后使用
fetchAll
,因为两者均已弃用。

* @deprecated Statement::execute() is deprecated, use Statement::executeQuery() or executeStatement() instead

* @deprecated Result::fetchAll is deprecated, and will be removed after 2022

因此,在执行原始 SQL 以及获取结果时,我们必须更加具体。


我们需要使用

Statement::execute()
executeQuery
,而不是使用
executeStatement

executeQuery返回对象

Result
:

使用当前绑定的参数执行语句并返回 结果。

executeStatement返回

int
:

使用当前绑定的参数执行语句并返回受影响的行。


我们需要使用

Result::fetchAll()
fetchAllNumeric
 以及更多
),而不是使用 fetchAllAssociative


要获得简单的结果,您必须这样做:

public function getSqlResult(EntityManagerInterface $em)
{   
    $sql = " 
        SELECT firstName,
               lastName
          FROM app_user
    ";

    $stmt = $em->getConnection()->prepare($sql);
    $result = $stmt->executeQuery()->fetchAllAssociative();
    return $result;
}   

并带有参数:

public function getSqlResult(EntityManagerInterface $em)
{   
    $sql = " 
        SELECT firstName,
               lastName,
               age
          FROM app_user
          where age >= :age
    ";

    $stmt = $em->getConnection()->prepare($sql);
    $stmt->bindParam('age', 18);
    $result = $stmt->executeQuery()->fetchAllAssociative();
    return $result;
}   

14
投票

如何执行原始查询并返回数据。

联系您的经理并建立新的联系:

$manager = $this->getDoctrine()->getManager();
$conn = $manager->getConnection();

创建查询并获取全部:

$result= $conn->query('select foobar from mytable')->fetchAll();

从结果中获取数据,如下所示:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);

12
投票

我发现答案可能是:

NativeQuery 可让您执行本机 SQL,根据映射结果 您的规格。这样一个 规范描述了如何 SQL结果集映射到Doctrine 结果由一个表示 结果集映射。

来源:本机 SQL


5
投票

我也有同样的问题。您想要查看实体管理器提供的连接对象:

$conn = $em->getConnection();

然后您可以直接查询/执行它:

$statement = $conn->query('select foo from bar');
$num_rows_effected = $conn->exec('update bar set foo=1');

请参阅连接对象的文档: http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html


5
投票

在您的模型中创建原始 SQL 语句(下面的示例是我必须使用但替换为您自己的日期间隔的示例。如果您正在执行 SELECT,则将 ->fetchall() 添加到execute() 调用中。

   $sql = "DELETE FROM tmp 
            WHERE lastedit + INTERVAL '5 minute' < NOW() ";

    $stmt = $this->getServiceLocator()
                 ->get('Doctrine\ORM\EntityManager')
                 ->getConnection()
                 ->prepare($sql);

    $stmt->execute();

4
投票

你不能,Doctrine 2 不允许原始查询。看起来你可以,但如果你尝试这样的事情:

$sql = "SELECT DATE_FORMAT(whatever.createdAt, '%Y-%m-%d') FORM whatever...";
$em = $this->getDoctrine()->getManager();
$em->getConnection()->exec($sql);

Doctrine 会抛出一个错误,指出 DATE_FORMAT 是一个未知函数。

但是我的数据库(MySQL)确实知道这个函数,所以基本上发生的事情是 Doctrine 在幕后(在你的背后)解析该查询并找到一个它不理解的表达式,认为该查询无效。

因此,如果像我一样,您希望能够简单地将字符串发送到数据库并让它处理它(并让开发人员对安全性承担全部责任),那就忘记它吧。

当然,您可以编写一个扩展以允许以某种方式实现这一点,但您最好使用 mysqli 来完成此操作,并将 Doctrine 留给其 ORM 业务。


0
投票

我正在使用

2.15.4
doctrine/orm
,并假设代码中的
$entityManager
Doctrine\ORM\EntityManagerInterface
的实例。

当您想要执行原始 SQL 查询时,有两种情况:

1。查询结果无关紧要,可以忽略

这似乎与原始问题相符,可以使用以下代码片段:

$sqls = [
    'DROP TABLE IF EXISTS _performance_test',
    'CREATE TABLE _performance_test (counter BIGINT UNSIGNED NOT NULL)',
    'INSERT INTO _performance_test (counter) VALUES (0)',
];
$connection = $entityManager->getConnection();
foreach ($sqls as $sql) {
    $connection->executeStatement($sql);
}

2。查询结果很重要并且被使用

$sql = 'SELECT counter FROM _performance_test LIMIT 1';
$result = $entityManager->getConnection()->prepare($sql)->executeQuery();

在本例中,

$result
Doctrine\DBAL\Result
的实例,您可以调用它的任何方法(
fetchAssociative
fetchOne
fetchAllAssociative
等)。示例:

$counter = $result->fetchOne();
© www.soinside.com 2019 - 2024. All rights reserved.