Usando Observadores Do Modelo Laravel

O Laravel Model Observers é um ótimo recurso. Observadores são usados ​​para agrupar ouvintes de eventos para um modelo. Nomes de métodos de classes de observadores referem-se ao evento Eloquent que você deseja ouvir. Esses métodos recebem o modelo como seu único argumento. O Laravel não inclui um diretório padrão para observadores. Além disso, o comando artesanal para gerar observadores também não está disponível por padrão.

Vamos implementar Model Observers em um projeto laravel e entender através de um exemplo simples.

Começando o projeto

laravel new observables

Configure seu banco de dados e adicione as credenciais. envArquivo. Estaremos demonstrando observadores através de um exemplo simples de produto. Primeiro, crie um modelo, um controlador e uma migração do produto, executando o seguinte comando:

php artisan make:model Product -mc

Adicionamos os sinalizadores m e c no comando acima. 
Eles também criarão migração e controlador para o modelo respectivamente. 
Agora, atualize o esquema no arquivo de migração que criamos na etapa anterior. 
Será nomeado
create_products_table.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->text('description');
        $table->integer('price');
        $table->integer('quantity');
        $table->timestamps();
    });
}
Execute o seguinte comando para migrar seu banco de dados:
php artisan migrate

Ele irá criar tabela de produtos. Agora, vamos configurar nossas rotas no arquivo routes / web.php. Haverá duas rotas para criar um produto e armazenar um produto. Aqui estão os conteúdos:
1
2
Route::get('/product', 'ProductController@create');
Route::post('/product', 'ProductController@store');
Criando lógica de visualização e back-end
Agora vamos criar nossa visão. Crie uma nova vista com o nome create.blade.php, dentro do diretorio: resources/views
Copie o conteúdo abaixo para a visualização.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Model Observer</title>
</head>
<body>
    <div class="container" style="margin-top: 50px;">
        <div class="row">
            <div class="col-sm-10 offset-sm-1">
                @if($message = session()->pull('message'))
                    <div class="alert alert-success">{{ $message }}</div>
                @endif
                <form method="post" action="/product">
                    {{ csrf_field() }}
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" class="form-control" id="name" name="name" placeholder="Enter Product Name">
                    </div>
                    <div class="form-group">
                        <label for="description">Description</label>
                        <textarea name="description" id="description" class="form-control"
                                  placeholder="Enter Product Description"></textarea>
                    </div>
                    <div class="form-group">
                        <label for="price">Price</label>
                        <input type="number" class="form-control" id="price" name="price" placeholder="Enter Product Price">
                    </div>
                    <div class="form-group">
                        <label for="quantity">Quantity</label>
                        <input type="number" class="form-control" id="quantity" name="quantity"
                               placeholder="Enter Product Quantity">
                    </div>
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary" name="submit">Submit</button>
                    </div>
                </form>
                @if(count($errors))
                    <ul class="alert alert-danger well">
                        @foreach($errors->all() as $error)
                            <li class="list-unstyled">{{ $error }}</li>
                        @endforeach
                    </ul>
                @endif
            </div>
        </div>
        @if(count($products))
            <hr class="dl-horizontal">
            <div class="row">
                <div class="col-sm-10 offset-sm-1">
                    <table class="table table-dark">
                        <thead>
                        <tr>
                            <th scope="col">#</th>
                            <th scope="col">Name</th>
                            <th scope="col">Description</th>
                            <th scope="col">Quantity</th>
                            <th scope="col">Price</th>
                        </tr>
                        </thead>
                        <tbody>
                        @foreach($products as $product)
                            <tr>
                                <th scope="row">{{ $loop->iteration }}</th>
                                <td>{{ $product->name }}</td>
                                <td>{{ $product->description }}</td>
                                <td>{{ $product->quantity }}</td>
                                <td>{{ $product->price }}</td>
                            </tr>
                        @endforeach
                        </tbody>
                    </table>
                </div>
            </div>
        @endif
    </div>
</body>
</html>
Nessa visão, estamos simplesmente criando um formulário para criar um produto usando o
estilo bootstrap 4. Link para o arquivo css de bootstrap é adicionado na seção head. 
Depois disso, estamos adicionando uma tabela que mostrará todos os produtos disponíveis.
 No topo, há uma caixa de alerta que mostrará se a criação do produto foi bem-sucedida.
