Skip to content

Instantly share code, notes, and snippets.

@denvernine
Created July 14, 2023 10:54
Show Gist options
  • Save denvernine/afadb26e2abdf0c1275a53c8b299a47a to your computer and use it in GitHub Desktop.
Save denvernine/afadb26e2abdf0c1275a53c8b299a47a to your computer and use it in GitHub Desktop.
Laravelでイベントハンドリング

モデルとその関連クラスを作成

php artisan make:model Item --all --api
##   INFO  Model and test [app/Models/Item.php] created successfully.
##
##   INFO  Factory [database/factories/ItemFactory.php] created successfully.
##
##   INFO  Migration [database/migrations/2023_07_14_075406_create_items_table.php] created successfully.
##
##   INFO  Seeder [database/seeders/ItemSeeder.php] created successfully.
##
##   INFO  Request [app/Http/Requests/StoreItemRequest.php] created successfully.
##
##   INFO  Request [app/Http/Requests/UpdateItemRequest.php] created successfully.
##
##   INFO  Controller [app/Http/Controllers/ItemController.php] created successfully.
##
##   INFO  Policy [app/Policies/ItemPolicy.php] created successfully.

下準備

app/Models/Item.php
 <?php

 namespace App\Models;

 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;

 class Item extends Model
 {
     use HasFactory;
+
+    public const TABLE_NAME = 'items';
+
+    protected $table = self::TABLE_NAME;
 }
database/migrations/2023_07_14_075406_create_items_table.php
 <?php

 use Illuminate\Database\Migrations\Migration;
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Support\Facades\Schema;
+use App\Models\Item;

 return new class extends Migration
 {
     /**
      * Run the migrations.
      */
     public function up(): void
     {
-        Schema::create('items', function (Blueprint $table) {
+        Schema::create(Item::TABLE_NAME, function (Blueprint $table) {
             $table->id();
+            $table->string('name');
             $table->timestamps();
         });
     }

     /**
      * Reverse the migrations.
      */
     public function down(): void
     {
-        Schema::dropIfExists('items');
+        Schema::dropIfExists(Item::TABLE_NAME);
     }
 };
database/factories/ItemFactory.php
 <?php

 namespace Database\Factories;

 use Illuminate\Database\Eloquent\Factories\Factory;

 /**
  * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Item>
  */
 class ItemFactory extends Factory
 {
     /**
      * Define the model's default state.
      *
      * @return array<string, mixed>
      */
     public function definition(): array
     {
         return [
-            //
+            'name' => fake()->name(),
         ];
     }
 }

マイグレーションとシーディングを行う。

php artisan migrate
php artisan db
insert into items(name) values ('apple');

イベントとリスナの作成

app/Providers/EventServiceProvider.php
 <?php

 namespace App\Providers;

-use Illuminate\Auth\Events\Registered;
-use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
 use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
 use Illuminate\Support\Facades\Event;
+use App\Domains\Events as DomainEvents;
+use App\Domains\Events\Listeners as DomainEventListeners;

 class EventServiceProvider extends ServiceProvider
 {
     /**
      * The event to listener mappings for the application.
      *
      * @var array<class-string, array<int, class-string>>
      */
     protected $listen = [
-        Registered::class => [
-            SendEmailVerificationNotification::class,
-        ],
+        DomainEvents\ItemEvent::class => [
+            DomainEventListeners\ItemEventLister::class,
+        ],
     ];

     /**
      * Register any events for your application.
      */
     public function boot(): void
     {
         //
     }

     /**
      * Determine if events and listeners should be automatically discovered.
      */
     public function shouldDiscoverEvents(): bool
     {
         return false;
     }
 }

以下のコマンドを実行すると EventServiceProvider.php に記載されているイベントとリスナが生成される。

php artisan event:generate

イベントを使ってみる

routes/api.php
 <?php

 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\ItemController;

 /*
 |--------------------------------------------------------------------------
 | API Routes
 |--------------------------------------------------------------------------
 |
 | Here is where you can register API routes for your application. These
 | routes are loaded by the RouteServiceProvider and all of them will
 | be assigned to the "api" middleware group. Make something great!
 |
 */

 Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
     return $request->user();
 });

+Route::resources([
+    'items' => ItemController::class,
+]);
app/Http/Controllers/ItemController.php
 <?php

 namespace App\Http\Controllers;

 use App\Http\Requests\StoreItemRequest;
 use App\Http\Requests\UpdateItemRequest;
 use App\Models\Item;
+use App\Domains\Events as DomainEvents;

 class ItemController extends Controller
 {
     //...

     /**
      * Display the specified resource.
      */
     public function show(Item $item)
     {
-        //
+        event(new DomainEvents\ItemEvent($item));
     }

     // ...
 }
app/Domains/Events/ItemEvent.php
 <?php

 namespace App\Domains\Events;

 use Illuminate\Broadcasting\Channel;
 use Illuminate\Broadcasting\InteractsWithSockets;
 use Illuminate\Broadcasting\PresenceChannel;
 use Illuminate\Broadcasting\PrivateChannel;
 use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
 use Illuminate\Foundation\Events\Dispatchable;
 use Illuminate\Queue\SerializesModels;
+use App\Models\Item;

 class ItemEvent
 {
     use Dispatchable, InteractsWithSockets, SerializesModels;

     /**
      * Create a new event instance.
      */
-    public function __construct()
-    {
-        //
-    }
+    public function __construct(
+       public readonly Item $item,
+    ) {}
-
-    /**
-     * Get the channels the event should broadcast on.
-     *
-     * @return array<int, \Illuminate\Broadcasting\Channel>
-     */
-    public function broadcastOn(): array
-    {
-        return [
-            new PrivateChannel('channel-name'),
-        ];
-    }
 }
app/Domains/Events/Listeners/ItemEventLister.php
 <?php
 namespace App\Domains\Events\Listeners;

 use App\Domains\Events\ItemEvent;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Support\Facades\Log;
+use Monolog\Handler\StreamHandler;

 class ItemEventLister
 {
     /**
      * Create the event listener.
      */
     public function __construct()
     {
         //
     }

     /**
      * Handle the event.
      */
     public function handle(ItemEvent $event): void
     {
-        //
+        Log::channel('single')->debug('get item! id:{id} name:{name}', (array) $event->item->attributesToArray());
     }
 }

storage/logs/laravel.log に以下が表示される。

[2023-07-14 10:10:52] local.DEBUG: get item! id:1 name:apple {"id":1,"name":"apple","created_at":null,"updated_at":null}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment