Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Watchable Laravel Package

jamesmills/watchable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require jamesmills/watchable
    

    For Laravel <5.5, register the service provider in config/app.php:

    'providers' => [
        // ...
        Jamesmills\Watchable\WatchableServiceProvider::class,
    ],
    
  2. Enable Watchable on a Model: Use the Watchable trait in your Eloquent model (e.g., Post.php):

    use Jamesmills\Watchable\Watchable;
    
    class Post extends Model
    {
        use Watchable;
    }
    
  3. Migrate the Database: Publish and run the migrations:

    php artisan vendor:publish --provider="Jamesmills\Watchable\WatchableServiceProvider" --tag="migrations"
    php artisan migrate
    
  4. First Use Case: Watch a model instance:

    $post = Post::find(1);
    $post->watch(); // User is authenticated via Laravel's auth
    

Implementation Patterns

Core Workflows

  1. Watching/Unwatching Models:

    // Watch a model
    $post->watch(); // Creates a watch record for the authenticated user
    
    // Unwatch a model
    $post->unwatch(); // Removes the watch record
    
    // Check if a model is watched
    $isWatched = $post->isWatched(); // Returns boolean
    
  2. Querying Watched Models: Fetch all watched models for the current user:

    $watchedPosts = Post::watched()->get();
    
  3. Events and Notifications: Listen for watched and unwatched events:

    // In EventServiceProvider
    protected $listen = [
        'Jamesmills\Watchable\Events\Watched' => [
            'App\Listeners\SendWatchNotification',
        ],
        'Jamesmills\Watchable\Events\Unwatched' => [
            'App\Listeners\HandleUnwatchLogic',
        ],
    ];
    

    Trigger notifications via the notify method:

    $post->watch()->notify(new PostWatchedNotification());
    
  4. Customizing Watch Behavior: Override the getWatchableKey() method in your model to use a custom key (e.g., slug):

    public function getWatchableKey()
    {
        return $this->slug;
    }
    

Integration Tips

  1. Middleware for Protected Routes: Use middleware to restrict access to watched models:

    Route::middleware(['auth', 'can:view-watched'])->group(function () {
        Route::get('/watched', [PostController::class, 'index']);
    });
    
  2. Eager Loading Watched Models: Optimize queries by eager-loading watches:

    $posts = Post::with(['watches' => function($query) {
        $query->where('user_id', auth()->id());
    }])->get();
    
  3. Batch Processing: Use syncWatched() to update watches in bulk (e.g., for syncing with an external service):

    $post->syncWatched([1, 2, 3]); // Watch IDs 1, 2, 3
    
  4. Scopes for Complex Queries: Combine scopes for advanced filtering:

    $watchedAndPublished = Post::watched()->published()->get();
    

Gotchas and Tips

Pitfalls

  1. Authentication Dependency:

    • The package assumes the current user is authenticated. Always verify auth()->check() before calling watch()/unwatch().
    • Fix: Wrap calls in middleware or add checks:
      if (auth()->check()) {
          $post->watch();
      }
      
  2. Key Collisions:

    • If getWatchableKey() returns the same value for multiple models, watches may behave unexpectedly.
    • Fix: Ensure uniqueness (e.g., use id by default or override getWatchableKey() carefully).
  3. Migration Conflicts:

    • The watches table may conflict with existing tables if not published correctly.
    • Fix: Run php artisan vendor:publish --tag=migrations and review the generated migration.
  4. Event Listener Order:

    • Events (Watched, Unwatched) fire after the watch is created/removed. If you need pre-actions, use model observers or middleware.

Debugging

  1. Check Watch Records: Inspect the watches table directly or log queries:

    \DB::enableQueryLog();
    $post->watch();
    \Log::info(\DB::getQueryLog());
    
  2. Verify User ID: Ensure the user_id in the watches table matches the authenticated user:

    $this->assertEquals(auth()->id(), $post->watches()->first()->user_id);
    
  3. Clear Cached Config: If changes to config aren’t reflected, clear the config cache:

    php artisan config:clear
    

Extension Points

  1. Custom Watch Model: Extend the Watch model (published via php artisan vendor:publish --tag=watchable-models):

    class CustomWatch extends \Jamesmills\Watchable\Models\Watch
    {
        protected $table = 'custom_watches';
    }
    

    Update the trait to use your model:

    use Jamesmills\Watchable\Concerns\UsesCustomWatchModel;
    
  2. Add Metadata to Watches: Attach extra data to watches via accessors/mutators:

    // In Watch model
    protected $casts = ['metadata' => 'array'];
    
    // When watching
    $post->watch(['notified_at' => now()]);
    
  3. Custom Watch Logic: Override the watch() method in your model:

    public function watch(array $options = [])
    {
        $this->fireModelEvent('watching', false);
        $result = parent::watch($options);
        $this->fireModelEvent('watched', false);
        return $result;
    }
    
  4. Soft Deletes: If your models use soft deletes, ensure the watches table also supports soft deletes:

    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Watch extends Model
    {
        use SoftDeletes;
        protected $dates = ['deleted_at'];
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity