LoginSignup
3
1

More than 1 year has passed since last update.

day7の今日は、テーブル間に外部キーによるリレーションがある場合にDoctrine, Eloquentそれぞれでどうやって表すか見ていきます。

SQL的にはauthorsテーブルとbooksテーブルへのauthor_idカラム(authors.idに対する外部キーつき)を追加しています。 https://github.com/77web/doctrine-vs-eloquent/blob/7f98ff21e16a1223e0ad5936e72e8be60c381ba0/sql/book.sql

Doctrine

author_idを追加したbooksテーブルを表すBookエンティティにはauthor_idプロパティでなくauthorプロパティを追加します。

<?php

declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ORM\Table(name: 'books')]
class Book
{
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    private string $id;

    #[ORM\Column(type: 'string', length: 255, nullable: false)]
    private string $title;

    #[ORM\Column(type: 'integer')]
    private int $price;

    #[ORM\ManyToOne(targetEntity: Author::class)]
    #[ORM\JoinColumn(onDelete: 'CASCADE')]
    private Author $author;

    public function getId(): string
    {
        return $this->id;
    }

    public function setId(string $id): void
    {
        $this->id = $id;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setTitle(string $title): void
    {
        $this->title = $title;
    }

    public function getPrice(): int
    {
        return $this->price;
    }

    public function setPrice(int $price): void
    {
        $this->price = $price;
    }

    public function getAuthor(): Author
    {
        return $this->author;
    }

    public function setAuthor(Author $author): void
    {
        $this->author = $author;
    }
}

https://github.com/77web/doctrine-vs-eloquent/blob/7f98ff21e16a1223e0ad5936e72e8be60c381ba0/Doctrine/Entity/Book.php

一方、所有側であるAuthorにもOneToManyリレーションを定義することで、author_idに自らのIDが設定されているBookエンティティのリストを取得することができます。

<?php

declare(strict_types=1);

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ORM\Table(name: 'authors')]
class Author
{
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    private string $id;

    #[ORM\Column(type: 'string', length: 255)]
    private string $name;

    #[ORM\OneToMany(targetEntity: Book::class)]
    private Collection $books;

    public function __construct()
    {
        $this->books = new ArrayCollection();
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function setId(string $id): void
    {
        $this->id = $id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): void
    {
        $this->name = $name;
    }

    public function getBooks(): Collection
    {
        return $this->books;
    }

    public function addBook(Book $book): void
    {
        if (!$this->books->contains($book)) {
            $book->setAuthor($this);
            $this->books->add($book);
        }
    }
}

https://github.com/77web/doctrine-vs-eloquent/blob/7f98ff21e16a1223e0ad5936e72e8be60c381ba0/Doctrine/Entity/Author.php

  • Book::$authorManyToOne アトリビュートによりBookがAuthorに対するinverse-sideであることを示します。
  • Author::$booksOneToMany アトリビュートによりAuthorがBookに対するowning-sideであることを示します。

Eloquent

author_idを追加したbooksテーブルを表すBookモデルには author() メソッドを追加します。

<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * App\Models\Book
 *
 * @property int $id
 * @property string $title
 * @property int $price
 * @property Author $author
 */
class Book extends Model
{
    public $fillable = [
        'title',
        'price',
        'author_id',
    ];

    public function author()
    {
        return $this->belongsTo(Author::class);
    }
}

https://github.com/77web/doctrine-vs-eloquent/blob/7f98ff21e16a1223e0ad5936e72e8be60c381ba0/Eloquent/Models/Book.php

一方、所有側であるAuthorにも books() メソッドを定義することで、author_idに自らのIDが設定されているBookモデルのリストを取得することができます。

<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

/**
 * App\Models\Author
 *
 * @property int $id
 * @property string $name
 * @property Collection<Book> $books
 */
class Author extends Model
{
    public $fillable = [
        'name',
    ];

    public function books()
    {
        return $this->hasMany(Book::class);
    }
}

https://github.com/77web/doctrine-vs-eloquent/blob/7f98ff21e16a1223e0ad5936e72e8be60c381ba0/Eloquent/Models/Author.php

3
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
3
1