Closed wimil closed 4 years ago
Could you provide a use-case for this feature, please?
Reacter's unreactTo
method just trying to find reaction from the Reacter
related to Reactant
model and then deletes it. So you can do it manually in a pretty trivial way:
$reactions = $user->viaLoveReacter()->getReactions();
foreach ($reactions as $reaction) {
$reaction->delete();
}
If you will delete reactions directly from the database using plain SQL query - then Laravel Eloquent model events wouldn't be fired and reaction counters will be un-synced.
I am using Facebook reactions, a user can react with a "pisses me off", but he can change his reaction to a "like". How could I do that? If the only way is to eliminate the reaction, and save the new reaction, now the unreactTo method only eliminates by type of reaction, then I would have to bring the reaction to get the type, and then eliminate. what occurred to me was to eliminate all the reactions and then add the new reaction, so I created a method called unreactAll, but it does not update the total and count of the reactions
public function unreactAll(ReactantContract $reactant): void
{
if ($reactant->isNull()) {
throw ReactantInvalid::notExists();
}
$this->reactions()
->where('reactant_id', $reactant->getId())->delete();
}
Ah, now I see your requirement.
That happens because you are calling delete method of the Query Builder instead of the Eloquent Model. Fetch all reactions first and then delete each.
$reactions = $this->reactions()->where('reactant_id', $reactant->getId())->get();
foreach ($reactions as $reaction) {
$reaction->delete();
}
Or use some Laravel magic if you like:
$reactions = $this->reactions()->where('reactant_id', $reactant->getId())->get();
$reactions->each->delete();
Sadly, there is no way to listen Query Builder requests by event listeners so we cannot execute recounting.
Thanks for the help, I created a method called "unreactFirst" that brings the first result and eliminates it, so use the eloquent and activate the events
public function unreactFirst(ReactantContract $reactant): void
{
if ($reactant->isNull()) {
throw ReactantInvalid::notExists();
}
$this
->reactions()
->where('reactant_id', $reactant->getId())
->first()
->delete();
}
With this I have solved the problem and now the user can react and change his reaction.
If user is allowed to create only one reaction, that should work.
If your method located in application's User
model, I'd recommend you to rely on Cog\Contracts\Love\Reactable\Models\Reactable
contract instead of Cog\Contracts\Love\Reactant\Models\Reactant
. Then your application logic will be less coupled with Love package implementation.
use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableContract;
public function unreactFirst(ReactableContract $reactable): void
{
$reactant = $reactable->getLoveReactant();
if ($reactant->isNull()) {
throw ReactantInvalid::notExists();
}
$this
->getLoveReacter()
->reactions()
->where('reactant_id', $reactant->getId())
->first()
->delete();
}
Instead of:
$user->unreactFirst($comment->getLoveReactant());
You will write:
$user->unreactFirst($comment);
You can see how better your code looks like by using Reacter Facade & Reactant Facade.
thank you very much for the advice and help
There is some method to erase all the reactions that a reacter has reacted to.
example something like unreactTo but all would be unreactAll