Koriym.CsvEntities

PDO - Fetching one to many related tables together

MIT License

Downloads
11.5K
Stars
2

Koriym.CsvEntities

PDO - Fetching one to many related tables together

下記のように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の連結最大値の設定

GROUP_CONCATを使ったカラムの連結処理の最大値はiniファイルまたはクエリーでgroup_concat_max_lenを変更する必要があります。(初期値は1024)

SET SESSION group_concat_max_len = 200000;

インストール

composer require koriym/csv-entities