Виконати необроблений SQL, використовуючи Doctrine 2


102

Я хочу виконати необроблений SQL за допомогою Doctrine 2

Мені потрібно обрізати таблиці бази даних та ініціалізувати таблиці з тестовими даними за замовчуванням.


2
До речі, коли я хочу робити автоматизовану базу даних, наприклад робити mysqldumps або завантажувати дані з попередніх дампів або скидання таблиць, я зазвичай пишу сценарій оболонки для цієї роботи, а потім пишу завдання (або "команду" мовою Symfony2 ), що виконує сценарій оболонки. Мета ОРМ, наскільки я розумію, полягає в тому, щоб абстрагувати повторювану роботу, і якщо ви робите щось на зразок обрізання таблиці, я не бачу, як було б сенс внести доктрину в картину, оскільки Доктрина не ' t полегшити це завдання.
Джейсон Світт

Відповіді:


164

Ось приклад грубого запиту в Доктрині 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 () що мені робити
Dexter

я використовую кодигнатор з доктриною 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter

1
Це привело мене в правильному напрямку, але не було саме те, що мені потрібно. Я підозрюю, що вік відповіді має значення. Я звик: ...getConnection()->query($sql);і бігти не довелося$stmt->execute();
Брендон

Зауважте, що за допомогою Symfony4 та автоматичної проводки ви можете набрати підказку, EntityManagerInterface $entityManagerа потім зателефонувати$entityManager->getConnection()
COil

50
//$sql - sql statement
//$em - entity manager

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

18
Також хороша ідея зателефонувати Prepa () замість exec, щоб ви могли отримати підтримку підготовлених заяв.
Джеремі Хікс

44

Я змусив це зробити, роблячи це, якщо припустити, що ви використовуєте 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 відповідно до ваших потреб.


1
Найкращий приклад з усіх них
Девід

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']);

1
query () - це коли SQL повертає деякі дані, які ви хочете використовувати; exec () - це коли це не так
Jeffiekins

12

Я дізнався, що відповідь, ймовірно:

A NativeQuery дозволяє виконувати власний SQL, відображаючи результати відповідно до ваших характеристик. Така специфікація, яка описує, як набір результатів SQL відображається на результат Doctrine, представлений ResultSetMapping.

Джерело: Native SQL .


17
Це прийнята відповідь, але я все ще не бачу, наскільки ця частина Доктрини є корисною, оскільки вам завжди потрібна ResultSetMapping. Я не хочу, щоб це відображало результати на Entities .... що за замовчуванням має місце запуску довільного SQL!
MikeMurko

2
@MikeMurko Я вважаю цей пост корисним для запуску необроблених запитів у Доктрині 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

Також неродний Native SQL не буде виконувати всі можливі запити SQL. DELETE / UPDATE / INSERT не буде працювати, ані деякі визначення таблиць, які не відповідають припущенням доктрини. (Приєднана таблиця M2M без ідентифікаторів). Тож ця відповідь не є універсальною. Не слід також сприймати як ВСТУПНІ роботи.
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 add -> 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);

Доктрина виплюне помилку, сказавши, що DATE_FORMAT - невідома функція.

Але моя база даних (mysql) справді знає цю функцію, тому в основному те, що відбувається, це Doctrine - це аналіз цього запиту за лаштунками (і за вашою спиною) і пошук виразу, яке він не розуміє, вважаючи запит недійсним.

Тож якщо ви, як я, ви хочете мати можливість просто надіслати рядок до бази даних і дозволити їй обробляти її (і нехай розробник несе повну відповідальність за безпеку), забудьте про це.

Звичайно, ви можете кодувати розширення, щоб дозволити це в тій чи іншій мірі, але ви так само добре використовуєте mysqli, щоб зробити це, і доктрину залишити в ORM-комерційності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.