Jak działa observer w Laravel?

by admin 2 Comments
Jak działa observer w Laravel?

Cześć tym razem wychodzę ze wpisem na temat jak działa observer w Laravelu. Cały ORM Laravela jest bardzo rozbudowany i pozwala wiele zaawansowanych operacji. Jednak istnieją czasami powody aby użyć czegoś bardziej zaawansowanego m.in. wzorce projektowe. Jeśli używałeś Laravela w projekcie na średnią i dużą skalę, mogłeś napotkać sytuację, w której chciałbyś wykonać jakąś akcję podczas przetwarzania Twojego modelu Eloquent.

Eloquent dostarcza zdarzenia do monitorowania stanu modelu:

  • retrieved – po pobraniu rekordu.
  • creating – przed utworzeniem rekordu.
  • created – po utworzeniu rekordu.
  • updating – przed aktualizacją rekordu.
  • updated – po zaktualizowaniu rekordu.
  • saving – przed zapisaniem rekordu (utworzonego lub zaktualizowanego).
  • saved – po zapisaniu rekordu (utworzonego lub zaktualizowanego).
  • deleting – przed usunięciem rekordu lub miękkim usunięciem rekordu.
  • deleted – po usunięciu rekordu lub soft-deleted.
  • restoring – przed przywróceniem rekordu za pomocą soft-delete
  • restored – po przywróceniu rekordu za pomocą soft-delete

Inicjalizacja projektu

Utwórzmy nowy projekt:

composer create-project --prefer-dist laravel/laravel laravel-observer

Następnie stwórzmy model produkt wraz z migracją, do tego posłużymy się poleceniem:

php artisan make:model Product -m

W pliku konfiguracyjnym .env nie zapomnij nadać odpowiednich parametrów do połączenia się z bazą danych, u mnie ta część wygląda następująco:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laraveldeveloper
DB_USERNAME=root
DB_PASSWORD=

Uzupełniamy tabelę products kolumnami:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->float('price');
            $table->string('description');
            $table->boolean('active');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Wykonuję migrację tabel, czy tworzę je w bazie danych:

php artisan migrate

Jeszcze musimy uzupełnić model Product.php polami w zmiennej $fillable, która odpowiada za nazwy kolumn w naszej bazie.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'price', 'description', 'active'];
}

Tworzenie Observera w Laravel

Jeśli chcesz słuchać zdarzenia, które wykonują się w twojej aplikacji. Przykładem może być aplikacja otomoto.pl podczas gdy obserwujesz dane ogłoszenie i właściciel ogłoszenia zrobi na nim zmianę użytkownikowi, który obserwuje dane ogłoszenie przyjdzie powiadomienie typu push że oferta ogłoszenia została zmieniona. W naszym przypadku jest to stan modelu saved().

Aby wygenerować observer na modelu Product należy wykonać taką komendę w konsoli:

php artisan make:observer ProductObserver --model=Product

W katalogu projektu app/observer pojawił się plik ProductObserver.php

Niestety to nie wystarczy aby nasz observer zaczął działać w związku z tym należy w pliku app\Providers\AppServiceProvider.php w metodzie boot() dodać linijkę która będzie “obserwować” zdarzenia na naszym modelu.

public function boot()
{
    Product::observe(ProductObserver::class);
}

W pliku naszego obserwera dodajmy metodę saving(), która jest odpowiedzialna za nasłuchiwanie zdarzeń podczas gdy model jest tworzony lub aktualizowany.

/**
 * Handle the product "saving" event.
 *
 * @param  \App\Product  $product
 * @return void
 */
public function saving(Product $product)
{
    $product->name = strtoupper($product->name);
}

Funkcja strtoupper() spowoduje że każda litera będzie zamieniona na dużą literę.

Dodatkowo stwórzmy jeszcze kontroller, a także który będzie odpowiedzialny za operacje na Produktach. Wykonajmy komendę w konsoli:

php artisan make:controller ProductController -r

Komenda utworzy plik w katalogu app\Http\Controllers\ProductController.php parametr -r wygeneruje metody które są odpowiedzialne za CRUD całej aplikacji, czyli metody tworzenia, odczytywanie, aktualizacje oraz usuwania danych.

W metodzie store() zapiszmy nasz produkt oraz prześlijmy go to użytkownika:

/**
 * Store a newly created resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\JsonResponse
 */
public function store(Request $request)
{
    $product = new Product([
        'name' => $request->get('name'),
        'price' => $request->get('price'),
        'description'  => $request->get('description'),
        'active'  => $request->get('active')
    ]);
    $product->save();
    return response()->json($product);
}

Dodajmy jeszcze w pliku api.php Routing aby można było wysłać rządzanie do naszego kontrollera.

Route::post('product','ProductController@store');

Przy użyciu narzędzia takiego jak Insomia czy Postman, możemy wysłać żądanie na ten adres – nazwanaszegoserwera.pl/api/product

W odpowiedzi dostaję poprawnie zwrócony model mojego produktu:

Pole name tak jak widać jest z dużych liter, co oznacza że obserwer działa prawidłowo.

Przykłady wykorzystania obserwera w praktyce:

  • Wysyłanie powiadomień użytkownikom
  • Wysłanie obecnego stanu modelu do aplikacji zewnętrznych
  • Modyfikacja poszczególnych pól wprowadzanych przez użytkowników

Widzisz jakieś inne zastosowanie obserwera w praktyce, napisz w komentarzu.

Jeśli potrzebujesz więcej informacji zachęcam do poczytania w dokumentacji Laravela, odnośnie wzorca observer.

Kod utworzonego projektu możesz znaleźć na: Github

Zachęcam także do przeczytania innego mojego artykułu: 7 powodów dlaczego laravel jest świetnym frameworkiem.

Comments ( 2 )

  1. MW
    Bardzo przyjemnie się czyta. Czekam na kolejne Dzięki
    • admin
      Planuję wypuszczać wpisy co 2 tygodnie więc stay tuned :)

Leave a reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>