LoginSignup
2
1

More than 1 year has passed since last update.

DoctrineとEloquent比較大全11: 更に複雑な条件絞り込み(nativeQuery vs DB::raw())

Posted at

day11(?)の今日はエンティティの絞り込みにより複雑な条件が必要な場合のやり方を見ていきます。

Doctrine

<?php

declare(strict_types=1);

use App\Entity\Author;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\ResultSetMapping;

require __DIR__.'/../vendor/autoload.php';

/** @var EntityManagerInterface $entityManager */
$entityManager = require __DIR__.'/bootstrap.php';

$sql = <<<EOQ
SELECT a.id, a.name FROM authors AS a LEFT JOIN books AS b ON b.author_id = a.id GROUP BY a.name HAVING count(b.id) > 1
EOQ;


$rsm = new ResultSetMapping();
$rsm->addEntityResult(Author::class, 'a');
$rsm->addFieldResult('a', 'name', 'name');
$rsm->addFieldResult('a', 'id', 'id');

// 1冊以上本を書いている著者
$query = $entityManager->createNativeQuery($sql, $rsm);

/** @var array<Author> $authors */
$authors = $query->getResult();

// 別解としてDBALを使う方法
$rows = $entityManager->getConnection()->fetchAllAssociative($sql);
$ids = array_column($rows, 'id');
$qb = $entityManager->getRepository(Author::class)->createQueryBuilder('a');
$authors = $qb->where($qb->expr()->in('a.id', ':filtered_ids'))
    ->setParameter('filtered_ids', $ids)
    ->getQuery()
    ->getResult()
;

https://github.com/77web/doctrine-vs-eloquent/blob/281eefd31e684ecbe15af262e737fdc9ffc96ec9/Doctrine/Usecase/filter_with_native_query.php

  • あくまでエンティティを取得する手段なので、エンティティの形にならないものを取得する場合はDBALを使ってarrayの結果を得るほうが良いです。
  • エンティティを取得する場合であっても、NativeQueryを使うよりも、DBALを使って条件を満たすエンティティのidのみを特定し、idで取得するほうが良いです。

Eloquent

<?php

declare(strict_types=1);

use App\Models\Author;
use Illuminate\Database\Eloquent\Collection;

require __DIR__.'/../vendor/autoload.php';

/** @var Collection<Author> $authors1 */
$authors = Author::query()->leftJoin('books', 'books.author_id', 'authors.id')->havingRaw('count(books.id) > 0')->get();

https://github.com/77web/doctrine-vs-eloquent/blob/281eefd31e684ecbe15af262e737fdc9ffc96ec9/Eloquent/Usecase/filter_with_raw.php

  • havingRaw() のサンプルを出しましたが、 selectRaw(), whereRaw() などクエリの様々なパーツに対してrawを適用することができます。
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1