rubik-llc/laravel-comments

Attach comments to Eloquent Models

v0.1.0 2022-03-17 12:25 UTC

README

Platform Latest Version on Packagist GitHub Workflow Status Check & fix styling GitHub

This package enables to easily associate comments to any Eloquent model in your Laravel application.

//Associate a comment to a model as a logged in user
$post->comment('My comment!');

//Associate a comment to a model as a specific user
$post->commentAs($user, "Another user's comment!");
//Associate a comment to a model directly from the user
$user->commentTo($post, 'Comment from user!');

Installation

You can install the package via composer:

composer require rubik-llc/laravel-comments

Publish and run the migrations with:

php artisan vendor:publish --tag="comments-migrations"
php artisan migrate

Alternatively, you can publish the config file with:

php artisan vendor:publish --tag="comments-config"

This is the contents of the published config file:

return [
    /*
    |--------------------------------------------------------------------------
    | Comment class
    |--------------------------------------------------------------------------
    |
    | The comment class that should be used to store and retrieve the comments.
    | If you specify a different model class, make sure that model extends the default
    | Comment model that is shipped with this package.
    |
    */

    'comment_model' => \Rubik\LaravelComments\Models\Comment::class,

    /*
    |--------------------------------------------------------------------------
    | Needs approval
    |--------------------------------------------------------------------------
    |
    | By default, when creating comments they don't need approval (unless specified otherwise).
    | You can change the default value here.
    |
    */

    'needs_approval' => false,

    /*
    |--------------------------------------------------------------------------
    | Cascade on delete
    |--------------------------------------------------------------------------
    |
    | When this option is enabled, all related comments will be deleted when
    | the commentable class is deleted.
    |
    | If you want to overwrite this config for a specific class, you need to add
    | "$cascadeCommentsOnDelete" property to the commentable class.
    |
    | E.g:
    |
    |   class Commentable extends Model
    |   {
    |       use HasComments;
    |
    |       public static bool $cascadeCommentsOnDelete = false;
    |       ...
    |
    */

    'cascade_on_delete' => true,

    /*
    |--------------------------------------------------------------------------
    | Commenter name attribute
    |--------------------------------------------------------------------------
    |
    | The default attribute that returns the name of the commenter. Every class
    | that uses the "CanComment" trait will have the "commenter_name" attribute
    | appended, which will return the value of the attribute specified here.
    |
    | If you want to overwrite this config for a specific class, you need to add
    | "$nameAttribute" property to the commenter class.
    |
    | E.g:
    |
    |   class Commenter extends Model
    |   {
    |       use CanComment;
    |
    |       public string $nameAttribute = 'username';
    |       ...
    |
    */

    'commenter_name_attribute' => 'name',

    /*
    |--------------------------------------------------------------------------
    | Silence name attribute exception
    |--------------------------------------------------------------------------
    |
    | By default, if the class that uses the "CanComment" trait doesn't have the
    | name attribute specified in the "commenter_name_attribute" option or in
    | the "$nameAttribute" property, an exception will be thrown. If you enable
    | this option, no exception will be thrown and the "commenter_name" attribute
    | will return "null" if it can't find the specified name attribute.
    |
    */

    'silence_name_attribute_exception' => false,

];

Usage

Registering the Commentable Model

In order to let your models have comments associated to them, simply add the HasComments trait to the class of that model.

namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Rubik\LaravelComments\Traits\HasComments;

class Post extends Model
{
    use HasComments;
    
    ...
}

In addition to the configuration, you can specify whether the comments associated to a commentable class should be deleted when the commentable model is deleted by adding the $cascadeCommentsOnDelete property to the class.

class Post extends Model
{
    use HasComments;
    
    public static bool $cascadeCommentsOnDelete = true;
    
    ...
}

Registering the Commenter Model

In order to let a model be able to attach comments, add the CanComment trait to the class of that model.

namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Rubik\LaravelComments\Traits\CanComment;

class User extends Model
{
    use CanComment;
    
    ...
}

