PDO - Fetching one to many related tables together
MIT License
下記のようにTodoが複数のMemoを持つone-to-manyのエンティティリストをPDOで作成します。
SELECT todo.id AS id,
todo.title AS title,
memo.id AS memo_id,
memo.body AS memo_body
FROM todo
LEFT OUTER JOIN memo
ON memo.todo_id = todo.id
GROUP BY todo.id;
Memoクラス
final class Memo
{
public string $id,
public string $title
}
Todoクラス
final class Todo
{
public string $id,
public string $title,
/** @var array<Memo> */
public array $memos,
}
上記のSQLとエンティティクラスを下記のように変更します。
SELECT todo.id AS id,
todo.title AS title,
GROUP_CONCAT(memo.id),
GROUP_CONCAT(memo.body)
FROM todo
LEFT OUTER JOIN memo
ON memo.todo_id = todo.id
GROUP BY todo.id;
final class Memo
{
public function __construct(
public string $id,
public string $title
){}
}
final class Todo
{
/** @var array<Memo> */
public array $memos;
public function __construct(
public string $id,
public string $title,
string|null $memoIds,
string|null $memoBodies
){
$this->memos = (new CsvEntities())(Memo::class, $memoIds, $memoBodies);
}
}
SQLをquery()
した後に、下記のようにfetchAllします。
$todoList = $pdo->fetchAll(PDO::FETCH_FUNC, static function (...$args) {
return new Todo(...$args);
});
` 当初目的としたTodo[]配列が得られます。
final class Todo
{
public string $id,
public string $title,
/** @var array<Memo> */
public array $memos,
}
セパレーターを指定できます。
$this->memos = (new CsvEntities())->get("\t", Memo::class, $memoIds, $memoBodies); // tab separator
GROUP_CONCAT
を使ったカラムの連結処理の最大値はiniファイルまたはクエリーでgroup_concat_max_len
を変更する必要があります。(初期値は1024)
SET SESSION group_concat_max_len = 200000;
composer require koriym/csv-entities