You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多态关联Voteable:评论与帖子投票功能开发求助

Hey there! Let's work through your voting system issues step by step—first, answering your core questions, then fixing that table not found error you're seeing.

Do you need to associate the Vote model with User?

Absolutely. Linking Vote to User is critical for two big reasons:

  • Prevent duplicate votes: You don't want the same user liking/disliking the same post or comment multiple times.
  • Track user activity: It lets you fetch a user's voting history, or check if they've already voted on a specific piece of content before saving a new vote.

How to set up the associations and save voting records

First, let's get your model relationships right:

  1. User Model: Add a relationship to all votes the user has cast
// app/Models/User.php
public function votes()
{
    return $this->hasMany(Vote::class);
}
  1. Vote Model: Define the polymorphic relationship to Post/Comment, plus the link to User
// app/Models/Vote.php
use Illuminate\Database\Eloquent\Model;

class Vote extends Model
{
    protected $fillable = ['user_id', 'value']; // Allow mass assignment for these fields

    public function voteable()
    {
        return $this->morphTo();
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
  1. Post & Comment Models: Add the polymorphic relationship to votes
// app/Models/Post.php
public function votes()
{
    return $this->morphMany(Vote::class, 'voteable');
}

// app/Models/Comment.php
public function votes()
{
    return $this->morphMany(Vote::class, 'voteable');
}

Fixing the "votes table doesn't exist" error

That SQL error is happening because you haven't created the votes database table yet. Let's generate and run the migration:

  1. Create the migration file:
php artisan make:migration create_votes_table
  1. Open the generated migration file (in database/migrations/) and update it with these fields:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up()
    {
        Schema::create('votes', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->onDelete('cascade'); // Delete votes if user is deleted
            $table->morphs('voteable'); // Auto-creates voteable_id and voteable_type columns
            $table->integer('value'); // Use 1 for upvote, -1 for downvote
            $table->timestamps();

            // Add unique constraint to block duplicate votes from the same user
            $table->unique(['user_id', 'voteable_id', 'voteable_type']);
        });
    }

    public function down()
    {
        Schema::dropIfExists('votes');
    }
};
  1. Run the migration to create the table:
php artisan migrate

Saving a user's vote (example controller logic)

Here's how you might handle voting in a controller, including checking for existing votes:

// app/Http/Controllers/VoteController.php
use Illuminate\Http\Request;
use App\Models\Vote;

class VoteController extends Controller
{
    public function store(Request $request)
    {
        // Validate incoming data
        $validated = $request->validate([
            'voteable_type' => 'required|string|in:App\Models\Post,App\Models\Comment',
            'voteable_id' => 'required|integer',
            'value' => 'required|integer|in:1,-1'
        ]);

        // Fetch the post/comment being voted on
        $voteable = $validated['voteable_type']::findOrFail($validated['voteable_id']);

        // Check if the user already voted on this content
        $existingVote = $voteable->votes()->where('user_id', auth()->id())->first();

        if ($existingVote) {
            // User already voted—either update their vote or return an error
            if ($existingVote->value === $validated['value']) {
                return back()->with('error', "You've already cast this vote!");
            } else {
                $existingVote->update(['value' => $validated['value']]);
                return back()->with('success', 'Your vote has been updated.');
            }
        } else {
            // Create a new vote record
            $voteable->votes()->create([
                'user_id' => auth()->id(),
                'value' => $validated['value']
            ]);
            return back()->with('success', 'Your vote has been saved!');
        }
    }
}

Don't forget to add a route for this:

// routes/web.php
Route::post('/votes', [VoteController::class, 'store'])->name('votes.store')->middleware('auth');

That should cover all your bases—you'll have proper user-vote association, working polymorphic votes for posts/comments, and the table error will be gone once you run the migration.

内容的提问来源于stack exchange,提问作者slickness

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:01:57