多态关联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:
- User Model: Add a relationship to all votes the user has cast
// app/Models/User.php public function votes() { return $this->hasMany(Vote::class); }
- 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); } }
- 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:
- Create the migration file:
php artisan make:migration create_votes_table
- 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'); } };
- 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

