LoginSignup
1
1

More than 1 year has passed since last update.

day23(から3日遅れの)今日はfromにサブクエリを使う方法を見ていきます。

Doctrine

<?php

declare(strict_types=1);

use Doctrine\ORM\EntityManagerInterface;

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

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

$sql = <<<EOQ
SELECT t.name, t.books_count FROM (select authors.id, authors.name, count(books.id) as books_count from authors left join books on books.author_id = authors.id group by authors.id, authors.name) as t
EOQ;

/** @var array<array{name: string, books_count: int}> $rows */
$rows = $entityManager->getConnection()->fetchAllAssociative($sql);
foreach ($rows as $row) {
    echo sprintf('%s(%d)', $row['name'], $row['books_count']).PHP_EOL;
}
  • fromに限らず、サブクエリを使うときはORMではなくDBALで対応することがほとんどです。無理にEntityにマップせずに一旦連想配列を取得して、必要に応じて後でDTOに詰め替えます。

Eloquent

<?php

declare(strict_types=1);

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

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

$subQuery = <<<EOQ
select authors.id, authors.name, count(books.id) as books_count from authors left join books on books.author_id = authors.id group by authors.id, authors.name
EOQ;

/** @var Collection<Author> $result */
$result = Author::query()->fromSub($subQuery, 't')->select('t.name', 't.books_count')->get();
foreach ($result as $author) {
    // books_countはAuthorのプロパティではないが、Author::query()で始めたのでAuthorにマップされている
    echo sprintf('%s(%d)', $author->name, $author->books_count).PHP_EOL;
}

  • Modelは未定義の項目も受け付けるため、サブクエリを使っていてもModelとして取得することができます。
  • fromに限らず、DBMSの許す限りselectやwhereにもサブクエリを利用できます。
1
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
1
1