- How do I replace a Laravel model observer with column watchers?
- Start by identifying observer methods that check specific columns (e.g., `wasChanged('status')`). Convert them into dedicated watcher handlers using the `#[Watcher]` attribute. For example, replace `saved()` logic for a single column with a handler targeting that column. Use `Timing::BEFORE_SAVE` or `Timing::AFTER_SAVE` to match the original observer’s timing. Test incrementally to avoid regressions.
- Can I use column watchers for audit logging in Laravel?
- Yes. Attach a watcher to columns like `updated_at`, `status`, or custom metadata fields. In the handler, log the old and new values using the `ColumnChange` object’s `getOldValue()` and `getNewValue()` methods. For performance, queue the logging job if it involves I/O operations. This avoids bloating your model with observer logic for every column.
- Does Laravel Column Watcher support queueable handlers for async processing?
- Absolutely. Mark your handler with `#[Watcher(queueable: true)]` to dispatch it to Laravel’s queue system. This is ideal for time-consuming tasks like sending notifications or updating external APIs. Failed jobs will use Laravel’s queue failure channels, so ensure you configure those for monitoring. Works with database or Redis queues.
- What Laravel versions and PHP requirements does this package need?
- The package requires Laravel 11, 12, or 13 and PHP 8.2+. It leverages PHP 8 attributes, so older PHP versions or Laravel 10 won’t work. If you’re on a legacy stack, consider alternatives like traditional observers or custom accessors. For new projects, this aligns perfectly with Laravel’s modern feature set.
- How do I test column watchers in Laravel with Pest or PHPUnit?
- Use Laravel’s `DatabaseTransactions` trait to test watchers. For queued handlers, manually dispatch them or use `Queue::fake()` to assert they’re pushed to the queue. Test edge cases like mass assignments or soft deletes by triggering changes via `Model::forceFill()` or `Model::restore()`. The `ColumnChange` object provides methods like `wasChanged()` to verify state changes in tests.
- Can I watch multiple columns with a single handler in Laravel Column Watcher?
- No, each handler is tied to a single column via the `columns` attribute in `#[Watcher]`. However, you can register multiple watchers on the same model to handle different columns. For example, one handler for `status` and another for `price`. This granularity avoids the monolithic logic found in traditional observers.
- What happens if a handler throws an exception during a model save?
- By default, exceptions in `afterSave` handlers will cause the model save to fail. For `beforeSave` handlers, exceptions will also halt the save. To handle failures gracefully, wrap handler logic in try-catch blocks or use queueable handlers with Laravel’s queue failure channels. Ensure your queue worker is configured to retry or log failures appropriately.
- How do column watchers interact with Laravel Octane’s real-time features?
- Column watchers are fully compatible with Laravel Octane. Handlers can dispatch events or broadcast updates in real-time when watched columns change. For example, a `status` column watcher can trigger a `StatusUpdated` event, which Octane can then push to connected clients via WebSockets. This is perfect for live dashboards or collaborative apps.
- Are there performance concerns with watching many columns on high-traffic models?
- The package introduces minimal overhead during model initialization (attributes are parsed once). For high-traffic models, consider lazy-loading handlers or using queueable handlers to offload work. Avoid watching columns that change frequently but don’t require immediate action. Profile your application to identify bottlenecks, especially if using `beforeSave` handlers that might delay saves.
- What alternatives exist if I can’t use PHP 8.2+ or Laravel 11+?
- For older Laravel versions, consider traditional model observers with manual column checks (e.g., `if ($model->wasChanged('column'))`). Alternatively, use Laravel’s accessors/mutators or custom traits to encapsulate column-specific logic. Packages like `spatie/laravel-activitylog` offer audit logging without column watchers, though they lack the granularity of this solution.