The CanComment trait appends a commenter_name attribute which returns the value of the attribute specified in the config file. In addition to that you can specify the name attribute, the value of which the commenter_name will have by adding the $nameAttribute property in the commenter class.

class User extends Model
{
    use CanComment;
    
    public string $nameAttribute = 'username';
    
    ...
}

In this case $user->commenter_name will return the same value as $user->username.

Creating comments

  1. To create a comment for the currently logged in user you can use the following syntax.
$post->comment('First comment!');

Additionally, you can specify whether a comment needs to be approved by adding a bool value as a second parameter.

$post->comment('Comment with default configuration!'); // this comment's approval is required based on configuration   

$post->comment('Comment with approval!', true); // this comment needs to be approved

$post->comment('Comment with no approval!', false); // this comment doesn't need to be approved
  1. You can create comments as other users.
$user = User::find(1);

$post->commentAs($user, 'First comment!');

$post->commentAs($user, 'Second comment!', true); // this comment needs to be approved
  1. Eventually, comments can bre created directly from the user model.
$post = Post::find(1);

$user->commentTo($post, 'First comment!');

$user->commentTo($post, 'Second comment!', true); // this comment needs to be approved

Retrieving comments

  1. Retrieving comments from the commentable model.
$post = Post::find(1);

// Retrieve all comments
$post->comments;

// Retrieve only approved comments and those that don't need approval
$post->approvedComments;
  1. Retrieving comments from the commenter model.
$user = User::find(1);

// Retrieve all comments
$user->comments;

// Retrieve only approved comments and those that don't need approval
$user->approvedComments;

Retrieving the commentable

$comment = Comment::find(1);

// Retrieve the commentable model instance
$comment->commentable;

Retrieving the commenter

$comment = Comment::find(1);

// Retrieve the commenter model instance
$comment->commenter;

Checking if comments are approved

To quickly check if a comment is approved use the is_approved attribute, it will return true if a comment is approved or doesn't need approval, otherwise it will return false.

$comment->is_approved // true/false

Approving comments

$comment = Comment::find(1);

$comment->approve(); 

$comment->approved_at // will return the date when the comment was approved

The approve() method accepts a string or a Carbon instance as a parameter to specify the approved_at date.

$comment->approve('2022-01-01');

$comment->approved_at // will return '2022-01-01'
$comment->approve(Carbon::parse('2022-02-02'));

$comment->approved_at // will return '2022-02-02'

By default, if you approve an already approved comment the approved_at value won't change.

$comment->approved_at // '2020-01-18'

$comment->approve('2022-01-01');

$comment->approved_at // will return '2020-01-18'

You can overwrite the approved_at by adding a boolean value as a second parameter.

$comment->approved_at // '2020-01-18'

$comment->approve('2022-01-01', true);

$comment->approved_at // will return '2022-01-01'

Disapproving comments

$comment = Comment::find(1); 

$comment->approved_at // '2022-01-01'

$comment->dissapprove();

$comment->approved_at // will return null

Replying to comments

Since the Comment class uses the HasComments trait, it is possible to attach comments to other comments.

$comment = Comment::find(1); 

$comment->comment('This is a reply for the first comment!')

$comment->comments // will return all replies for this comment

Recursively retrieving comments

You can retrieve all comments with their children and commenter from the commentable using the commentsWithCommentsAndCommenter() relation.

$post = Post::find(1); 

$post->commentsWithCommentsAndCommenter

Cascade on delete

Deleting a commentable will also delete all comments that are attached to it.

Using a custom Comment class

If you are using a custom comment class make sure it extends the default Comment class that is shipped with this package.

namespace App\Models;
use Rubik\LaravelComments\Models\Comment;

class CustomComment extends Comment
{   
    ...
}

In addition to that, you need to set the comment_model value in the config file to the path of your custom class.

// config/comments.php

return [
     ...
    
    'comment_model' => App\Models\CustomComment::class,  
     
     ...
]
$post->comment('My custom comment!');

$post->comments->first(); // will return an instance of CustomComment

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.