dougua4836 2018-01-14 08:00
浏览 24
已采纳

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

Unfortunately, I cannot successfully access a DB column in a pivot table. Besides this, the model is working well.

Model Device

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

Model Task

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

I tried with a very simple example but failed:

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

Error:

"Trying to get property of non-object"

  • 写回答

1条回答 默认 最新

  • dtf54486 2018-01-14 08:34
    关注

    You can only access the pivot data if the model collection is the result of a call to the relation method that is aware of that pivot data, meaning you must access devices on a Task model to find any pivot data:

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

    This is because of what pivot data represents: additional data that comes with a relationship definition. So created_at represents a statement such as:

    Task 1 belongs to - among many - Device x since created_at.

    Pivot data does not tell you anything about 1 specific model in of itself.

    Problem 1:

    It is an impossible to determine request to do Task::find(1)->pivot, since Task might have multiple belongsToMany relations, and the expression above does not explicitly specify which relation to access.

    Problem 2: Imagine that Eloquent models would have a cure for problem 1 by implementing a method called pivotFor() that would let you do something like Task::find(1)->pivotFor('devices'). Now there is still information missing, because it is not known which of the related Device models we are trying to access the pivot data for (belongsToMany queries for a Collection of many models)

    To fix problem 2 our hypothetical pivotFor method should accept a second argument of type int, whose value matches the id of the target Device. But that is just theory. Instead you can try to compose the behavior you're looking for from the facilities that eloquent models, relationships and collections already provide (it's possible), and create this implementation on a higher level (a Support class / repository, for example).

    The Laravel documentation provides much more information about how all this works, and it's very likely you'll find a solution there.

    in short: You'll need to determine:

    • Which relation you want to use on Task
    • Which model of the collection of related you want to get back

    Since this is a higher order operation - the belongsToMany simply does not return single models - you should come up with your own implementation for what you try to achieve.

    P.S.

    Task::find(1)->devices returns you exactly Illuminate\Database\Eloquent\Collection|App\Device[].

    You tried to access created_at on the pivot object. You should add that to the withPivot call, if that column indeed exists on the pivot 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();
    }
    

    If you actually intended to get the created_at value for a Task or Device you should access that on the respective model instances directly:

    $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
        );
    });
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法
  • ¥15 组策略中的计算机配置策略无法下发
  • ¥15 如何绘制动力学系统的相图
  • ¥15 对接wps接口实现获取元数据
  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