我很难在Laravel 5中创建三个表/模型之间的三对多关系。到目前为止,从网上查找并没有给我任何可行的解决方案。
我有三种模式:用户,角色,论文。
我想要实现的是将三者相互连接起来。例如,用户可以与许多这些相关联,而用户可以在一个特定<上具有许多不同的角色强>论文即可。
因此用户可以在一个特定的论文上拥有多个角色(例如讲师和评论者),同样用户也可以关联另一个论文并且还有另一个角色(仅限教师)。
到目前为止,我已经尝试了一种方法,这意味着创建另一个可以处理数据透视表的模型。所以我创建了一个模型关系。
我目前的表格:
用户
id
name
论文
id
topic
角色
id
name
关系
id
role_id (references id on roles)
thesis_id (references id on theses)
user_id (references id on users)
我现在有代码
user.php的
class User extends Authenticatable
{
public function relations(){
return $this->hasMany('App\Relation', 'relations');
}
}
Thesis.php
class Thesis extends Model
{
public function relations(){
return $this->hasMany('App\Relation', 'relations');
}
}
Role.php
class Role extends Model
{
public function relations(){
return $this->hasMany('App\Relation', 'relations');
}
}
Relation.php
class Relation extends Model
{
public function user(){
return $this->belongsToMany('App\User');
}
public function thesis(){
return $this->belongsToMany('App\Thesis');
}
public function role(){
return $this->belongsToMany('App\Role');
}
}
现在我在插入数据透视表时使用 $ relation = new Relation; 方法。
我不知道如何从数据透视表中获取数据。例如,获取用户的论文以及用户对该特定论文<具有哪种角色 / strong>即可。
我尝试过像 $ user-&gt; thesis()或 $ user-&gt; role()或 $ user-&gt ;论文() - &gt;角色(),但没有一个不起作用。我只得到一个未定义的方法错误。
如果我能够得到一些帮助或至少某种方向,即使我在这里展示的内容有些正确,我也会非常感激。
谢谢。
答案 0 :(得分:5)
您对通过中间表存储关系的Many to Many relationship感兴趣。中间表可以在其上存储其他属性,因此,您可以创建具有附加thesis_users
属性的role_id
中间表。该文档涵盖了“检索中间表列”标题下的此用例。您不需要其他模型来表示这些关系。
如果您需要确定哪个pivot table
用户具有特定Thesis
,则可以查询中间表(也称为roles
),例如:
return $this->belongsToMany('App\Thesis')->wherePivot('role_id', 1);
您的用户模型关系看起来像这样:
public function theses()
{
return $this->belongsToMany('App\Thesis');
}
你的论文模型关系看起来像这样:
public function users()
{
return $this->belongsToMany('App\User');
}
然后你可以对论文模型做另外的关系约束,如下所示:
public function authors()
{
return $this->belongsToMany('App\User')->wherePivot('role_id', 1);
}
public function reviewers()
{
return $this->belongsToMany('App\User')->wherePivot('role_id', 2);
}
public function instructors()
{
return $this->belongsToMany('App\User')->wherePivot('role_id', 3);
}
在您的用户模型上:
public function authored()
{
return $this->belongsToMany('App\Thesis')->wherePivot('role_id', 1);
}
public function reviewer()
{
return $this->belongsToMany('App\Thesis')->wherePivot('role_id', 2);
}
等
Thesis::find(1)->reviewers(); // returns every App\User with the role_id 2 on App\Thesis with ID 1
Thesis::find(1)->instructors(); // returns every App\User with the role_id 3 on App\Thesis with ID 1
User::find(1)->theses(); // returns each App\Thesis that the user has any role on
User::find(1)->authored(); // returns each App\Thesis that the user has the author role on
答案 1 :(得分:0)
我做了一些工作。建立了新的关系。 This可能会对您有所帮助。我在这里复制了相同的代码。
它可能不是最好的表现。
第一种情景 - 属于许多人
实施例
用户属于多个角色
角色属于许多用户
角色属于许多权限
权限属于许多角色
users → user-role → roles → role-permission→ permissions
5个表(2个支点)
所以,让我们说我们想要获取用户权限,这些权限通过角色连接
//attach roles to user
$user->roles()->attach($admin->id);
//attach permissions to user
$admin->permissions()->attach($permission->id);
//get users' permissions using HasManyThroughMany relationship
$userPermissions = $user->permissions();
user.php的
use App\Extensions\Eloquent\Model as Model;
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id');
}
public function permissions()
{
return $this->hasManyThroughMany(Permission::class,
Role::class,
'user_role',
'role_permission',
'permission_id',
'role_id');
}
}
Role.php
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class, 'user_role', 'role_id', 'user_id');
}
public function permissions()
{
return $this->belongsToMany(Permission::class, 'role_permission', 'role_id', 'permission_id');
}
}
Permission.php
class Permission extends Model
{
public function users()
{
return $this->belongsToMany(User::class ,'user_permission', 'permission_id', 'user_id');
}
public function roles()
{
return $this->belongsToMany(Role::class, 'role_permission', 'permission_id', 'role_id');
}
}
第二种情景 - 有很多次
实施例
学生有很多报名
每个报名都有很多科目
每个主题属于注册
每个注册都属于学生
student→ enrollment → subject
3桌
所以,让我们说我们想要取一个学生科目,这些科目是通过报名连接的
//save students enrollment
$student->enrollments()->save($enrollment);
//save enrollments subject
$enrollment->subjects()->save($subject);
//get student's subjects using HasManyThroughMany relationship
$student->subjects();
Student.php
use App\Extensions\Eloquent\Model as Model;
class Student extends Model
{
public function enrollments()
{
return $this->hasMany(Enrollment::class);
}
public function subjects()
{
return $this->hasManyThroughMany(Subject::class, Enrollment::class);
}
}
Enrollment.php
class Enrollment extends Model
{
public function subjects()
{
return $this->hasMany(Subject::class);
}
public function student()
{
return $this->belongsTo(Student::class);
}
}
Subject.php
class Subject extends Model
{
public function enrollment()
{
return $this->belongsTo(Enrollment::class);
}
}
新的HasManyThroughMany关系文件。
HasManyThroughMany.php
namespace App\Extensions\Eloquent;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\Relation;
class HasManyThroughMany extends Relation
{
public function __construct(
Builder $query,
EloquentModel $farParent,
EloquentModel $parent,
$firstKey, $secondKey,
$localKey,
$throughKey)
{
$this->localKey = $localKey;
$this->firstKey = $firstKey;
$this->secondKey = $secondKey;
$this->farParent = $farParent;
$this->throughKey = $throughKey;
$this->farParentRelatedKey = $this->getModelRelatedKey($this->farParent);
parent::__construct($query, $parent);
}
public function addConstraints()
{
$parentTable = $this->parent->getTable();
$this->setJoin();
if (static::$constraints && !$this->throughKey) {
$localValue = $this->farParent[$this->localKey];
$this->query->where($parentTable.'.'.$this->firstKey, '=', $localValue);
} else {
$localValue = $this->farParent['id'];
$this->query->where($this->firstKey . '.' . $this->farParentRelatedKey, '=', $localValue);
}
}
protected function setJoin(Builder $query = null)
{
$query = $query ?: $this->query;
$foreignKey = $this->related->getTable().'.'.$this->secondKey;
$farParentTable = $this->farParent->getTable();
$farParentTableKey = $farParentTable.'.'.$this->localKey;
$firstKey = $this->parent->getTable().'.'.$this->firstKey;
$id = $this->related->getTable() . '.id as id';
$all = $this->related->getTable() . '.*';
$columns = [$id, $all];
if(!$this->throughKey){
$query->addSelect($columns)
->join($this->parent->getTable(),
$this->getQualifiedParentKeyName(),
'=',
$foreignKey)
->join($farParentTable,
$farParentTableKey,
'=',
$firstKey);
} else {
$query->addSelect($columns)
->join($this->secondKey,
$this->secondKey . '.' . $this->localKey,
'=',
$this->related->getTable() . '.id')
->join($this->firstKey,
$this->firstKey . '.' . $this->throughKey,
'=',
$this->secondKey . '.' . $this->throughKey)
->join($farParentTable,
$farParentTable . '.id',
'=',
$this->firstKey . '.' . $this->farParentRelatedKey);
}
if ($this->parentSoftDeletes()) {
$query->whereNull($this->parent->getQualifiedDeletedAtColumn());
}
}
public function getModelRelatedKey($model)
{
return strtolower(class_basename($model)) . '_id';
}
public function getForeignKey()
{
return $this->related->getTable().'.'.$this->secondKey;
}
public function parentSoftDeletes()
{
return in_array('Illuminate\Database\Eloquent\SoftDeletes',
class_uses_recursive(get_class($this->parent)));
}
public function addEagerConstraints(array $models){}
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, $this->related->newCollection());
}
return $models;
}
public function match(array $models, Collection $results, $relation){}
public function getResults()
{
return $this->get();
}
}
新模型文件 Model.php
namespace Hello\Extensions\Eloquent;
use Illuminate\Database\Eloquent\Model AS EloquentModel;
use App\Extensions\Eloquent\HasManyThroughMany;
class Model extends EloquentModel
{
public function hasManyThroughMany($related,
$through,
$firstKey = null,
$secondKey = null,
$localKey = null,
$throughKey = null)
{
$through = new $through;
$firstKey = $firstKey ?: $this->getForeignKey();
$secondKey = $secondKey ?: $through->getForeignKey();
$localKey = $localKey ?: $this->getKeyName();
return new HasManyThroughMany((new $related)->newQuery(),
$this,
$through,
$firstKey,
$secondKey,
$localKey,
$throughKey);
}
}