Entendendo o Soft Delete do Laravel

Adicione esse recurso ao seu leque de ferramentas de desenvolvimento web.

Gabriel Albuquerque (Albuca)
7 min readAug 14, 2020
Imagem de fundo por Ellie Burgin em Pexels: https://www.pexels.com/@ellie-burgin-1661546

O Soft Delete

Soft Delete é um nome não comum para algo que costumamos fazer todo dia no nosso computador. Seja você usuário de Windows, Linux ou Mac, com certeza você conhece o conceito de lixeira (sim, lixeira), quando você tem um arquivo ou pasta que não tem mais uso, você provavelmente apaga esse arquivo, mas por padrão, ele não é removido do seu HD ou dispositivo de memória automaticamente, ele vai para a lixeira, onde você pode decidir se esse arquivo será apagado permanentemente ou restaurado para o lugar de onde foi ‘apagado’.

O Soft Delete é uma técnica que faz exatamente o mesmo, você apaga um item/registro através de sua aplicação e ele some, porém ele continua existindo no banco de dados e caso você queira, você pode apagá-lo permanentemente (excluindo do db) ou então restaurá-lo como se nada tivesse ocorrido.

Por baixo dos panos funciona da seguinte maneira: Você adiciona um campo de SD na sua tabela, e ao apagar um registro pela aplicação, nós alteramos esse campo de Soft Delete para, por exemplo, ‘invisível’ e quando dermos um get na tabela, a aplicação através de uma regra de negócio, vai ler esse campo, e se o campo tiver o valor ‘invisível’, ele não será exibido. Ou seja, o registro sempre vai existir, porém é a aplicação ocultará ele.

Soft Delete no Laravel

Achou interessante? E se eu te falar que o Laravel já implementa o Soft Delete por padrão? Isso mesmo, o ORM Eloquent presente no Laravel consegue fazer Soft Delete sem precisar instalar nenhum componente extra, com apenas algumas configurações e você poderá apagar, restaurar ou apagar permanentemente qualquer registro através de sua aplicação.

Vamos exemplificar o uso dessa feature com uma tabela de posts, se quiser me acompanhar você já precisa ter seu Banco de Dados criado e setado no environment da aplicação, o meu .env está basicamente assim (ignore os comentários)

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=soft_delete # O nome do Schema criado
DB_USERNAME=root # Username padrão do MySQL
DB_PASSWORD= # Padrão (nenhuma senha)

Apesar de trabalhar com posts, o que faremos aqui servirá para qualquer tipo de tabela ou registro.

Configuração na camada de Model

Agora que sabemos o que é Soft Delete e como ele está presente no Laravel, vamos criar o Model para que seja possível utilizar o recurso, em um console aberto na raíz do projeto basta rodar (ignore os comentários):

php artisan make:model Post -m# php artisan: Uso do PHP para execução do artisan do Laravel
# make:model: Uso do artisan para criar um model
# Post: Nome do Model
# -m: Flag para criação de uma migration para esse model

Model criado, agora vamos configurá-lo para usarmos o SD, é nessa configuração que o Laravel impressiona ainda mais, normalmente seriam escritas várias linhas de código para configurar esse recurso em uma aplicação, mas o framework ‘ativa’ essa feature com apenas uma linha de código, o arquivo de Model vai ficar mais ou menos assim:

// Arquivo app/Posts.phpuse Illuminate\Database\Eloquent\SoftDeletes;class Post extends Model
{

// Ativação do recurso
use SoftDeletes;
}

Está pronto! Com apenas essa linha você já pode trabalhar com o Soft Delete no Model.

Configuração no Banco de Dados

O recurso está ativo, porém o soft delete requer um campo na tabela dentro do DB, mas isso será fácil de configurar com as Migrations do Laravel, no console, dentro da raíz do projeto rode:

php artisan make:migration add_column_posts_softdelete --table=posts# Seguir sempre a nomeclatura: add_column_<tabela>_<campo>
# --table=posts: Especificação da tabela a ser alterada
database/migrations/<suadata>_add_column_posts_softdelete.php

Esse comando vai criar uma Migration, migration é um recurso que (entre várias coisas) permite que a aplicação se comunique diretamente com a base de dados criando/alterando colunas e tabelas, em poucas palavras, essa migration vai criar um campo na nossa tabela de posts (por isso especificamos com ‘ — table’). Se quiser saber mais sobre Migrations e entender melhor o processo, dê uma lida nesse artigo meu em que eu explico o básico.

Migration criada, o arquivo de migration se encontra em database/migrations/ ele terá um prefixo relativo à sua data atual + o nome especificado no comando, dentro dele você encontrará uma classe com o nome do comando, dentro dessa classe terão dois métodos, o up() e o down().

A grosso modo, o método up será executado quando a migration rodar, ele deve realizar as ações que queremos e o down será executado quando desejarmos fazer um rollback (desfazer as alterações), então o up deve realizar a ação (criar o campo) e o down deve desfazer a ação (remover o campo).

