Laravel L5.5 无法访问 "Many to many" 关系中的枢轴 table

Laravel L5.5 No access to pivot table in "Many to many" relationship

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

模型设备

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);

错误:

"Trying to get property of non-object"

如果模型 collection 是调用了解该数据透视数据的关系方法的结果,则您只能访问数据透视数据,这意味着您必须访问 Task 模型上的 devices 才能找到任何数据透视表:

$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 关系,并且上面的表达式没有明确指定访问哪个关系。

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

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

The Laravel documentation 提供了有关所有这些工作原理的更多信息,您很可能会在那里找到解决方案。

简而言之:您需要确定:

  • 您想在 Task
  • 上使用哪个关系
  • 你想找回collection相关的哪个型号

因为这是一个 高阶 操作 - belongsToMany 根本不是 return 单一模型 - 你应该想出你自己的实现你努力实现。

P.S.

Task::find(1)->devicesreturn你就是Illuminate\Database\Eloquent\Collection|App\Device[].

您试图访问枢轴 object 上的 created_at。您应该将其添加到 withPivot 调用中,如果该列确实存在于数据透视表 table:

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();
}

如果您实际上想要获取 TaskDevicecreated_at 值,您应该直接在相应的模型实例上访问它:

$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
    );
});