{"id":13910419,"url":"https://github.com/maize-tech/laravel-markable","last_synced_at":"2025-10-30T13:50:21.737Z","repository":{"id":37961397,"uuid":"478068135","full_name":"maize-tech/laravel-markable","owner":"maize-tech","description":"Integrate likes, bookmarks, favorites, reactions and custom made marks into your application","archived":false,"fork":false,"pushed_at":"2025-06-16T15:51:42.000Z","size":410,"stargazers_count":734,"open_issues_count":2,"forks_count":32,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-07-16T12:03:47.162Z","etag":null,"topics":["bookmarks","favorites","laravel","likes","markable","marks","reactions"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maize-tech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"maize-tech"}},"created_at":"2022-04-05T09:56:45.000Z","updated_at":"2025-07-05T05:49:42.000Z","dependencies_parsed_at":"2024-03-25T16:12:47.565Z","dependency_job_id":"30ab6a63-35fc-46e1-ad3a-e90dc75a8dd9","html_url":"https://github.com/maize-tech/laravel-markable","commit_stats":{"total_commits":35,"total_committers":3,"mean_commits":"11.666666666666666","dds":0.3142857142857143,"last_synced_commit":"b8c3340a58167917a73afc0fca3b54bc4588eb06"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/maize-tech/laravel-markable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maize-tech%2Flaravel-markable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maize-tech%2Flaravel-markable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maize-tech%2Flaravel-markable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maize-tech%2Flaravel-markable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maize-tech","download_url":"https://codeload.github.com/maize-tech/laravel-markable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maize-tech%2Flaravel-markable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265608029,"owners_count":23797234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bookmarks","favorites","laravel","likes","markable","marks","reactions"],"created_at":"2024-08-07T00:01:22.347Z","updated_at":"2025-10-30T13:50:16.709Z","avatar_url":"https://github.com/maize-tech.png","language":"PHP","funding_links":["https://github.com/sponsors/maize-tech"],"categories":["PHP"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"/art/socialcard-dark.png\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"/art/socialcard-light.png\"\u003e\n  \u003cimg src=\"/art/socialcard-light.png\" alt=\"Social Card of Laravel Markable\"\u003e\n\u003c/picture\u003e\n\u003c/p\u003e\n\n# Laravel Markable\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/maize-tech/laravel-markable.svg?style=flat-square)](https://packagist.org/packages/maize-tech/laravel-markable)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/maize-tech/laravel-markable/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/maize-tech/laravel-markable/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/maize-tech/laravel-markable/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/maize-tech/laravel-markable/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/maize-tech/laravel-markable.svg?style=flat-square)](https://packagist.org/packages/maize-tech/laravel-markable)\n\nThis package allows you to easily add the markable feature to your application, as for example likes, bookmarks, favorites and so on.\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require maize-tech/laravel-markable\n```\n\nYou can publish and run the migrations with:\n\n```bash\nphp artisan vendor:publish --tag=\"markable-migration-bookmark\" # publishes bookmark migration\nphp artisan vendor:publish --tag=\"markable-migration-favorite\" # publishes favorite migration\nphp artisan vendor:publish --tag=\"markable-migration-like\"  # publishes like migration\nphp artisan vendor:publish --tag=\"markable-migration-reaction\"  # publishes reaction migration\n\nphp artisan migrate\n```\n\nYou can publish the config file with:\n```bash\nphp artisan vendor:publish --tag=\"markable-config\"\n```\n\nThis is the content of the published config file:\n\n```php\n\u003c?php\n\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | User model\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the fully qualified class name of the user model class.\n    |\n    */\n\n    'user_model' =\u003e App\\Models\\User::class,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Table prefix\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the prefix for all mark tables.\n    | If set, all migrations should be named with the given prefix and\n    | the mark's class name.\n    |\n    */\n\n    'table_prefix' =\u003e 'markable_',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Allowed values\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the list of allowed values for each mark type.\n    | If a specific mark should not accept any values, you can avoid adding it\n    | to the list.\n    | The array key name should match the mark's class name in lower case.\n    |\n    */\n\n    'allowed_values' =\u003e [\n        'reaction' =\u003e [],\n    ],\n];\n```\n\n## Usage\n\n### Basic\n\nTo use the package, add the `Maize\\Markable\\Markable` trait to the model where you want to have marks.\n\nOnce done, you can define the list of possible marks for the given model implementing the `$marks` array with the list of mark classes' namespace.\n\nHere's an example model including the `Markable` trait and implementing the `Like` mark:\n\n``` php\n\u003c?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maize\\Markable\\Markable;\nuse Maize\\Markable\\Models\\Like;\n\nclass Course extends Model\n{\n    use Markable;\n\n    protected $fillable = [\n        'title',\n        'description',\n    ];\n\n    protected static $marks = [\n        Like::class,\n    ];\n}\n```\n\nYou can now assign likes to the model:\n\n``` php\nuse App\\Models\\Course;\nuse Maize\\Markable\\Models\\Like;\n\n$course = Course::firstOrFail();\n$user = auth()-\u003euser();\n\nLike::add($course, $user); // marks the course liked for the given user\n\nLike::remove($course, $user); // unmarks the course liked for the given user\n\nLike::toggle($course, $user); // toggles the course like for the given user\n\nLike::has($course, $user); // returns whether the given user has marked as liked the course or not\n\nLike::count($course); // returns the amount of like marks for the given course\n```\n\n### Custom metadata\n\nIf needed, you may also add custom metadata when assigning a mark:\n\n``` php\nuse App\\Models\\Course;\nuse Maize\\Markable\\Models\\Like;\n\n$course = Course::firstOrFail();\n$user = auth()-\u003euser();\n\nLike::add($course, $user, [\n    'topic' =\u003e $course-\u003etopic,\n]);\n\nLike::toggle($course, $user, [\n    'topic' =\u003e $course-\u003etopic,\n]);\n```\n\n### Custom mark model\n\nThe package allows you to define custom marks.\n\nFirst thing you need to do is create a migration which defines the new mark model.\nThe package works with separate tables for each mark in order to increase the performances when executing related queries.\n\nThe migration table name should contain the prefix defined in `table_prefix` attribute under `config/markable.php`.\nDefault prefix is set to `markable_`.\n\nHere's an example migration for bookmarks:\n\n``` php\nreturn new class extends Migration\n{\n    public function up()\n    {\n        Schema::create('markable_bookmarks', function (Blueprint $table) {\n            $table-\u003eid();\n            $table-\u003eforeignId('user_id')-\u003econstrained()-\u003ecascadeOnUpdate()-\u003ecascadeOnDelete();\n            $table-\u003emorphs('markable');\n            $table-\u003estring('value')-\u003enullable();\n            $table-\u003ejson('metadata')-\u003enullable();\n            $table-\u003etimestamps();\n        });\n    }\n}\n```\n\nOnce done, you can create a new class which extends the abstract `Mark` class and implement the `markableRelationName` method, which is used to retrieve the users who marked a given model entity with the mark entity as pivot.\n\nYou can also override the `markRelationName` method, which is used to retrieve the list of marks of a given model entity.\nBy default, the relation name is the plural name of the mark class name.\n\nHere's an example model for the bookmarks mark:\n\n``` php\n\u003c?php\n\nnamespace App\\Models;\n\nuse Maize\\Markable\\Mark;\n\nclass Bookmark extends Mark\n{\n    public static function markableRelationName(): string\n    {\n        return 'bookmarkers';\n    }\n    \n    /**\n     * The override is useless in this case, as I am returning the default\n     * relation name which is the plural name of the mark class name (bookmarks, indeed)\n     */\n    public static function markRelationName(): string\n    {\n        return 'bookmarks';\n    }\n}\n```\n\nThat's all!\nYou can now include the custom mark to all models you wish and use it as explained before.\n\n### Working with mark values\n\nYou might need a custom mark with a subset of allowed values.\n\nIn 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`.\n\nThe array key name should match the mark's class name in lower case.\n\nHere's an example when working with reactions:\n\n``` php\n'allowed_values' =\u003e [\n    'reaction' =\u003e [\n        'person_raising_hand',\n        'heart',\n        'kissing_heart',\n    ],\n],\n```\n\nYou can then use the custom mark with values:\n\n``` php\nuse App\\Models\\Post;\nuse Maize\\Markable\\Models\\Reaction;\n\n$post = Post::firstOrFail();\n$user = auth()-\u003euser();\n\nReaction::add($post, $user, 'kissing_heart'); // adds the 'kissing_heart' reaction to the post for the given user\n\nReaction::remove($post, $user, 'kissing_heart'); // removes the 'kissing_heart' reaction to the post for the given user\n\nReaction::toggle($post, $user, 'heart'); // toggles the 'heart' reaction to the post for the given user\n\nReaction::has($post, $user, 'heart'); // returns whether the user has reacted with the 'heart' reaction to the given post or not\n\nReaction::count($post, 'person_raising_hand'); // returns the amount of 'person_raising_hand' reactions for the given post\n```\n\nYou can also use wildcards to allow any value for a specific mark.\n\nHere's an example when working with reactions:\n\n``` php\n'allowed_values' =\u003e [\n    'reaction' =\u003e '*',\n],\n```\n\nWhen set, you can use any value when giving a reaction:\n\n``` php\nuse App\\Models\\Post;\nuse Maize\\Markable\\Models\\Reaction;\n\n$post = Post::firstOrFail();\n$user = auth()-\u003euser();\n\nReaction::add($post, $user, 'random_value'); // adds the 'random_value' reaction to the post for the given user\n```\n\n### Retrieve the list of marks of an entity with eloquent\n\n``` php\nuse App\\Models\\Course;\nuse App\\Models\\Post;\n\nCourse::firstOrFail()-\u003elikes; // returns the collection of like marks related to the course\nPost::firstOrFail()-\u003ereactions; // returns the collection of reaction marks related to the post \n```\n\n### Retrieve the list of users who marked an entity with eloquent\n\n``` php\nuse App\\Models\\Course;\nuse App\\Models\\Post;\n\nCourse::firstOrFail()-\u003elikers; // returns the collection of users who liked the course along with the mark value as pivot\nPost::firstOrFail()-\u003ereacters; // returns the collection of users who reacted to the post along with the mark value as pivot\n```\n\n### Filter marked models with eloquent\n\n``` php\nuse App\\Models\\Course;\nuse App\\Models\\Post;\n\nCourse::whereHasLike(\n    auth()-\u003euser()\n)-\u003eget(); // returns all course models with a like from the given user\n\nPost::whereHasReaction(\n    auth()-\u003euser(),\n    'heart'\n)-\u003eget(); // returns all post models with a 'heart' reaction from the given user\n```\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://github.com/maize-tech/.github/blob/main/CONTRIBUTING.md) for details.\n\n## Security Vulnerabilities\n\nPlease review [our security policy](https://github.com/maize-tech/.github/security/policy) on how to report security vulnerabilities.\n\n## Credits\n\n- [Enrico De Lazzari](https://github.com/enricodelazzari)\n- [Riccardo Dalla Via](https://github.com/riccardodallavia)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaize-tech%2Flaravel-markable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaize-tech%2Flaravel-markable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaize-tech%2Flaravel-markable/lists"}