79243389

Date: 2024-12-02 08:39:09
Score: 1.5
Natty:
Report link

First you can improve your migration by replacing unsignedBigInteger with foreignId like so:

Schema::create('post_user', function (Blueprint $table) {
    $table->id();
    $table->enum('vote', ['up', 'down'])->default('up');
    $table->foreignId('post_id')->constrained()->cascadeOnDelete(); // or onDelete('set null')
    $table->foreignId('user_id')constrained()->cascadeOnDelete(); // or onDelete('set null')
    $table->timestamps();

    // make sure a user can only vote once for each post
    $table->unique(['user_id', 'post_id']);
});

If you need to access the count of up and down votes frequently, it may help to add another index for post_id and vote.

$table->index(['post_id', 'vote']);

in User model:

public function votedPosts()
{
    return $this->belongsToMany(Post::class, 'votes')
                ->withPivot('vote')
                ->withTimestamps();
}

in Post model:

public function voters()
{
    return $this->belongsToMany(User::class, 'votes')
                ->withPivot('vote')
                ->withTimestamps();
}

Create a fluent model for updating user's vote on a post (add to Post model):

use Illuminate\Database\Eloquent\Relations\Pivot;

class Post extends Model
{
    // Define voters relationship as above...

    public function vote(User $user)
    {
        return new class($this, $user) {
            private $post;
            private $user;

            public function __construct(Post $post, User $user)
            {
                $this->post = $post;
                $this->user = $user;
            }

            public function up()
            {
                $this->post->voters()->syncWithoutDetaching([
                    $this->user->id => ['vote' => 'up']
                ]);
            }

            public function down()
            {
                $this->post->voters()->syncWithoutDetaching([
                    $this->user->id => ['vote' => 'down']
                ]);
            }
        };
    }
}

I used syncWithoutDetaching to prevent deleting any existing vote, we just want to update the vote.

then update user's vote in a single line like so:

// User casts an "up" vote
$post->vote(Auth::user())->up();

// User changes the vote to "down"
$post->vote(Auth::user())->down();
Reasons:
  • RegEx Blacklisted phrase (2): down vote
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Kaveh Movahedi