Nauczymy się tworzyć observer w praktyce, wykorzystamy istniejący projekt i ostatnią migrację, warto przypomnieć sobie lekcję teoretyczną o observerach. Do dzieła.
Ok, przypomnijmy sobie te komendy. Ta sprawdza, czy notatka jest usunięta:
Artisan::command('note-is-trashed {id}', function (int $id) {
$note = Note::withTrashed()->findOrFail($id);
$this->comment($note->trashed() ? "true" : "false");
});
Ta usuwa notatkę:
Artisan::command('note-delete {id}', function (int $id) {
$note = Note::withoutTrashed()->findOrFail($id);
$note->delete();
$this->comment($note->trashed() ? "true" : "false");
});
Ta przywraca notatkę:
Artisan::command('note-restore {id}', function (int $id) {
$note = Note::withTrashed()->findOrFail($id);
$note->restore();
$this->comment($note->trashed() ? "true" : "false");
});
Mamy też komendy z fasadą DB. Usuwanie:
Artisan::command('note-delete-db {id}', function (int $id) {
$affected = DB::table("notes")
->where("id", $id)
->update(["deleted_at" => \Carbon\Carbon::now()]);
$this->comment("updated - deleted");
$this->comment($affected);
});
Przywracanie z fasadą DB:
Artisan::command('note-restore-db {id}', function (int $id) {
$affected = DB::table("notes")
->where("id", $id)
->update(["deleted_at" => null]);
$this->comment("updated - restored");
$this->comment($affected);
});
Metody z fasadą DB są o tyle dobre, że nie odpalają eventów observera, to warto pamiętać. Ok, zróbmy observer:
php artisan make:observer NoteObserver --model=Note
Teraz go sobie napiszemy:
<?php
namespace App\Observers;
use App\Models\Note;
class NoteObserver
{
/**
* Handle the Note "created" event.
*/
public function created(Note $note): void
{
//
}
/**
* Handle the Note "updated" event.
*/
public function updated(Note $note): void
{
}
/**
* Handle the Note "deleted" event.
*/
public function deleted(Note $note): void
{
$note->delete_count += 1;
$note->save();
}
/**
* Handle the Note "restored" event.
*/
public function restored(Note $note): void
{
$note->restore_count += 1;
$note->save();
}
/**
* Handle the Note "force deleted" event.
*/
public function forceDeleted(Note $note): void
{
//
}
}
Update count zostawiamy na następną lekcję, na razie tego NIE ruszajmy. Ok, podpinamy observer do modelu przez atrybut:
//(...)
use App\Observers\NoteObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
#[ObservedBy([NoteObserver::class])]
#[ScopedBy([HiddenScope::class])]
class Note extends Model
{
use HasFactory;
use SoftDeletes;
protected $fillable = ['title', 'content', ];
public function author(){
return $this->belongsTo(Person::class, "person_id");
}
public function scopeHiddenOnly(Builder $query): void
{
$query->withoutGlobalScope(HiddenScope::class)->where('hidden', true);
}
}
Zawsze pamiętamy o importach. Ok, teraz możemy usunąć i przywrócić notatkę. Zobaczymy w bazie danych, że delete count i restore count automatycznie nam się ustawia.
Jeżeli użyjemy metod z fasadą DB, nie będzie nam się ustawiać.
Oczywiście możemy napisać komendę, która po cichu usunie notatkę, wtedy observer też się nie odpali:
Artisan::command('note-delete-quiet {id}', function (int $id) {
$ret_val = Note::withoutEvents(function() use($id){
$note = Note::withoutTrashed()->findOrFail($id);
$note->delete();
return "deleted quietly";
});
$this->comment($ret_val);
});
Teraz notatka zostanie usunięta, ale delete count nie będzie zmieniony, bo eventy observera się nie odpalą.
Update count to temat następnej lekcji, niech to się w głowie ułoży.