カテゴリ: Symfony 更新日: 2025/12/24

Symfony Doctrineでソフトデリートを実装する方法を完全ガイド!初心者でもわかる削除の仕組み

Doctrineでソフトデリートを実装する方法
Doctrineでソフトデリートを実装する方法

先生と生徒の会話形式で理解しよう

生徒

「Symfonyでデータを削除すると、本当にデータベースから消えてしまうんですか?もし復元したくなったら困りそうです…。」

先生

「その通りです。普通の削除ではデータが完全に消えてしまいます。でもDoctrineではソフトデリートという方法を使えば、消したように見えてデータは残したままにできますよ。」

生徒

「消したように見せるってどういう仕組みなんでしょうか?初心者でもできますか?」

先生

「大丈夫です。ソフトデリートは難しそうに見えますが、仕組みを理解するととても便利です。今日はいちばんやさしい方法でソフトデリートを実装するやり方を説明します。」

1. ソフトデリートとは?初心者にも分かりやすいイメージで解説

1. ソフトデリートとは?初心者にも分かりやすいイメージで解説
1. ソフトデリートとは?初心者にも分かりやすいイメージで解説

SymfonyのDoctrine ORMで扱う削除には、大きく2つの方法があります。ひとつは「完全削除」で、データベースから記録そのものを消してしまう方法です。もうひとつが「ソフトデリート」で、削除されたように見せかけながら、本当はデータを残しておく方法です。これはまるで机の引き出しにしまっただけで、他の人からは見えない状態にしておくイメージです。

ソフトデリートを使うと、ユーザーがうっかり削除してしまったデータを後から復元できるメリットがあります。また、削除履歴として残したいときにも便利で、安全性や信頼性を高めたいアプリケーションでよく使われます。SymfonyとDoctrineでは、削除済みかどうかを判定する「削除日」のカラムを用意し、その値が入っている場合は非表示にします。

2. Doctrineでソフトデリートを実装する基本の考え方

2. Doctrineでソフトデリートを実装する基本の考え方
2. Doctrineでソフトデリートを実装する基本の考え方

Doctrineでは、ソフトデリートを実現するために「deletedAt」という日付のプロパティをエンティティに追加します。削除操作を行うと、このdeletedAtに日付が入る仕組みにしておきます。初心者の方には「削除された日時をメモしておく」と考えると分かりやすいです。削除されたものは、通常の検索では表示しないようにしておきます。

重要なのは、削除済みかどうかの判断をSQLではなくエンティティの状態として記録しておく点です。データを物理的に消してしまわずに、「使わない状態にするだけ」という役割分担が、ソフトデリートの大きな特徴です。Symfonyで実際の処理を行うときも、削除メソッドを呼ぶのではなく、deletedAtを更新するだけの仕組みに変わります。

3. ソフトデリート対応のエンティティを作成しよう

3. ソフトデリート対応のエンティティを作成しよう
3. ソフトデリート対応のエンティティを作成しよう

ここではエンティティにdeletedAtを追加し、ソフトデリートを可能にする基本の形を紹介します。初心者の方は「削除されたかどうかを日付で判定する」という部分だけ理解できれば十分です。コードの細かい意味は、ゆっくり覚えていけば大丈夫です。


<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Article
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $title = null;

    #[ORM\Column(type: 'datetime', nullable: true)]
    private ?\DateTime $deletedAt = null;

    public function softDelete(): void
    {
        $this->deletedAt = new \DateTime();
    }

    public function isDeleted(): bool
    {
        return $this->deletedAt !== null;
    }
}

この例では、softDeleteメソッドで削除された日時を記録し、isDeletedメソッドで削除されたかどうかを判定しています。Symfonyで「削除」という操作を行うときは、エンティティマネージャーのremoveを呼ぶのではなく、このsoftDeleteを呼ぶだけにします。これによって、データは残ったまま「削除済み」として扱われるようになります。

