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

Laravel Reactions Laravel Package

qirolab/laravel-reactions

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require qirolab/laravel-reactions
    

    No manual service provider registration needed (Laravel 5.5+ auto-discovers).

  2. Publish Config (Optional):

    php artisan vendor:publish --provider="Qirolab\LaravelReactions\LaravelReactionsServiceProvider" --tag="config"
    

    Defaults are sensible, but customize via config/reactions.php if needed.

  3. First Use Case: Add reactions to a model (e.g., Post):

    use Qirolab\LaravelReactions\Traits\Reacts;
    
    class Post extends Model
    {
        use Reacts;
    }
    

    Run migrations:

    php artisan migrate
    
  4. Define Reactions: In config/reactions.php, set your reaction types (e.g., like, love, dislike):

    'reactions' => ['like', 'love', 'dislike'],
    
  5. Basic Usage:

    // Add a reaction
    $post->reaction()->create(['type' => 'like', 'user_id' => auth()->id()]);
    
    // Check if user reacted
    $post->isReactedBy(auth()->id(), 'like');
    
    // Get reaction count
    $post->reactionsCount('like');
    

Implementation Patterns

Core Workflows

  1. Model Integration:

    • Use the Reacts trait on Eloquent models to enable reactions.
    • Example for a Comment model:
      class Comment extends Model
      {
          use Reacts;
      }
      
  2. Reaction Types:

    • Define reaction types in config/reactions.php:
      'reactions' => ['upvote', 'downvote', 'bookmark', 'share'],
      
    • Dynamically add/remove types without migrations (uses a pivot table).
  3. Common CRUD Operations:

    // Create a reaction
    $model->reaction()->create(['type' => 'like', 'user_id' => 1]);
    
    // Delete a reaction
    $model->reaction()->where('user_id', 1)->delete();
    
    // Toggle reaction (e.g., like/dislike)
    $model->toggleReaction('like', auth()->id());
    
  4. Querying Reactions:

    • Get all reactions for a model:
      $post->reactions()->get();
      
    • Filter by type/user:
      $post->reactions()->where('type', 'like')->get();
      $post->reactions()->where('user_id', 1)->get();
      
  5. Real-Time Updates:

    • Use Laravel Echo/Pusher to broadcast reaction changes:
      $post->reaction()->create(['type' => 'like', 'user_id' => auth()->id()]);
      broadcast(new ReactionBroadcast($post, 'like', auth()->id()));
      
  6. API Endpoints:

    • Example route/controller:
      Route::post('/posts/{post}/react', [ReactionController::class, 'store']);
      
      public function store(Post $post, Request $request) {
          $post->toggleReaction($request->type, auth()->id());
          return response()->json(['success' => true]);
      }
      
  7. Frontend Integration:

    • Fetch reaction counts via API:
      fetch(`/posts/${postId}/reactions/count?type=like`)
        .then(res => res.json())
        .then(count => console.log(count));
      
    • Use Blade directives for UI:
      @reactionButton($post, 'like', auth()->id())
      

Gotchas and Tips

Pitfalls

  1. Migration Conflicts:

    • The package creates a reactions table and a pivot table (model_has_reactions). Ensure no naming collisions with existing tables.
    • Fix: Rename tables in the config or manually adjust migrations.
  2. Caching Issues:

    • Reaction counts may not update instantly if cached. Use reactionsCount('type', true) to force refresh.
    • Tip: Cache reaction counts with a short TTL (e.g., 5 minutes) for performance.
  3. User Authentication:

    • Always validate user_id in reactions to prevent abuse. Use middleware or policies:
      public function store(Request $request) {
          $this->authorize('react', $post);
          $post->toggleReaction($request->type, auth()->id());
      }
      
  4. Performance with Large Datasets:

    • Avoid withCount('reactions') on models with millions of reactions. Use raw SQL or aggregate queries:
      DB::table('reactions')->where('reactable_id', $post->id)->where('type', 'like')->count();
      
  5. Soft Deletes:

    • If your model uses SoftDeletes, reactions will also soft-delete. Override the trait to handle this:
      use Qirolab\LaravelReactions\Traits\Reacts as BaseReacts;
      
      class Post extends Model {
          use BaseReacts {
              BaseReacts::boot as private bootReactions;
          }
      
          protected static function bootReactions() {
              static::deleted(function ($model) {
                  $model->reactions()->delete();
              });
          }
      }
      

Debugging

  1. Reaction Not Saving:

    • Check if the reactable_type and reactable_id are correctly set (default: class and id of the model).
    • Debug: Temporarily add dd($model->getTable(), $model->getKey()) to verify.
  2. Count Mismatches:

    • Compare raw SQL counts with the package’s counts:
      $rawCount = DB::table('reactions')->where('reactable_id', $post->id)->where('type', 'like')->count();
      $packageCount = $post->reactionsCount('like');
      
  3. Duplicate Reactions:

    • Ensure user_id + type is unique in the pivot table. The package handles this by default, but custom logic may override it.

Extension Points

  1. Custom Reaction Logic:

    • Override the Reacts trait methods (e.g., toggleReaction):
      class Post extends Model {
          use Reacts;
      
          public function toggleReaction($type, $userId) {
              // Custom logic (e.g., rate limiting)
              if ($this->hasReactedToday($userId, $type)) {
                  return false;
              }
              return parent::toggleReaction($type, $userId);
          }
      }
      
  2. Additional Reaction Metadata:

    • Extend the pivot table by creating a custom migration:
      Schema::table('model_has_reactions', function (Blueprint $table) {
          $table->json('metadata')->nullable();
      });
      
    • Update the Reacts trait to use the new column.
  3. Reaction Events:

    • Listen for reaction events (e.g., ReactionCreated):
      use Qirolab\LaravelReactions\Events\ReactionCreated;
      
      ReactionCreated::listen(function ($reaction) {
          // Send notification, log, etc.
      });
      
  4. Custom Reaction Types:

    • Dynamically add reaction types at runtime:
      $this->addReactionType('custom_type');
      
    • Note: This requires clearing cached config if using Laravel’s caching.
  5. Multi-Tenant Support:

    • Add tenant_id to the pivot table for multi-tenancy:
      Schema::table('model_has_reactions', function (Blueprint $table) {
          $table->unsignedBigInteger('tenant_id')->after('id');
      });
      
    • Filter reactions by tenant in queries:
      $post->reactions()->where('tenant_id', auth()->tenant()->id)->get();
      

Pro Tips

  1. Bulk Reactions:

    • Use chunking for bulk operations to avoid memory issues:
      Post::chunk(100, function ($posts) {
          foreach ($posts as $post) {
              $post->toggleReaction('like', $userId);
          }
      });
      
  2. Reaction Analytics:

    • Create a view for reaction analytics:
      DB::view('reaction_analytics', function ($query) {
          $query->select('type', DB::raw('count(*) as count'))
                ->from('reactions')
                ->groupBy('type');
      });
      
  3. Localization:

    • Localize reaction labels in Blade:
      @reactionButton($post, 'like', auth()->id(), __('Like'))
      
  4. Testing:

    • Use factories to seed reactions:
      $post = Post::factory()->create();
      Reaction::factory()->create(['
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope