cybercog / laravel-love

Add Social Reactions to Laravel Eloquent Models. It lets people express how they feel about the content. Fully customizable Weighted Reaction System & Reaction Type System with Like, Dislike and any other custom emotion types. Do you react?
https://komarev.com/sources/laravel-love
MIT License
1.17k stars 71 forks source link

Argument 1 passed to Cog\Laravel\Love\Reacter\Facades\Reacter::reactTo() must implement interface Cog\Contracts\Love\Reactable\Models\Reactable? #109

Closed Duohao closed 5 years ago

Duohao commented 5 years ago

document has no example , diffcult to get error reason

code:

class Comments extends Model implements ReactableContract
{
    use Reactable;
}
class User extends Authenticatable implements ReacterableContract
{
    use Notifiable, Reacterable;
}
    $user = \Hello\Models\User\User::find(3);
        if ($user->isNotRegisteredAsLoveReacter()) {
            $user->registerAsLoveReacter();
        }

        $reacter = $user->viaLoveReacter();
        $comment = \Hello\Models\Comments\Comments::find(2);

        if ($comment->isNotRegisteredAsLoveReactant()) {
            $comment->registerAsLoveReactant();
        }
        $reactant  = $comment->getLoveReactant();
        **$reacter->reactTo($reactant, ReactionType::fromName('Like'), null);**

error :

Argument 1 passed to Cog\Laravel\Love\Reacter\Facades\Reacter::reactTo() must implement interface Cog\Contracts\Love\Reactable\Models\Reactable, instance of Cog\Laravel\Love\Reactant\Models\Reactant given, called in 
antonkomarev commented 5 years ago

Hello, @Duohao!

There are 2 ways to use Love Reacter API:

  1. Method $user->getLoveReacter() returns Reacter model which requires to make calls to Internal API. Read about Reacter in documentation
$commentReactant = $comment->getReactant();
$reactionType = ReactionType::fromName('Like');

$user->getLoveReacter()->reactTo($commentReactant, $reactionType);
  1. Method $user->viaLoveReacter() returns a ReacterFacade with simplified API which looks very similar to first one. It have same methods names but awaits your application specific types, so you don't need to directly operate with internal Love models. Read about Reacter Facade in documentation

Because you've used viaLoveReacter then there is no need to getReactant(). Just pass $comment instance to reactTo method. And `ReactionType::fromName()' could be just a string.

$user->viaLoveReacter()->reactTo($comment, 'Like');

Your example could be rewritten this way:

$user = \Hello\Models\User\User::find(3);
if ($user->isNotRegisteredAsLoveReacter()) {
    $user->registerAsLoveReacter();
}

$comment = \Hello\Models\Comments\Comments::find(2);
if ($comment->isNotRegisteredAsLoveReactant()) {
    $comment->registerAsLoveReactant();
}

$user->viaLoveReacter()->reactTo($comment, 'Like');

I think that you don't need to register user & comments after the find. Registering better do in background to not affect client execution process.

If you are installing package in already deployed system, then you'd better create console command which will seed your database: example of command

At the end your controller code will be very clean & simple.

$user = \Hello\Models\User\User::find(3);
$comment = \Hello\Models\Comments\Comments::find(2);

$user->viaLoveReacter()->reactTo($comment, 'Like');
Duohao commented 5 years ago

Thanks for your patience, it's ok now :

        $user = \Hello\Models\User\User::find(4);
        $comment = \Hello\Models\Comments\Comments::find(2);
        if ($user->isNotRegisteredAsLoveReacter()) {
            $user->registerAsLoveReacter();
        }

        if ($comment->isNotRegisteredAsLoveReactant()) {
            $comment->registerAsLoveReactant();
        }

        if ($user->viaLoveReacter()->hasNotReactedTo($comment, 'Like')) {
            $user->viaLoveReacter()->reactTo($comment, 'Like');
        }