Symfony handson lesson-5

# Doctrine Relation
## One to One
概要
- 1対1
- 例：ユーザテーブルのレコードはプロフィールテーブルのレコードを一つのみ紐付けられる

以下コマンドでOne to One関係を作成
symfony console make:entity
> 既存のEntity名を入力（ex. userProfile）
> 関係カラムの名称を入力（ex. user）
> 関係を入力（ex. OneToOne）
> 紐づけ対象のEntity（ex. User）
> nullableにするか（ex. no）
> 双方向にしたいかどうか（ex. yes）
> 関係の相手側の名称をどうするか（ex. userProfile）

![スクリーンショット 2023-07-16 17.54.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519081/25f9823a-26bc-7a33-84bb-c5fb15f5a5e4.png)

```example_userProfile.php
#[ORM\OneToOne(inversedBy: 'userProfile', cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: false)]
private ?User $user = null;
// ...
public function getUser(): ?User
{
    return $this->user;
}

public function setUser(User $user): self
{
    $this->user = $user;

    return $this;
}
```
```example_user.php
#[ORM\OneToOne(mappedBy: 'user', cascade: ['persist', 'remove'])]
private ?UserProfile $userProfile = null;
// ...
public function getUserProfile(): ?UserProfile
{
    return $this->userProfile;
}

public function setUserProfile(UserProfile $userProfile): self
{
    // set the owning side of the relation if necessary
    if ($userProfile->getUser() !== $this) {
        $userProfile->setUser($this);
    }

    $this->userProfile = $userProfile;

    return $this;
}
```
mappedBy: フィールド名
targetEntity: 関係を持つEntity
Cascade: Userを作成した場合，自動でUserProfileが作成される，"remove"がある場合削除も自動的
ionversedBy: mappedByと逆のフィールド名
JoinColumn: 関係を持っているEntity（こちらがあるEntityには共通Columnは無い）

## One to Many
- 1対多
- 例：投稿テーブルのレコードはコメントテーブルのレコードを複数紐付けられる

OneToOneとほぼ同様に作成可能
symfony console make:MicroPost
... > OneToMany
```Comment.php
#[ORM\ManyToOne(inversedBy: 'comment')]
#[ORM\JoinColumn(nullable: false)]
private ?MicroPost $post = null;
// ...
public function getPost(): ?MicroPost
{
    return $this->post;
}

public function setPost(?MicroPost $post): self
{
    $this->post = $post;

    return $this;
}
```
```MicroPost.php
#[ORM\OneToMany(mappedBy: 'post', targetEntity: Comment::class, orphanRemoval: true)]
private Collection $comment;
// ...
/**
 * @return Collection<int, Comment>
 */
public function getComment(): Collection
{
    return $this->comment;
}

public function addComment(Comment $comment): self
{
    if (!$this->comment->contains($comment)) {
        $this->comment->add($comment);
        $comment->setPost($this);
    }

    return $this;
}

public function removeComment(Comment $comment): self
{
    if ($this->comment->removeElement($comment)) {
        // set the owning side to null (unless already changed)
        if ($comment->getPost() === $this) {
            $comment->setPost(null);
        }
    }

    return $this;
}
```

Collectionで扱える
- Collection: https://gotohayato.com/content/89/

Repositoryで変更や関係などを保存する場合
- 属している側のRepositoryを利用する MicroPostRepository

## Many to Many
- 多対多
- 例：フォロー機能で，ユーザテーブルのレコードは複数のユーザテーブルのレコードをフォローできる
    - フォローされているユーザテーブルのレコードも同様

同様に作成可能
- Userは複数のMicroPostにいいね可能
```User.php
#[ORM\ManyToMany(targetEntity: MicroPost::class, mappedBy: 'likedBy')]
private Collection $liked;
// ...
/**
 * @return Collection<int, MicroPost>
 */
public function getLiked(): Collection
{
    return $this->liked;
}

public function addLiked(MicroPost $liked): self
{
    if (!$this->liked->contains($liked)) {
        $this->liked->add($liked);
        $liked->addLikedBy($this);
    }

    return $this;
}

public function removeLiked(MicroPost $liked): self
{
    if ($this->liked->removeElement($liked)) {
        $liked->removeLikedBy($this);
    }

    return $this;
}
```
```MicroPost.php
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'liked')]
private Collection $likedBy;
// ...
/**
 * @return Collection<int, User>
 */
public function getLikedBy(): Collection
{
    return $this->likedBy;
}

public function addLikedBy(User $likedBy): self
{
    if (!$this->likedBy->contains($likedBy)) {
        $this->likedBy->add($likedBy);
    }

    return $this;
}

public function removeLikedBy(User $likedBy): self
{
    $this->likedBy->removeElement($likedBy);

    return $this;
}
```