【问题标题】:Laravel: How should I update this relationship?Laravel:我应该如何更新这种关系?
【发布时间】:2014-04-08 11:14:48
【问题描述】:

假设我有以下表格:

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_exercises,其中有userIDexerciseID 作为外键,如果是这样,当我进行更新时如何将它们链接到我的用户?还是有更优雅的解决方案?

【问题讨论】:

    标签: php database laravel eloquent


    【解决方案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';
    });
    

    【讨论】:

    • 感谢您的详尽回答。但是,我在保存行上收到错误 Class 'users_completed_exercises' not found。我需要为数据透视表制作模型吗?
    • 您不必为数据透视表制作模型。 Laravel 为你做到了。我没有对实体进行通常的检查。你有没有检查 $exercise 在你的 Exercise::find() 之后是否真的存在? -原谅我的英语,而不是我的母语-
    • 确实如此,我检查了var_dump
    • 你能超过 var_dump 的结果吗? (小技巧,用dd(框架方法)代替var_dump)
    • 使用 attach() 而不是 save() 将在这两种方式下工作。在我的开发环境中测试。 Attach 不会尝试保存实体,而 save 会。
    猜你喜欢
    • 2014-05-08
    • 2018-04-14
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 2017-03-05
    • 2018-04-17
    相关资源
    最近更新 更多