Agora, vamos configurar nosso controlador. Copie o conteúdo abaixo para o arquivo ProductController.php.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
namespace App\Http\Controllers;
use App\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
    public function create()
    {
        $products = Product::all();
        return view('create', compact('products'));
    }
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'description' => 'required',
            'price' => 'required|numeric',
            'quantity' => 'required|numeric'
        ]);
        $product = new Product();
        $product->name = $request->name;
        $product->description = $request->description;
        $product->price = $request->price;
        $product->quantity = $request->quantity;
        $product->save();
        return redirect('/product')->with('message', 'Product created successfully');
    }
}
No método de criação, estamos simplesmente disponibilizando todos os modelos de produtos e retornando a visualização.
Em seguida, no método de armazenamento, primeiro os dados são validados e, em seguida, um novo produto é criado e salvo no banco de dados. Em seguida, redirecionamos para a página do produto com a mensagem de sucesso exibida na parte superior da página.
Usando Observadores do Modelo
Agora digamos que o preço do produto precisa ser atualizado. 
Temos que adicionar algum imposto ao preço do produto. Além disso, 
para qualquer produto criado com quantidade superior a 10, daremos uma compensação 
de 50% no imposto. Mas não queremos adicionar essa lógica ao nosso controlador. 
Podemos usar eventos de modelo que são disparados automaticamente por laravel quando 
o novo registro é criado, atualizado ou excluído.
Esta é a lista de todos os eventos, modelo eloquente disparado que podemos ligar
  • retrieved
  • creating
  • created
  • updating
  • updated
  • saving
  • saved
  • deleting
  • deleted
  • restoring
  • restored
Você pode encontrar eventos mais eloqüentes nos documentos oficiais do laravel. Agora vamos escrever nossa lógica para o método de inicialização presente em app / Provides / AppServiceProvider.php.
1
2
3
4
5
6
7
8
9
10
11
public function boot()
{
    \App\Product::creating(function ($model) {
        $tax = .20;
        if ($model->quantity < 10) { $model->price += $model->price * $tax;
        } else if ($model->quantity >= 10) {
            $model->price += $model->price * ($tax / 2);
        }
    });
}
Agora, no momento da criação, estamos ignorando o valor do preço com base em sua quantidade. Então, aqui nós usamos o modelo de evento para criar o trabalho.
Também podemos criar uma classe dedicada que forneça métodos de evento eloquentes para um modelo específico.

Creating dedicated model observers

Adicionar todo o código do observador no AppServiceProvider não é uma boa escolha. Podemos criar classes dedicadas para cada modelo. Primeiro, precisamos criar um provedor de serviços. Execute o seguinte comando para criá-lo:
php artisan make:provider ProductModelServiceProvider

Registre o provedor de serviços adicionando a seguinte entrada à matriz de provedores no arquivo config / app.php:
1
App\Providers\ProductModelServiceProvider::class,
Observadores não podem ser criados por meio da linha de comando por padrão. Então, vamos criar um diretório Observer dentro da pasta do aplicativo. Dentro da pasta Observer, crie o arquivo ProductObserver.php com o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
namespace App\Observer;
use App\Product;
class ProductObserver
{
    public function creating(Product $product)
    {
        $tax = .20;
        if ($product->quantity < 10) {
            $product->price += $product->price * $tax;
        } else if ($product->quantity >= 10) {
            $product->price += $product->price * ($tax / 2);
        }
    }
}
Vá para o arquivo ProductModelServiceProvider.php e inclua o seguinte no método de inicialização. Ele dirá a laravel que estamos observando o modelo Product na classe ProductObserver.
1
\App\Product::observe(\App\Observer\ProductObserver::class);
Agora remova o observador de criação que adicionamos no arquivo AppServiceProvider.php.
O carregamento automático dos arquivos pode não funcionar corretamente porque criamos uma pasta e adicionamos nosso arquivo observável. Execute os dois comandos a seguir, um a um, para garantir que você não receberá erros:

# Autoloading of files
composer dump

# Configure the cache
php artisan config:cache

Agora teste o aplicativo e você encontrará o preço alterado com base na quantidade.
É assim que podemos usar o Model Observers no aplicativo Laravel. Eles são muito úteis para refatorar nosso código e trabalhar com o cache.
Veja como o aplicativo se parece:

Você pode encontrar todo o código fonte para esta aplicação simples aqui

Fonte do conteúdo