Выполнение необработанного SQL с помощью Doctrine 2

103

Я хочу выполнить необработанный SQL с помощью Doctrine 2

Мне нужно усечь таблицы базы данных и инициализировать таблицы тестовыми данными по умолчанию.

Jiew Meng
источник
2
Между прочим, когда я хочу выполнить автоматическую работу с базой данных, например, выполнить mysqldumps или загрузить данные из предыдущих дампов или удалить таблицы, я обычно пишу сценарий оболочки для этой работы, а затем пишу задачу (или «команду» на языке Symfony2 ), который выполняет сценарий оболочки. Цель ORM, насколько я понимаю, состоит в том, чтобы абстрагироваться от повторяющейся работы, и если вы делаете что-то вроде усечения таблицы, я не понимаю, как иметь смысл добавлять Doctrine в картину, поскольку Doctrine не делает этого. Не облегчить эту задачу.
Джейсон Светт

Ответы:

165

Вот пример необработанного запроса в Doctrine 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();
}   
Джейсон Светт
источник
4
Хороший ответ. Чтобы получить диспетчер сущностей в этом коде, вы можете использовать $ this-> getDoctrine () -> getManager () вместо этого кода над «$ this-> getEntityManager ()» , так что у меня это сразу сработало.
webblover
эй, он дает мне вызов неопределенного метода Index :: getDoctrine (), что мне делать
Декстер
Я использую codeigniter с доктриной 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Декстер
1
Это привело меня в правильном направлении, но это было не совсем то, что мне нужно. Я подозреваю, что возраст ответа имеет значение. Я использовал: ...getConnection()->query($sql);и не нужно было бежать$stmt->execute();
Брэндон
Обратите внимание, что с Symfony4 и автоматическим подключением вы можете набрать подсказку, EntityManagerInterface $entityManagerа затем позвонить$entityManager->getConnection()
COil
50
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );
orourkedd
источник
19
Также неплохо вызвать prepare () вместо exec, чтобы вы все еще могли получить поддержку подготовленных операторов.
Джереми Хикс,
45

Я заставил его работать, сделав это, предполагая, что вы используете 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 в соответствии со своими потребностями.

Fernandodof
источник
1
Лучший пример из всех
Дэвид
14

Как выполнить необработанный запрос и вернуть данные.

Подключитесь к своему менеджеру и установите новое соединение:

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

Создайте свой запрос и fetchAll:

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

Получите данные из результата следующим образом:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);
Эрик Лещинский
источник
1
query () используется, когда SQL возвращает данные, которые вы хотите использовать; exec () для
случаев,
12

Я узнал, что ответ, вероятно, такой:

NativeQuery позволяет выполнять собственный SQL, отображая результаты в соответствии с вашими требованиями. Такая спецификация, которая описывает, как набор результатов SQL сопоставляется с результатом Doctrine, представлена ​​ResultSetMapping.

Источник: Собственный SQL .

Jiew Meng
источник
17
Это принятый ответ, но я до сих пор не понимаю, насколько полезна эта часть Doctrine, потому что вам всегда нужен ResultSetMapping. Я не хочу, чтобы результаты отображались в Entities .... по умолчанию это точка запуска произвольного SQL!
MikeMurko 02
2
@MikeMurko Я нашел этот пост полезным для выполнения сырых запросов в Доктрине 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Джейсон Светт
Также Non-native Native SQL не будет выполнять все возможные SQL-запросы. DELETE / UPDATE / INSERT не будут работать, а также определения некоторых таблиц, которые не соответствуют предположениям доктрины. (Таблица соединений M2M без идентификаторов). Так что этот ответ не универсален. Также не следует принимать, поскольку INSERT не работают.
przemo_li
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();
Badzilla
источник
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.

Алексис Финн
источник