Как составить SQL или DQL запрос, используя библиотеку Doctrine?

Здравствуйте! Я работаю над проектом на PHP, в котором используется ORM Doctrine для взаимодействия с базой данных. Мне нужно выполнить сложный запрос к базе данных, который представлен ниже:  
<pre><code class="sql">SELECT    ta.ta_name AS authority
 , ta.ta_id AS taxid
    -&gt;         , ta.ta_amount AS multiplier
    -&gt;         , tam.tam_column_value AS match_value
    -&gt;         , tp.tp_id AS tax_profile_id
    -&gt;         , tp.tp_name AS tax_profile
    -&gt; FROM tax_authority ta
    -&gt; JOIN tax_type tt ON ta.ta_tt_id = tt.tt_id
    -&gt; JOIN tax_auth_match tam ON tam.tam_ta_id = ta.ta_id
    -&gt; JOIN tax_type_match ttm ON ttm.ttm_tt_id = tt.tt_id
    -&gt; JOIN tax_profile_defs tpd ON tt.tt_id = tpd.tpd_tt_id
    -&gt; JOIN tax_profile tp ON tpd_tp_id = tp.tp_id
    -&gt; WHERE ta.ta_active = 'Y'
    -&gt; ORDER BY match_value ASC;</code></pre>  
Не могли бы вы помочь мне с его реализацией в контексте Doctrine?
  • 20 сентября 2024 г. 6:23
Ответы на вопрос 2
Конечно! Для выполнения SQL или DQL запроса в Doctrine вам нужно будет использовать репозиторий или EntityManager для выполнения запроса. В данном случае вы можете использовать DQL (Doctrine Query Language), который, как правило, более предпочтителен, поскольку он работает с сущностями, а не с таблицами базы данных.

Для начала, предположим, что вы уже определили соответствующие сущности для таблиц `tax_authority`, `tax_type`, `tax_auth_match`, `tax_type_match`, `tax_profile_defs`, и `tax_profile`. Например:

1. `TaxAuthority`
2. `TaxType`
3. `TaxAuthMatch`
4. `TaxTypeMatch`
5. `TaxProfileDef`
6. `TaxProfile`

### Пример DQL запроса

Вот пример, как можно написать ваш запрос с использованием DQL:

```php
use Doctrine\ORM\EntityManagerInterface;

class TaxService
{
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function getTaxAuthorities()
    {
        $dql = "
            SELECT 
                ta.name AS authority,
                ta.id AS taxid,
                ta.amount AS multiplier,
                tam.columnValue AS match_value,
                tp.id AS tax_profile_id,
                tp.name AS tax_profile
            FROM 
                App\Entity\TaxAuthority ta
            JOIN 
                ta.taxType tt
            JOIN 
                ta.taxAuthMatches tam
            JOIN 
                tt.taxTypeMatch ttm
            JOIN 
                tt.profileDefs tpd
            JOIN 
                tpd.taxProfile tp
            WHERE 
                ta.active = :isActive
            ORDER BY 
                match_value ASC
        ";

        $query = $this->entityManager->createQuery($dql);
        $query->setParameter('isActive', 'Y');

        return $query->getResult();
    }
}
```

### Объяснение кода

1. **Создание DQL запроса:** Мы используем строку DQL, чтобы описать наш запрос к базе данных. Обратите внимание, что в DQL используются имена классов и их свойств (например, `ta.name`, `ta.id`), а не имена таблиц и столбцов.

2. **Параметры:** Используем параметры для безопасной передачи значений (например, `:isActive`), что защищает от SQL-инъекций.

3. **Выполнение запроса:** Мы создаем и выполняем запрос через метод `createQuery()` и затем получаем результаты с помощью `getResult()`.

4. **Возврат результата:** В конце метод возвращает результаты запроса.

### Примечания

- Убедитесь, что все сущности и связи между ними правильно настроены.
- Имейте в виду, что вы должны скрыть ваши настройки путей к сущностям (например, `App\Entity\TaxAuthority`) в зависимости от вашей структуры проекта.
- Если у вас в базе данных много записей, подумайте о пагинации или ограничении числа возвращаемых результатов.

Если у вас есть дополнительные вопросы или если вам нужна помощь с конкретными аспектами, дайте знать!
Суть ORM - представление сущностей и связей БД в виде объектов. Соответственно и работать с ними, за исключением специфических случаев, надо как с объектами. <br/> В вашем случае код должен выглядеть как-то так: <br/> <pre><code class="php">$taxAuthorities = $this-&gt;db-&gt;entityManager
    -&gt;getRepository(TaxAuthority::class)
    -&gt;findBy(['active' =&gt; true]);
foreach ($taxAuthorities as $taxAuthority) {
    // здесь работа с объектом через геттеры
   // например, $taxAuthority-&gt;getTaxType()
}</code></pre> <br/> Если всё-таки хотите построить запрос, то как-то так: <br/> <pre><code class="php">$qb = $this-&gt;db-&gt;entityManager-&gt;createQueryBuilder();
$query = $qb
    -&gt;select('ta.taName', 'ta.taId', 'ta.taAmount', 'tam.tamColumnValue', 'tp.tpId', 'tp.tpName')
    -&gt;from(TaxAuthority::class, 'ta')
    -&gt;innerJoin(TaxType::class, 'tt', Join::WITH, $qb-&gt;expr()-&gt;eq('tt.ttId', 'ta.taTtId')
    -&gt;innerJoin(TaxAuthMatch::class, 'tam', Join::WITH, $qb-&gt;expr()-&gt;eq('tam.tamTaId', 'ta.taId')
    -&gt;innerJoin(TaxTypeMatch::class, 'ttm', Join::WITH, $qb-&gt;expr()-&gt;eq('ttm.ttmTtId', 'tt.ttId')
    -&gt;innerJoin(TaxProfileDefs::class, 'tpd', Join::WITH, $qb-&gt;expr()-&gt;eq('tpd.tpdTtId', 'tt.ttId')
    -&gt;innerJoin(TaxProfile::class, 'tp', Join::WITH, $qb-&gt;expr()-&gt;eq('tp.tpId', 'tpd.tpdTpId')
    -&gt;where($qb-&gt;expr()-&gt;eq('ta.taActive', 'Y')
    -&gt;orderBy('tam.tamColumnValue');
// Посмотреть текст DQL
// echo $query-&gt;getDQL();
$result = $query-&gt;getQuery()-&gt;getResult();</code></pre>
Похожие вопросы