Laravel L5.5无法访问“多对多”关系中的数据透视表

时间:2018-01-14 08:00:46

标签: php laravel laravel-5 eloquent laravel-eloquent

不幸的是,我无法成功访问数据透视表中的数据库列。除此之外,该模型运作良好。

模型设备

public function tasks()
{
    return $this->belongsToMany('App\Task', 'xx', 'yy', 'zz')
    ->withPivot('id', 'duedate', 'interval', 'reoccurdate', 'completed', 'state')
    ->withTimestamps();
}

模型任务

public function devices()
{
    return $this->belongsToMany('App\Device', 'xx', 'yy', 'zz')
    ->withPivot('id', 'duedate', 'interval', 'reoccurdate', 'completed', 'state')
    ->withTimestamps();
}

我尝试了一个非常简单的例子,但失败了:

dd(Task::findOrFail(1)->pivot->created_at);

错误:

  

“试图获取非对象的属性”

1 个答案:

答案 0 :(得分:1)

如果模型集合是调用知道该数据透视数据的关系方法的结果,则只能访问数据透视数据,这意味着您必须访问devices Task模型以查找任何数据透视数据:

$devicesForTask1 = Task::find(1)->devices;
$devicesForTask1->each(function (Device $device) {

    // Here we can use pivot, since the models were found through a
    // relation method that implements the pivot definition. each
    // model now has its own pivot property:
    Log::info($device->pivot->duedate);
    Log::info($device->pivot->interval);
    // etc...
});

这是因为数据透视数据代表的含义:关系定义附带的其他数据。所以created_at表示如下声明:

Task 1属于 - 其中之一 - 设备x自created_at

数据透视数据本身并不能告诉您任何有关特定模型的信息。

问题1:

无法确定执行Task::find(1)->pivot的请求,因为Task可能有多个belongsToMany关系,并且上面的表达式没有明确指定要访问的关系。

问题2: 想象一下,Eloquent模型可以通过实现一个名为pivotFor()的方法来解决问题1,这个方法可以让你做Task::find(1)->pivotFor('devices')之类的事情。现在仍然缺少信息,因为我们不知道哪些相关的Device模型正在尝试访问(belongsToMany {/ 1}}个Collection 许多的pivotFor个数据透视数据模型)

要解决问题2,我们假设的int方法应接受类型为Device的第二个参数,其值与目标Task的ID匹配。但那只是理论。相反,您可以尝试从雄辩的模型,关系和集合已经提供的设施(它可能)中构建您正在寻找的行为,并在更高层次上创建此实现(支持类/存储库) ,例如)。

The Laravel documentation提供了有关这一切如何运作的更多信息,并且您很可能会在那里找到解决方案。

简而言之:您需要确定:

  • 您要在belongsToMany
  • 上使用哪种关系
  • 您想要回复的相关系列的哪个型号

由于这是高阶操作 - Task::find(1)->devices根本不返回单个模型 - 您应该为自己尝试实现的目标提出自己的实现。

<强> P.S。

Illuminate\Database\Eloquent\Collection|App\Device[]会准确地返回created_at

您尝试访问数据透视对象上的public function devices() { return $this ->belongsToMany('App\Device', 'xx', 'yy', 'zz') ->withPivot( 'created_at', // Only if created_at exists on the pivot table! 'id', 'duedate', 'interval', 'reoccurdate', 'completed', 'state' ) ->withTimestamps(); } 。你应该将它添加到withPivot调用,如果该列确实存在于数据透视表上

created_at

如果您确实希望获得TaskDevice的{​​{1}}值,则应直接在相应的模型实例上访问该值:

$task = Task::find(1);

Log::info('Task was created at: ' . $task->created_at);

$task->devices->each(function (Device $device) {
    Log::info(
        'Device '
        . $device->id
        . ' was created at: '
        . $device->created_at
    );
});