1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHPのORM: DoctrineORMとEloquentの比較大全をひとりでやるAdvent Calendar 2022

Day 21

DoctrineとEloquent比較大全21: レコードの更新日時・作成日時を自動で保存する

Posted at

day21(から4日遅れ)の今日は、DoctrineやEloquentでレコードを保存するときに、作成日時・更新日時を自動保存する方法を見ていきます。

Doctrine

Entity/Book.php
<?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: 'books')]
#[ORM\HasLifecycleCallbacks]
class Book
{
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    private int $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;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $description;

    #[ORM\OneToMany(mappedBy: 'book', targetEntity: Reaction::class, cascade: ['persist'], orphanRemoval: true)]
    private Collection $reactions;

    #[ORM\Column(name: 'created_at', type: 'datetime_immutable')]
    private \DateTimeImmutable $createdAt;

    #[ORM\Column(name: 'updated_at', type: 'datetime_immutable')]
    private \DateTimeImmutable $updatedAt;

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

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

    public function setId(int $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;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): void
    {
        $this->description = $description;
    }

    /**
     * @return Collection<Reaction>
     */
    public function getReactions(): Collection
    {
        return $this->reactions;
    }

    public function setReactions(Collection $reactions): void
    {
        $this->reactions = $reactions;
    }

    public function addReaction(Reaction $reaction): void
    {
        if (!$this->reactions->contains($reaction)) {
            $reaction->setBook($this);
            $this->reactions->add($reaction);
        }
    }

    public function removeReaction(Reaction $reaction): void
    {
        $reaction->setBook(null);
        $this->reactions->removeElement($reaction);
    }

    #[ORM\PrePersist]
    public function prePersist(): void
    {
        $this->createdAt = new \DateTimeImmutable();
        $this->updatedAt = new \DateTimeImmutable();
    }

    #[ORM\PreUpdate]
    public function preUpdate(): void
    {
        $this->updatedAt = new \DateTimeImmutable();
    }

    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function setCreatedAt(\DateTimeImmutable $createdAt): void
    {
        $this->createdAt = $createdAt;
    }

    public function getUpdatedAt(): \DateTimeImmutable
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(\DateTimeImmutable $updatedAt): void
    {
        $this->updatedAt = $updatedAt;
    }
}
<?php

declare(strict_types=1);

use App\Entity\Author;
use App\Entity\Book;
use Doctrine\ORM\EntityManagerInterface;

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

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

$author = new Author();
$author->setName('tanakahisateru');
$newBook = new Book();
$newBook->setTitle('ちょうぜつソフトウェア設計入門');
$newBook->setPrice(3080);
$newBook->setDescription('かわいい絵柄で釣ってオブジェクト指向をガッツリ解説する本');
$newBook->setAuthor($author);

/** @var EntityManagerInterface $entityManager */
$entityManager = require __DIR__.'/bootstrap.php';
$entityManager->persist($author);
$entityManager->persist($newBook);
$entityManager->flush();

$newBook->getCreatedAt(); // 登録日時
$newBook->getUpdatedAt(); // 更新日時
  • DoctrineのLifecycleCallbackを設定することで実現できます。カラムや保存処理は自分で書く必要があります。
  • 全部のエンティティにupdatedAt, createdAtを設定したい場合など、全エンティティに設定するのが面倒な場合はDoctrineExtensions https://github.com/doctrine-extensions/DoctrineExtensionsTimestampable を使うと楽に設定できます。

Eloquent

Models/Book.php
<?php

declare(strict_types=1);

namespace App\Models;

use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Model;

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

    public $timestamps = true;

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

    public function likes()
    {
        return $this->morphMany(Like::class, 'likable');
    }
}
<?php

declare(strict_types=1);

use App\Models\Author;
use App\Models\Book;

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

$author = new Author();
$author->name = 'tanakahisateru';
$author->save();
$newBook = new Book();
$newBook->title = 'ちょうぜつソフトウェア設計入門';
$newBook->price = 3080;
$newBook->description = 'かわいい絵柄で釣ってオブジェクト指向をガッツリ解説する本';
$newBook->author_id = $author->id;
$newBook->save();

$newBook->created_at; // 登録日時がセットされている
$newBook->updated_at; // 更新日時がセットされている
  • Modelの $timestamps プロパティをtrueにセットするだけです。細かいオプション(カラム名を標準から変える等)はすべてModelの所定のプロパティを使って設定します。
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?