4. Repository側で削除済みデータを除外する設計パターン

4. Repository側で削除済みデータを除外する設計パターン
4. Repository側で削除済みデータを除外する設計パターン

ソフトデリートを導入したあとに重要なのは、「削除済みデータをふつうの一覧に表示しない」ための仕組みです。初心者の方が混乱しやすい部分ですが、Repositoryで検索条件をまとめておくととても整理しやすくなります。Repositoryは、Symfonyでデータベースを操作するときの専用係のような存在です。


<?php

namespace App\Repository;

use App\Entity\Article;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class ArticleRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Article::class);
    }

    public function findAllActive(): array
    {
        return $this->createQueryBuilder('a')
            ->andWhere('a.deletedAt IS NULL')
            ->orderBy('a.id', 'DESC')
            ->getQuery()
            ->getResult();
    }
}

このfindAllActiveメソッドでは、削除されていないデータだけを取得する条件をRepositoryにまとめています。これにより、コントローラ側で条件を書かなくても、一覧表示では常に削除されていないデータだけが表示されるようになります。まるで、削除済みのデータが見える棚と見えない棚に分かれているようなイメージです。

5. ソフトデリートを使うと便利な理由と注意点

5. ソフトデリートを使うと便利な理由と注意点
5. ソフトデリートを使うと便利な理由と注意点

ソフトデリートを使うと、削除したデータを後から復元できるため、安全なアプリケーションになります。不正削除や操作ミスにも強くなり、履歴としてデータを残すことができる点もメリットです。また、削除ではなく「非表示」として扱うサービスでは定番の仕組みです。

ただし、注意点として、削除済みデータがデータベースに残り続けるため、長期間の運用ではデータが増えていきます。そのため、完全に不要になったデータを一定期間ごとに削除する仕組みを用意しておくと良いでしょう。初心者の段階ではまず「削除ではなく削除日時を記録する」という考え方を理解しておけば十分です。

SymfonyとDoctrine ORMでソフトデリートを正しく使いこなすと、アプリケーション全体の品質が上がり、安心してデータを管理できるようになります。最初はシンプルなエンティティで試してみて、少しずつ実際のプロジェクトに取り入れていくのがおすすめです。

関連記事:
カテゴリの一覧へ
新着記事
New1
Laravel
LaravelでAPIのレスポンスをテストする方法を完全解説!assertJsonで初心者も安心
New2
CodeIgniter
CodeIgniterでRESTful API開発!初心者でもわかる全体構成ガイド
New3
Symfony
Symfonyのコントローラとは?作成・構造・役割を初心者向けにやさしく解説!
New4
Symfony
Symfonyでバリデーションメッセージを多言語対応する方法!初心者でもわかる国際化の基本
人気記事
No.1
Java&Spring記事人気No1
Laravel
Laravelで動的パラメータをルートに渡す方法!初心者にもやさしいルートパラメータの使い方入門
No.2
Java&Spring記事人気No2
Laravel
Laravelのシングルアクションコントローラとは?使い方と利点
No.3
Java&Spring記事人気No3
Laravel
Laravelでキャッシュを使う方法(ファイル・Redis・Memcached)
No.4
Java&Spring記事人気No4
Laravel
LaravelのBlade構文まとめ!@if @foreach など基本ディレクティブ解説
No.5
Java&Spring記事人気No5
Symfony
Symfonyの依存性注入(DI)とは?コンストラクタでの注入方法を初心者向けに徹底解説
No.6
Java&Spring記事人気No6
Laravel
Laravelで名前付きルートを設定する方法!初心者でもわかるroute()関数の使い方
No.7
Java&Spring記事人気No7
Laravel
Laravelのマイグレーション履歴を確認する方法を徹底解説!migrate:statusの使い方
No.8
Java&Spring記事人気No8
Laravel
Laravelでコントローラを作成する方法(artisanコマンド)