Laravel:我应该如何更新这种关系?

时间:2014-04-08 11:14:49

标签: php database laravel eloquent

假设我有以下表格:

User:
-userID
-userName
...

Exercises:
-exerciseID
...

User型号:

<?php

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;

class User extends Eloquent implements UserInterface, RemindableInterface {

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';
    protected $primaryKey = 'userID';

...

    public function hasPassedExercises() {
        return $this->hasMany('Exercise', 'exerciseID');
    }

}

我想说User有很多completedExercises,所以当用户完成练习时,我会像这样更新模型:

    Route::post('dbm/userPassedExercise', function () {
        $user = User::with('hasPassedExercises')->find($_POST['userID']);

        $exercise = Exercise::find($_POST['exerciseID']);
        $user->hasPassedExercises->save($exercise);
    });

但是,据我所知,这对任何基础表都没有影响。我正在尝试理解文档,看看它如何适用于我的问题。所以我的问题是在这里做什么是正确的行动方案。

我是否应该创建一个以users_completed_exercisesuserID作为外键的表exerciseID,如果是,那么在进行更新时如何将它们链接到我的用户?还是有更优雅的解决方案?

1 个答案:

答案 0 :(得分:1)

实际上,您必须使用关系表(称为数据透视表)。

在laravel文档中,您必须使用您的名称命名您的数据透视表名称(您没有,但它是首选)。 我们将采用您的命名约定:users_completed_exercises

所以在这里我们应该有这个:

users:
   - userId // Unsigned Int PRIMARY KEY AUTO_INCREMENT

Exercises:
   - exerciseId // Unsigned Int PRIMARY KEY AUTO_INCREMENT

users_completed_exercises:
   - id // Unsigned Int PRIMARY KEY AUTO_INCREMENT
   - exerciseId // Unsigned Int FOREIGN KEY REFERECES EXERCICES ON ID
   - userId // Unsigned Int FOREIGN KEY REFERECES USERS ON ID

在用户模型上,您应该:

public function passedExercises()
{
   // Alphabetical order of your id's are here, very important because laravel
   // retreives the good ID with your table name.
   return $this->belongsToMany('Exercise', 'users_completed_exercises', 'exerciseId', 'userId');
}

和练习模型相反

public function usersWhoPassed()
{
   // Alphabetical order of your id's are here, very important because laravel
   // retreives the good ID with your table name.
   return $this->belongsToMany('User', 'users_completed_exercises', 'exerciseId', 'userId');
}

现在退回信息很容易。

Route::post('dbm/userPassedExercise', function () {
    // Don't use $_POST with laravel, they are exceptions indeed, but avoid as much as
    // possible.
    $user = User::find(Input::get('userId'));

    $exercise = Exercise::find(Input::get('exerciseId'));
    // Very important, use () on relationships only if you want to continue the query
    // Without () you will get an Exercises Collection. Use ->get() or ->first() to end
    // the query and get the result(s)
    $exercise->usersWhoPassed()->save($user);
});

您可以轻松检查用户是否也通过了练习

Route::get('/exercises/{id}/passed_users', function($id)
{
    $exercise = Exercise::find($id);

    if ($exercise->usersWhoPassed()
        ->where('userId', '=', Input::get('userId'))->count()) {
       return 'User has passed';
    }
    return 'User has failed';
});