¿Cómo hacer SoftDelete en Symfony?

soft-delete-symfony.jpg
Solucionex
15
Nov 18

Lo primero es saber a qué nos referimos con "soft delete", hacer dicha operación es eliminar nuestros elementos de una forma lógica, manteniendo la tupla en la base de datos, pero desapareciendo de nuestra aplicación desarrollada en Symfony como si la hubiésemos eliminado físicamente los elementos de las tablas.

Esto nos permite dar una mayor seguridad a los programas que desarrollamos, ya que habrá ciertos elementos que quizá queramos evitar que el usuario final los elimine por error, pudiéndolos recuperar de la base de datos, ya que el elemento se encontrará en ella, pero habiéndose marcado con un campo como borrado.

Para ello utilizaremos el bundle StofDoctrineExtensionsBundle que tiene varias herramientas para facilitarnos la vida cuando queremos programar en Symfony. Configurarlo es muy sencillo, con seguir la documentación de Symfony no deberíamos tener ningún problema, pero resumiendo:

        
  • Añadimos el bundle
        $ composer require stof/doctrine-extensions-bundle     
  •     
  • Lo añadimos al AppKernel.php o al bundles.php, dependiendo de la versión de Symfony que estemos usando:
    Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],     
  •     
  • Editamos el config.yml (en Symfony 2 o 3) o el config/packages/doctrine.yaml (en Symfony 4)          doctrine:
      orm:
        filters:
            softdeleteable:
              class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
            enabled: true
        

Ahora ya podremos configurar las entidades que queremos que tengan un borrado lógico y no físico con unas simples anotaciones que podemos ver en la documentación oficial, suponiendo que tenemos una entidad llamada Article, tendríamos que poner lo siguiente para que la fecha de borrado se almacene en el campo "deletedAt":

<?php
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/** * @ORM\Entity * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true) */
class Article {
/**
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
 private $id;

  /**
 * @ORM\Column(name="title", type="string")
 */
 private $title;

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

...

 

Después de esta operación, en todos los Select que se hagan de la entidad Article se ignorarán por defecto aquellos elementos cuyo campo "deletedAt" sea distinto de nulo.

Si en nuestra aplicación tuviésemos un administrador que necesitase ver los elementos borrados, sin tener que acceder a la base de datos física, también es posible. Tendríamos que deshabilitar el filtro del softdelete para poder extraerlas de las tablas, esto sería utilizando estas dos líneas de código en el controlador, por ejemplo:

$filters = $this->getDoctrine()->getManager()->getFilters();
$filters->disable('softdeleteable');

Después de aplicar esta configuración, tendremos una aplicación con unos datos más consistentes, seguros y a salvo de usuarios manazas.