Laravel Markable
This package allows you to easily add the markable feature to your application, as for example likes, bookmarks, favorites and so on.
Installation
You can install the package via composer:
composer require maize-tech/laravel-markable
You can publish and run the migrations with:
php artisan vendor:publish --tag="markable-migration-bookmark" # publishes bookmark migration
php artisan vendor:publish --tag="markable-migration-favorite" # publishes favorite migration
php artisan vendor:publish --tag="markable-migration-like" # publishes like migration
php artisan vendor:publish --tag="markable-migration-reaction" # publishes reaction migration
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="markable-config"
This is the content of the published config file:
return [
/*
|--------------------------------------------------------------------------
| User model
|--------------------------------------------------------------------------
|
| Here you may specify the fully qualified class name of the user model class.
|
*/
'user_model' => App\Models\User::class,
/*
|--------------------------------------------------------------------------
| Table prefix
|--------------------------------------------------------------------------
|
| Here you may specify the prefix for all mark tables.
| If set, all migrations should be named with the given prefix and
| the mark's class name.
|
*/
'table_prefix' => 'markable_',
/*
|--------------------------------------------------------------------------
| Allowed values
|--------------------------------------------------------------------------
|
| Here you may specify the list of allowed values for each mark type.
| If a specific mark should not accept any values, you can avoid adding it
| to the list.
| The array key name should match the mark's class name in lower case.
|
*/
'allowed_values' => [
'reaction' => [],
],
];
Usage
Basic
To use the package, add the Maize\Markable\Markable
trait to the model where you want to have marks.
Once done, you can define the list of possible marks for the given model implementing the $marks
array with the list of mark classes' namespace.
Here's an example model including the Markable
trait and implementing the Like
mark:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Maize\Markable\Markable;
use Maize\Markable\Models\Like;
class Course extends Model
{
use Markable;
protected $fillable = [
'title',
'description',
];
protected static $marks = [
Like::class,
];
}
You can now assign likes to the model:
use App\Models\Course;
use Maize\Markable\Models\Like;
$course = Course::firstOrFail();
$user = auth()->user();
Like::add($course, $user); // marks the course liked for the given user
Like::remove($course, $user); // unmarks the course liked for the given user
Like::toggle($course, $user); // toggles the course like for the given user
Like::has($course, $user); // returns whether the given user has marked as liked the course or not
Like::count($course); // returns the amount of like marks for the given course
Custom mark model
The package allows you to define custom marks.
First thing you need to do is create a migration which defines the new mark model. The package works with separate tables for each mark in order to increase the performances when executing related queries.
The migration table name should contain the prefix defined in table_prefix
attribute under config/markable.php
. Default prefix is set to markable_
.
Here's an example migration for bookmarks:
class CreateBookmarksTable extends Migration
{
public function up()
{
Schema::create('markable_bookmarks', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnUpdate()->cascadeOnDelete();
$table->morphs('markable');
$table->string('value')->nullable();
$table->json('metadata')->nullable();
$table->timestamps();
});
}
}
Once done, you can create a new class which extends the abstract Mark
class and implement the markableRelationName
method, which defines the name of the relation.
Here's an example model for bookmarks:
namespace App\Models;
use Maize\Markable\Mark;
class Bookmark extends Mark
{
public static function markableRelationName(): string
{
return 'bookmarkers';
}
}
That's all! You can now include the custom mark to all models you wish and use it as explained before.
Working with mark values
You might need a custom mark with a subset of allowed values.
In this case, you can just define your custom mark as explained before and add the list of allowed values in allowed_values
array under config/markable.php
.
The array key name should match the mark's class name in lower case.
Here's an example when working with reactions:
'allowed_values' => [
'reaction' => [
'person_raising_hand',
'heart',
'kissing_heart',
],
],
You can then use the custom mark with values:
use App\Models\Post;
use Maize\Markable\Models\Reaction;
$post = Post::firstOrFail();
$user = auth()->user();
Reaction::add($post, $user, 'kissing_heart'); // adds the 'kissing_heart' reaction to the post for the given user
Reaction::remove($post, $user, 'kissing_heart'); // removes the 'kissing_heart' reaction to the post for the given user
Reaction::toggle($post, $user, 'heart'); // toggles the 'heart' reaction to the post for the given user
Reaction::has($post, $user, 'heart'); // returns whether the user has reacted with the 'heart' reaction to the given post or not
Reaction::count($post, 'person_raising_hand'); // returns the amount of 'person_raising_hand' reactions for the given post
Retrieve mark relation with eloquent
use App\Models\Course;
use App\Models\Post;
Course::firstOrFail()->likers; // returns the collection of likes to the given course with their user
Post::firstOrFail()->reacters; // returns the collection of reactions to the given post with their user and value
Filter marked models with eloquent
use App\Models\Course;
use App\Models\Post;
Course::whereHasLike(
auth()->user()
)->get(); // returns all course models with a like from the given user
Post::whereHasReaction(
auth()->user(),
'heart'
)->get(); // returns all post models with a 'heart' reaction from the given user
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.