No método up devemos especificar que queremos uma coluna soft delete na nossa tabela:

// UP -> Cria campo requerido pelo Soft Delete
public function up()
{
// Na tabela 'posts', execute a function:
Schema::table('posts', function (Blueprint $table) {
// Acesse a tabela e crie os campos de soft delete
$table->softDeletes();
});}

Já no método down, devemos dropar a coluna de Soft Delete:

// Down -> Remove o campo criado por UP
public function down()
{
// Na tabela 'posts', execute a function:
Schema::table('posts', function (Blueprint $table) {

// Acesse a tabela e remova os campos de soft delete
$table->dropSoftDeletes();
});}

No fim das contas, a classe da sua migration deverá ficar mais ou menos assim:

Minha migration finalizada

Para rodar essa migration e inserir os campos de Soft Delete, no console digite:

php artisan migrate
Mensagem de sucesso do artisan

Após isso, na sua tabela do DB terá as colunas ‘id’, ‘created_at’ ‘updated_at’ (criados pela flag ‘-m’ usada na criação do Model) e também terá a coluna ‘deleted_at’ (criado pela migration que acabamos de configurar) esse campo referencia a data e hora em que o registro em questão foi apagado pela aplicação. Esse ‘deleted_at’ é equivalente ao nosso ‘invisível’ explicado anteriormente, através dele a aplicação fará a regra de negócio em relação ao registro.

Controller

Nesse ponto, todas as configurações já foram feitas e sua aplicação já é capaz de realizar o Soft Delete, vou demonstrar alguns exemplos de deleção, restauração e deleção permanente de registros através da camada de Controller. Não irei entrar em detalhes sobre a criação de controllers ou rotas para acessá-los por conta que isso iria fora do escopo do artigo.

A deleção não é diferente do delete padrão que é normalmente feito, a diferença é que após feita, o registro no banco de dados recebe o valor de ‘deleted_at’ igual à data e hora do momento da deleção:

class PostController extends Controller
{
// Metodo de delecao simples
public function destroy(Post $post)
{
// Encontre o post de id = ao passado, e o remova
Post::find($post->id)->delete();
}
}

Registro deletado, se você checar no seu banco de dados, o registro agora tem um valor de ‘deleted_at’ equivalente à data e hora atuais, ou seja, ele está ‘invisível’ para sua aplicação.

Veja o campo deleted_at preenchido

Podemos agora escolher entre restaurar ou deletar permanentemente esse registro, vamos primeiro restaurá-lo, para acessar um registro apagado é usado o método ‘onlyThrashed’, o método where irá receber o id do registro, para assim selecionarmos o registro que desejamos. O método responsável por restaurar o registro é o ‘restore’, a restauração ficará mais ou menos assim:

class PostController extends Controller
{
// Metodo de restauracao
public function restore($post) // Leia os comentários do final
{
// Encontre entre os excluidos o post de id = ao passado
$post = Post::onlyThrashed()->where([
'id' => $post
]);
// Restaure o post
$post->restore();
}
}
/*
* Como não estamos lidando com um registro 'visível', a injeção de * dependência no parâmetro do método não funcionará. Por isso estou * usando '$post' e não especificando a classe com 'Post $post'
*/
Tanto quando criamos, tanto quando restauramos, o registro terá o ‘deleted_at’ igual a ‘null’

Registro restaurado, se você olhar ele no DB verá que o campo de deleted será null, portanto nosso registro está de volta à aplicação.

Mas ainda podemos deletar permanentemente, ou seja, podemos apagar ele do banco de dados, semelhantemente à restauração, precisamos selecionar o registro ‘thrashed’ e o armazenar dentro de uma variável, a diferença é que o método executado na variável será ‘forceDelete’ (e não ‘restore’), seu controller ficará mais ou menos assim:

class PostController extends Controller
{
// Metodo de delete permanente
public function forceDelete($post) // Sem usar o 'Post'
{
// Encontre entre os excluidos o post de id = ao passado
$post = Post::onlyThrashed()->where([
'id' => $post
])->first();
// Apague o post
$post->forceDelete();
}
}

Após isso, seu registro será apagado da aplicação e do seu banco de dados.

Conclusão

Bom, acredito que o que escrevi tenha sido proveitoso e que você tenha entendido o que foi explicado.

Soft Delete é algo interessante, sofisticado e é um ótimo recurso para qualquer aplicação, o que foi escrito aqui é só um exemplo de aplicação do recurso, mas as possibilidades são várias, você pode, por exemplo, criar um sistema de lixeiras para posts de um blog, se for uma aplicação que tem usuários, em pedidos de deleção de conta você pode deixar a conta na ‘trashed’ por determinado tempo e depois remover ela efetivamente.

É claro, não deixe de ler a documentação oficial do Laravel e também a parte que fala sobre Soft Deleting, leia-as, faça seus testes e aprenda. Bons estudos!

--

--

No responses yet