A. Bechir
A. Bechir

Reputation: 120

Laravel How to store a variable into database and update it on every click

I have laravel blog, i have implement Add to favorite option using Vue.js and it's works very well. Now i want to implement like post (every user can like post more times), it's just like medium claps, i already have the clap button and it works, on every click the $likeCounter variable get updated and on hold also, the problem is how can i insert that variable ($likeCounter) into database (using javascript, vuejs ...)? The likes table has this columns user_id, post_id, likes_count user_id & post_id (pivot) inserted using vue.js

in my controller i have this method to attach user_id and post_id

public function like(Post $post)
{
    Auth::user()->likes()->attach($post->id);

    return back();
}

in User model i have this method to get all liked posts for the authenticated user

/**
 * Get all of liked posts for the user.
 */
public function likes()
{
    return $this->belongsToMany(Post::class, 'likes', 'user_id', 'post_id')->withTimeStamps();
}

in Post Model i have this method

/**
 * Determine whether a post has been liked by a user.
 *
 * @return boolean
 */
public function liked()
{
    return (bool) Like::where('user_id', Auth::id())
                        ->where('post_id', $this->id)
                        ->first();
}

public function likes()
{
    return $this->hasMany('App\Models\Like');
}

in Like.vue

methods: {
        like(post) {
            axios.post('/like/'+post)
                .then(response => this.isLiked = true)
                .catch(response => console.log(response.data));
        },

I use some javascript to update a variable on every click until the current user rich the max which is 50 claps for every authenticated user

function updateNumberOfClaps() {
    numberOfClaps < 50 ? numberOfClaps++ : null
    clapCount.innerHTML = "+" + numberOfClaps
    clapTotalCount.innerHTML = initialNumberOfClaps + numberOfClaps
  }

and it works well (attached the new like with user_id and post_id), if the same user click again on the same post a new like will be attached in database with same user_id and the same post_id. the issue is how can i store a variable counter in likes_count column and update it on every click, so instead of attached same post with same user again and again, i want to store a variable of how many the user like this post. I hope this is clear

Upvotes: 2

Views: 994

Answers (2)

Tpojka
Tpojka

Reputation: 7111

Set default value for likes_count to 50. Then, in your update method:

public function update(Request $request, $id)
{
    try {
        $userId = Auth::id();

        $like = Like::firstOrCreate([
            'user_id' => $userId,
            'post_id' => $id
        ]);

        if ((int)$like->likes_count < 1) {
            // user can not like this post anymore
            return response()->json(['message' => 'Like limit exceeded.']);
        }

        $like->decrement('likes_count');

        return response()->json(['message' => 'Post liked.']);

    } catch (\Exception $e) {
        Log::info('Something went wrong liking post ' . $id . ' by ' . $userId . ': ' . $e->getMessage());
        return response()->json(['message' => 'Error.']);
    }


}

Don't forget to include classes (Request, Auth, App\Like, Log...).

Upvotes: 1

Dom DaFonte
Dom DaFonte

Reputation: 1779

Here is an implementation of Reactions to items I've done before. I'll offer you the model and stripped out logic in my Controller to save a reaction to help you figure it out.

This should give you a decent understanding of the table structure and the controller logic to handle it.

If you want more details on how the logic works, the please ask. Hope this helps.

Models - Reaction and ReactionType.

The Reaction table stores all reactions to things, it's a pivot table that stores

  • user_id - The user who reacted/liked something
  • The related table - The table where the object that user liked is from
  • related table id - The references of what the user liked.... this is where I would find the person whose item was liked
  • reaction_type_id - This is the reference to the type of reaction (see reaction type)

ReactionType - This stores the types of reactions people can have in your app:

  • Reaction Name - The label used to tag the reaction (Like, dislike, hate, love, etc)
  • description - Description of what the reaction means.
  • Icon - What to present from an icon/image perspective in the view.

    class Reaction extends Model
    {
        protected $fillable = array('user_id', 'related_table', 'related_table_id', 'reaction_type_id');
        protected $table = 'reactions';
    }
    
    class ReactionType extends Model
    {
        protected $fillable = array('name', 'description', 'icon');
        protected $table = 'reaction_types';
    }
    

Controller - This is what stores the reaction I have notes in the controller explaining it.

class ReactionController extends Controller
{

    public function store(Requests\ReactionRequest $request)
    {
        $reaction = array(
            'user_id' => $request->id, 
            'reaction_type_id' => $request->reaction_type_id, 
            'related_table' => $request->related_table, 
            'related_table_id' => $request->related_table_id );
        //Check to see if there's a record already.  You can only have one reaction per item. 
        $CheckInDB = Reaction::where('user_id', '=', $reaction['user_id'])
    ->where('related_table', '=', $reaction['related_table'])
    ->where('related_table_id', '=', $reaction['related_table_id'])->first();
    //If the reaction is in the database then update the type (did they change reaction? 
    if ($CheckInDB) {
        //If they sent the same exact reaction type that is already in the database, then 0 it out... This would indicate they unselected the reaction they provided.
        if($CheckInDB->reaction_type_id == $reaction['reaction_type_id'])   {
            $CheckInDB->reaction_type_id = 0;   
        }
        //Otherwise, update the reaction_type_id with the new reaction.
        else {
            $CheckInDB->reaction_type_id = $reaction['reaction_type_id'];   
        }
        //Update the reaction.
        $CheckInDB->save();
    }
    //If the user has never reacted to the item, then create a new record with that reaction.
    else {
        Reaction::create($reaction);
    }
    return back();
}

}

Upvotes: 0

Related Questions