LoginSignup
0
1

More than 5 years have passed since last update.

Symfony3で論理削除の導入

Last updated at Posted at 2018-11-21

概要

仕事で論理削除を実装する必要が出てきたので調べたついでに残しておく

環境

  • PHP → 7.1.23
  • symfony/symfony → v3.4.18
  • doctrine/orm → v2.6.2
  • gedmo/doctrine-extensions → v2.4.36
  • stof/doctrine-extensions-bundle → v1.3.0

設定

Doctrine拡張のインストール

$ composer require stof/doctrine-extensions-bundle

バンドルの有効化

app/AppKernel.php
<?php 
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            // ...

            new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),

            // ...
        ];
    {
}

Configに設定

app/config/config.yml
doctrine:
    orm:
        # フィルターを利用したい場合はこれも書く
        filters:
            softdeleteable:
                class: 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter'
                enabled: true

# 論理削除設定
stof_doctrine_extensions:
    default_locale: '%locale%'
    orm:
        default:
            softdeleteable: true

Entityの準備

src/AppBundle/Entity/Product.php
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Class Product
 * @package AppBundle\Entity
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
 * @ORM\Table(name="product")
 * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)
 */
class Product
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $deletedAt;

    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return \DateTime
     */
    public function getDeletedAt()
    {
        return $this->deletedAt;
    }

    /**
     * @param \DateTime $deletedAt
     */
    public function setDeletedAt($deletedAt)
    {
        $this->deletedAt = $deletedAt;
    }
}

DBに反映

$ bin/console doctrine:schema:update --force

使用例(フィルターと論理削除)

src/AppBundle/Controller/Admin/ProductController.php
<?php 

/**
 * Class ProductController
 * @package AppBundle\Controller\Admin
 * @Route("/admin/product")
 */
class ProductController extends Controller
{
    /**
     * 製品一覧(フィルター適用例)
     * @Route("/", name="admin_product_list")
     * @Method("GET")
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function listAction(Request $request)
    {
        // 製品一覧取得
        /** @var EntityManager $em */
        $em = $this->getDoctrine()->getManager();
        // 論理削除したデータも含めて取得したい場合はフィルターを適用する(soft-deleteableは古い記述の仕方っぽい)
        $em->getFilters()->disable('softdeleteable');
        $products = $em->getRepository(Product::class)->findAll();

        dump($products)

        // ...
    }
    // ...

    /**
     * 製品削除(論理削除例)
     *
     * @Route("/{id}/delete", name="admin_product_delete")
     * @Method("DELETE")
     * @param Request $request
     * @param Product $product
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function deleteAction(Request $request, Product $product)
    {
        // ...

        // Entityで指定さえしておけば特別な記述なく論理削除できる
        $em = $this->getDoctrine()->getManager();
        $em->remove($product);
        $em->flush();

        // 現バージョンは2回削除を実行する事で物理削除となる(バグ?)
        // $em->remove($product);
        // $em->flush();

        // 正常動作はこちらのはず
        // $em->getFilters()->disable('softdeleteable');
        // $em->remove($product);
        // $em->flush();

        // ...
    }
}

注意点

  • 論理削除したデータを取得しないのはORMを利用する場合だけなのでDQLとクエリビルダの時はwhereで指定する

参考文献

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