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()
;
- あくまでエンティティを取得する手段なので、エンティティの形にならないものを取得する場合は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();
-
havingRaw()
のサンプルを出しましたが、selectRaw()
,whereRaw()
などクエリの様々なパーツに対してrawを適用することができます。