├── .github └── workflows │ ├── update-changelog.yml │ └── tests.yml ├── src ├── Contracts │ └── HasReaction.php ├── Events │ ├── RemoveReactionEvent.php │ ├── RemoveAllReactionEvent.php │ └── StoreReactionEvent.php ├── Enums │ └── LaravelReactionTypeEnum.php ├── Providers │ └── LaravelReactionServiceProvider.php ├── Models │ └── Reaction.php └── Traits │ ├── Reactor.php │ └── Reactable.php ├── phpunit.xml ├── config └── laravel-reaction.php ├── LICENSE ├── database └── migrations │ └── 2024_09_21_112229_create_reactions_table.php ├── composer.json ├── CHANGELOG.md └── README.md /.github/workflows/update-changelog.yml: -------------------------------------------------------------------------------- 1 | name: update changelog 2 | 3 | on: 4 | release: 5 | types: [released] 6 | 7 | permissions: {} 8 | 9 | jobs: 10 | update: 11 | permissions: 12 | contents: write 13 | uses: laravel/.github/.github/workflows/update-changelog.yml@main 14 | -------------------------------------------------------------------------------- /src/Contracts/HasReaction.php: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests 10 | 11 | 12 | 13 | 14 | ./src 15 | ./config 16 | ./database 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /config/laravel-reaction.php: -------------------------------------------------------------------------------- 1 | 'reactions', 8 | 9 | 'user' => [ 10 | /* 11 | * User model. 12 | */ 13 | 'model' => 'App\Models\User', 14 | 15 | /* 16 | * Foreign Key column name. 17 | */ 18 | 'foreign_key' => 'user_id', 19 | 20 | /* 21 | * Users table name. 22 | */ 23 | 'table' => 'users', 24 | 25 | /* 26 | * The correct guard. 27 | */ 28 | 'guard' => 'web', 29 | 30 | /* 31 | * If you are using uuid or ulid you can change it for the type of foreign_key. 32 | * 33 | * When you are using ulid or uuid, you need to add related traits into the models. 34 | */ 35 | 'foreign_key_type' => 'id', // uuid, ulid, id 36 | ] 37 | ]; 38 | -------------------------------------------------------------------------------- /src/Providers/LaravelReactionServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadMigrationsFrom(__DIR__ . '/../../database/migrations'); 15 | $this->mergeConfigFrom(__DIR__ . '/../../config/laravel-reaction.php', 'laravel-reactions'); 16 | } 17 | 18 | public function boot(): void 19 | { 20 | $this->publishes([ 21 | __DIR__ . '/../../config/laravel-reaction.php' => config_path('laravel-reaction.php'), 22 | ], 'laravel-reactions-config'); 23 | 24 | $this->publishes([ 25 | __DIR__ . '/../../database/migrations/' => database_path('migrations') 26 | ], 'laravel-reactions-migrations'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2025 Milwad Khosravi (Binafy) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /src/Models/Reaction.php: -------------------------------------------------------------------------------- 1 | setTable(config('laravel-reactions.table', 'reactions')); 31 | } 32 | 33 | // Relations 34 | 35 | /** 36 | * Reactable morph relation. 37 | */ 38 | public function reactable(): \Illuminate\Database\Eloquent\Relations\MorphTo 39 | { 40 | return $this->morphTo(); 41 | } 42 | 43 | /** 44 | * Relation one-to-many, User model. 45 | */ 46 | public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo 47 | { 48 | return $this->belongsTo( 49 | config('laravel-reactions.user.model'), 50 | config('laravel-reactions.user.foreign_key'), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /database/migrations/2024_09_21_112229_create_reactions_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | 17 | $userForeignType = config('laravel-reactions.user.foreign_key_type', 'id'); 18 | $userForeignName = config('laravel-reactions.user.foreign_key'); 19 | $userForeignTableName = config('laravel-reactions.user.table'); 20 | 21 | if ($userForeignType === 'ulid') { 22 | $table->foreignUlid($userForeignName) 23 | ->nullable() 24 | ->constrained($userForeignTableName) 25 | ->nullOnDelete(); 26 | } else if ($userForeignType === 'uuid') { 27 | $table->foreignUuid($userForeignName) 28 | ->nullable() 29 | ->constrained($userForeignTableName) 30 | ->nullOnDelete(); 31 | } else { 32 | $table->foreignId($userForeignName) 33 | ->nullable() 34 | ->constrained($userForeignTableName) 35 | ->nullOnDelete(); 36 | } 37 | 38 | $table->morphs('reactable'); 39 | $table->string('type'); 40 | $table->string('ip')->nullable(); 41 | 42 | $table->unique([$userForeignName, 'reactable_type', 'reactable_id', 'ip'], 'reaction_user_name_per_ip'); 43 | 44 | $table->timestamps(); 45 | }); 46 | } 47 | 48 | /** 49 | * Reverse the migrations. 50 | */ 51 | public function down(): void 52 | { 53 | Schema::dropIfExists(config('laravel-reactions.table', 'reactions')); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: "Run Tests" 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | php: [8.1, 8.2, 8.3, 8.4] 12 | laravel: [10.*, 11.*, 12.*] 13 | dependency-version: [prefer-lowest, prefer-stable] 14 | include: 15 | - laravel: 12.* 16 | testbench: 10.* 17 | pest-plugin-laravel: 3.1.0 18 | 19 | - laravel: 11.* 20 | testbench: 9.* 21 | pest-plugin-laravel: 2.3.0 22 | 23 | - laravel: 10.* 24 | testbench: 8.* 25 | pest-plugin-laravel: 2.0.0 26 | 27 | exclude: 28 | - laravel: 12.* 29 | php: 8.1 30 | 31 | - laravel: 11.* 32 | php: 8.1 33 | 34 | - laravel: 10.* 35 | php: 8.4 36 | 37 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} 38 | 39 | steps: 40 | - name: Checkout code 41 | uses: actions/checkout@v4 42 | 43 | - name: Setup PHP 44 | uses: shivammathur/setup-php@v2 45 | with: 46 | php-version: ${{ matrix.php }} 47 | extensions: curl, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, iconv 48 | coverage: none 49 | 50 | - name: Install dependencies 51 | run: | 52 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "pestphp/pest-plugin-laravel:${{ matrix.pest-plugin-laravel }}" --no-interaction --no-update 53 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction 54 | - name: Execute tests 55 | run: vendor/bin/pest 56 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "binafy/laravel-reactions", 3 | "description": "Laravel Reactions is a simple and flexible package that allows you to add reaction functionality to any Eloquent model", 4 | "keywords": [ 5 | "laravel reactions", 6 | "laravel-reactions", 7 | "binafy/laravel-reactions", 8 | "binafy", 9 | "milwad", 10 | "milwad khosravi", 11 | "fun developer", 12 | "laravel reactions package", 13 | "laravel reactions github", 14 | "laravel", 15 | "laravel library", 16 | "reaction", 17 | "reactions", 18 | "like", 19 | "love", 20 | "clap", 21 | "eloquent", 22 | "laravel reaction eloquent" 23 | ], 24 | "type": "library", 25 | "license": "MIT", 26 | "homepage": "https://github.com/binafy/laravel-reactions", 27 | "minimum-stability": "dev", 28 | "autoload": { 29 | "psr-4": { 30 | "Binafy\\LaravelReaction\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Tests\\": "tests/" 36 | } 37 | }, 38 | "authors": [ 39 | { 40 | "name": "Milwad Khosravi", 41 | "email": "milwad.dev@gmail.com", 42 | "role": "author", 43 | "homepage": "https://github.com/milwad-dev" 44 | }, 45 | { 46 | "name": "Binafy", 47 | "role": "owner", 48 | "homepage": "https://github.com/binafy" 49 | } 50 | ], 51 | "require": { 52 | "php": "^8.1", 53 | "laravel/framework": "^10.0|^11.0|^12.0" 54 | }, 55 | "require-dev": { 56 | "pestphp/pest-plugin-laravel": "^1.4.0|^2.0.0|^3.1.0", 57 | "orchestra/testbench": "^8.0|^9.0|^10.0" 58 | }, 59 | "config": { 60 | "sort-packages": true, 61 | "allow-plugins": { 62 | "pestphp/pest-plugin": true 63 | } 64 | }, 65 | "scripts": { 66 | "test": "vendor/bin/pest", 67 | "test-coverage": "vendor/bin/pest --coverage-html ./coverage" 68 | }, 69 | "extra": { 70 | "laravel": { 71 | "providers": [ 72 | "Binafy\\LaravelReaction\\Providers\\LaravelReactionServiceProvider" 73 | ] 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Traits/Reactor.php: -------------------------------------------------------------------------------- 1 | value; 26 | } 27 | 28 | // Store reaction 29 | $reaction = $reactable->reactions()->firstOrCreate([ 30 | $userForeignName => $this->getKey(), 31 | 'type' => $type, 32 | 'reactable_id' => $reactable->getKey(), 33 | 'reactable_type' => $reactable::class, 34 | ]); 35 | 36 | // Dispatch event 37 | StoreReactionEvent::dispatch($reaction); 38 | 39 | return $reaction; 40 | } 41 | 42 | /** 43 | * Remove reactions if exists. 44 | */ 45 | public function removeReactions(HasReaction $reactable): bool 46 | { 47 | $userForeignName = config('laravel-relations.user.foreign_key', 'user_id'); 48 | 49 | $reactable->reactions() 50 | ->where([$userForeignName => $this->getKey()]) 51 | ->delete(); 52 | 53 | // Dispatch event 54 | RemoveAllReactionEvent::dispatch(); 55 | 56 | return true; 57 | } 58 | 59 | /** 60 | * Remove reaction if exists. 61 | */ 62 | public function removeReaction(string|LaravelReactionTypeEnum $type, HasReaction $reactable): bool 63 | { 64 | $userForeignName = config('laravel-relations.user.foreign_key', 'user_id'); 65 | 66 | if ($type instanceof LaravelReactionTypeEnum) { 67 | $type = $type->value; 68 | } 69 | 70 | $reactable = $reactable->reactions() 71 | ->where([$userForeignName => $this->getKey(), 'type' => $type]) 72 | ->first(); 73 | 74 | if (!$reactable) { 75 | return false; 76 | } 77 | 78 | $reactable->delete(); 79 | 80 | // Dispatch event 81 | RemoveReactionEvent::dispatch(); 82 | 83 | return true; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Traits/Reactable.php: -------------------------------------------------------------------------------- 1 | morphMany(Reaction::class, 'reactable'); 20 | } 21 | 22 | /** 23 | * React to reactable. 24 | */ 25 | public function reaction(string|LaravelReactionTypeEnum $type, User|null $user = null): Reaction 26 | { 27 | if (is_null($user)) { 28 | $user = auth()->user(); 29 | } 30 | 31 | return $user->reaction($type, $this); 32 | } 33 | 34 | /** 35 | * Remove reaction if exists. 36 | */ 37 | public function removeReaction(string|LaravelReactionTypeEnum $type, User|null $user = null): bool 38 | { 39 | if (is_null($user)) { 40 | $user = auth()->user(); 41 | } 42 | 43 | return $user->removeReaction($type, $this); 44 | } 45 | 46 | /** 47 | * Remove all reactions if exists. 48 | */ 49 | public function removeReactions(User|null $user = null): bool 50 | { 51 | if (is_null($user)) { 52 | $user = auth()->user(); 53 | } 54 | 55 | return $user->removeReactions($this); 56 | } 57 | 58 | /** 59 | * Check reactable is reacted by the user. 60 | */ 61 | public function isReacted(User|null $user = null): bool 62 | { 63 | if (is_null($user)) { 64 | $user = auth()->user(); 65 | } 66 | 67 | return $this->reactions()->whereBelongsTo($user)->exists(); 68 | } 69 | 70 | /** 71 | * Get react count by type. 72 | */ 73 | public function getReactCountByType(string|LaravelReactionTypeEnum $type): int 74 | { 75 | return $this->reactions()->where('type', $type)->count(); 76 | } 77 | 78 | /** 79 | * Get reactions with count. 80 | */ 81 | public function getReactionsWithCount(): \Illuminate\Support\Collection 82 | { 83 | return $this 84 | ->reactions() 85 | ->groupBy('type') 86 | ->selectRaw('type, count(id) as total') 87 | ->get() 88 | ->mapWithKeys(fn (Reaction $reaction) => [$reaction->type => $reaction->total]); 89 | } 90 | 91 | /** 92 | * Get all reactors. 93 | */ 94 | public function getReactors(): \Illuminate\Support\Collection 95 | { 96 | return $this 97 | ->reactions() 98 | ->get() 99 | ->map(fn (Reaction $reaction) => $reaction->user); 100 | } 101 | 102 | // Attributes 103 | 104 | /** 105 | * Get is_reacted attribute. 106 | */ 107 | public function getIsReactedAttribute(): bool 108 | { 109 | return $this->isReacted(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Milwad Khosravi (Binafy) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | ## v1.0.0 - 2025-07-17 12 | 13 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.9.0...v1.0.0 14 | 15 | ## v0.9.0 - 2025-07-17 16 | 17 | ### What's Changed 18 | 19 | * Add event by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/6 20 | 21 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.8.0...v0.9.0 22 | 23 | ## v0.8.0 - 2025-07-17 24 | 25 | ### What's Changed 26 | 27 | * Readme by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/5 28 | 29 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.7.0...v0.8.0 30 | 31 | ## v0.7.0 - 2025-07-16 32 | 33 | ### What's Changed 34 | 35 | * Laravel 12 by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/4 36 | 37 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.6.0...v0.7.0 38 | 39 | ## v0.6.0 - 2025-07-16 40 | 41 | ### What's Changed 42 | 43 | * Improve composer by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/3 44 | 45 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.5.0...v0.6.0 46 | 47 | ## v0.5.0 - 2025-07-16 48 | 49 | ### What's Changed 50 | 51 | * Add `getReactors` method by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/2 52 | 53 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.4.0...v0.5.0 54 | 55 | ## v0.4.0 - 2025-07-16 56 | 57 | ### What's Changed 58 | 59 | * Add `getReactionsWithCount` method to Reactable by [@milwad-dev](https://github.com/milwad-dev) in https://github.com/binafy/laravel-reactions/pull/1 60 | 61 | ### New Contributors 62 | 63 | * [@milwad-dev](https://github.com/milwad-dev) made their first contribution in https://github.com/binafy/laravel-reactions/pull/1 64 | 65 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.3.0...v0.4.0 66 | 67 | ## v0.3.0 - 2025-07-16 68 | 69 | **Full Changelog**: https://github.com/binafy/laravel-reactions/compare/v0.2.1...v0.3.0 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Reactions 2 | 3 | Binafy Laravel Reactions 4 | 5 | [![PHP Version Require](https://img.shields.io/packagist/dependency-v/binafy/laravel-reactions/php)](https://packagist.org/packages/binafy/laravel-reactions) 6 | [![Latest Stable Version](https://img.shields.io/packagist/v/binafy/laravel-reactions.svg?style=flat-square)](https://packagist.org/packages/binafy/laravel-reactions) 7 | [![Total Downloads](https://img.shields.io/packagist/dt/binafy/laravel-reactions.svg?style=flat-square)](https://packagist.org/packages/binafy/laravel-reactions) 8 | [![License](https://img.shields.io/packagist/l/binafy/laravel-reactions)](https://packagist.org/packages/binafy/laravel-reactions) 9 | [![Passed Tests](https://github.com/binafy/laravel-reactions/actions/workflows/tests.yml/badge.svg)](https://github.com/binafy/laravel-reactions/actions/workflows/tests.yml) 10 | [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/binafy/laravel-reactions) 11 | 12 | ## Introduction 13 | 14 | Laravel Reactions is a simple and flexible package that enables you to add reaction functionality (such as 👍, ❤️, 😂, etc.) to any Eloquent model in your Laravel application. Whether you're building a social network, blog, or forum, this package makes it easy for users to express themselves through customizable reactions. 15 | 16 | 🔧 Features: 17 | 18 | - Add reactions to any model (e.g., posts, comments, messages) 19 | - Multiple reaction types (like, love, laugh, etc.) 20 | - Easy API for adding/removing reactions 21 | - Track who reacted and how 22 | - Eloquent relationships for seamless integration 23 | - Built-in support for custom reaction types 24 | - Lightweight and easy to customize 25 | 26 | ## Installation 27 | 28 | - ```PHP >= 8.1``` 29 | - ```Laravel >= 10.0``` 30 | 31 | You can install the package with Composer: 32 | 33 | ```bash 34 | composer require binafy/laravel-reactions 35 | ``` 36 | 37 | ## Publish 38 | 39 | If you want to publish a config file, you can use this command: 40 | 41 | ```shell 42 | php artisan vendor:publish --tag="laravel-reactions-config" 43 | ``` 44 | 45 | If you want to publish the migrations, you can use this command: 46 | 47 | ```shell 48 | php artisan vendor:publish --tag="laravel-reactions-migrations" 49 | ``` 50 | 51 | For convenience, you can use this command to publish config, migration, and ... files: 52 | 53 | ```shell 54 | php artisan vendor:publish --provider="Binafy\LaravelReaction\Providers\LaravelReactionServiceProvider" 55 | ``` 56 | 57 | ## Usage 58 | 59 | ### Setting Up Your Models 60 | 61 | Before using reactions, your models need the appropriate traits. User models require the Reactor trait to create reactions, while content models require the Reactable trait to receive reactions. 62 | 63 | #### User Model Setup 64 | 65 | ```php 66 | use Binafy\LaravelReaction\Traits\Reactor; 67 | 68 | class User extends Authenticatable 69 | { 70 | use Reactor; 71 | } 72 | ``` 73 | 74 | #### Content Model Setup 75 | 76 | ```php 77 | use Binafy\LaravelReaction\Contracts\HasReaction; 78 | use Binafy\LaravelReaction\Traits\Reactable; 79 | 80 | class Post extends Model implements HasReaction 81 | { 82 | use Reactable; 83 | } 84 | ``` 85 | 86 | ### Creating Reactions 87 | 88 | There are multiple ways to create reactions depending on your application's needs. You can create reactions from the user perspective or from the reactable content perspective. 89 | 90 | #### From User Models 91 | 92 | Users can react to any reactable content using the `reaction()` method from the `Reactor` trait: 93 | 94 | ```php 95 | use Binafy\LaravelReaction\Enums\LaravelReactionTypeEnum; 96 | 97 | $user = User::find(1); 98 | $post = Post::find(1); 99 | 100 | // Using enum reaction types 101 | $user->reaction(LaravelReactionTypeEnum::REACTION_ANGRY, $post); 102 | 103 | // Using custom string reaction types 104 | $user->reaction('love', $post); 105 | ``` 106 | 107 | #### From Reactable Models 108 | 109 | Reactable content can also initiate reactions, which is useful when you want to handle reactions from the content's perspective: 110 | 111 | ```php 112 | $post = Post::find(1); 113 | $user = User::find(1); 114 | 115 | // Specify the user explicitly 116 | $post->reaction('like', $user); 117 | 118 | // Use the currently authenticated user 119 | $post->reaction('like'); // Uses auth()->user() 120 | ``` 121 | 122 | ### Checking Reactions 123 | 124 | You can check whether content has been reacted to by specific users using the `isReacted()` method: 125 | 126 | ```php 127 | $post = Post::find(1); 128 | $user = User::find(1); 129 | 130 | // Check if a specific user reacted 131 | if ($post->isReacted($user)) { 132 | echo "User has reacted to this post"; 133 | } 134 | 135 | // Check if the currently authenticated user reacted 136 | if ($post->isReacted()) { 137 | echo "You have reacted to this post"; 138 | } 139 | ``` 140 | 141 | ### Basic Reaction Queries 142 | 143 | The `Reactable` trait provides several methods for querying reaction data: 144 | 145 | #### Counting Reactions by Type 146 | 147 | ```php 148 | $post = Post::find(1); 149 | 150 | // Count specific reaction type 151 | $likeCount = $post->getReactCountByType('like'); 152 | $angryCount = $post->getReactCountByType(LaravelReactionTypeEnum::REACTION_ANGRY); 153 | ``` 154 | 155 | #### Getting All Reaction Counts 156 | 157 | ```php 158 | $post = Post::find(1); 159 | 160 | // Returns collection with type => count pairs 161 | $reactionCounts = $post->getReactionsWithCount(); 162 | // Example result: ['like' => 5, 'love' => 3, 'angry' => 1] 163 | ``` 164 | 165 | #### Getting Reactors 166 | 167 | ```php 168 | $post = Post::find(1); 169 | 170 | // Get all users who reacted to this post 171 | $reactors = $post->getReactors(); 172 | ``` 173 | 174 | ### Removing Reactions 175 | 176 | Reactions can be removed either by type or completely: 177 | 178 | #### Remove Specific Reaction Type 179 | 180 | ```php 181 | $user = User::find(1); 182 | $post = Post::find(1); 183 | 184 | // Remove specific reaction type 185 | $user->removeReaction('like', $post); 186 | 187 | // Or from the reactable side 188 | $post->removeReaction('like', $user); 189 | $post->removeReaction('like'); // For authenticated user 190 | ``` 191 | 192 | #### Remove All Reactions 193 | 194 | ```php 195 | $user = User::find(1); 196 | $post = Post::find(1); 197 | 198 | // Remove all reactions by the user on this post 199 | $user->removeReactions($post); 200 | 201 | // Or from the reactable side 202 | $post->removeReactions($user); 203 | $post->removeReactions(); // For authenticated user 204 | ``` 205 | 206 | ### Events 207 | 208 | | Event | Description | 209 | |--------------------------|---------------------------| 210 | | `StoreReactionEvent` | When store new reaction | 211 | | `RemoveReactionEvent` | When remove a reaction | 212 | | `RemoveAllReactionEvent` | When remove all reactions | 213 | 214 | ## Contributors 215 | 216 | Thanks to all the people who contributed. [Contributors](https://github.com/binafy/laravel-reactions/graphs/contributors). 217 | 218 | 219 | 220 | ## Security 221 | 222 | If you discover any security-related issues, please email `binafy23@gmail.com` instead of using the issue tracker. 223 | 224 | ## Changelog 225 | 226 | The changelog can be found in the `CHANGELOG.md` file of the GitHub repository. 227 | 228 | ## License 229 | 230 | The MIT License (MIT). Please see [License File](https://github.com/binafy/laravel-reactions/blob/1.x/LICENSE) for more information. 231 | 232 | ## Star History 233 | 234 | [![Star History Chart](https://api.star-history.com/svg?repos=binafy/laravel-reactions&type=Date)](https://star-history.com/#binafy/laravel-reactions&Date) 235 | 236 | ## Donate 237 | 238 | If this package is helpful for you, you can buy a coffee for me :) ❤️ 239 | 240 | - Iranian Gateway: https://daramet.com/milwad_khosravi 241 | - Paypal Gateway: SOON 242 | - MetaMask Address: `0xf208a562c5a93DEf8450b656c3dbc1d0a53BDE58` 243 | --------------------------------------------------------------------------------