bindings 中间件是怎么回事?

看到手动添加 bindings 中间件这一段。哪位能给讲讲这个中间件吗?
在不用Dingo的时候为什么不用手动添加?
如果没有添加这个中间件,看到错误信息“Call to a member function toDateTimeString() on null”,怎么判断出来是bindings中间件导致的?谢谢!

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2
  • 如果没有添加这个中间件,看到错误信息“Call to a member function toDateTimeString() on null”,怎么判断出来是bindings中间件导致的?
    • 实际上,这个错误是在用户id为1或者2的时候,才会出现。假如你一开始就使用id为8的用户来测试(此用户应该没有manage_contents权限),那么在$this->authorize('update', $topic);这句就会报This action is unauthorized.的500错误。可以Trace如下:
      App\Models\User->isAuthorOf()
      App\Policies\TopicPolicy->update()
      Illuminate\Auth\Access\Gate->callPolicyMethod()
      Illuminate\Auth\Access\Gate->callAuthCallback()
      Illuminate\Auth\Access\Gate->raw()
      Illuminate\Auth\Access\Gate->authorize()
      App\Http\Controllers\Api\TopicsController->authorize()
      App\Http\Controllers\Api\TopicsController->update()
    • 不难发现,在 \App\Models\User::isAuthorOf方法中,有判断权限的代码如下,这里不相等,就会报错。
      public function isAuthorOf($model)
      {
      return $this->id == $model->user_id;
      }
    • 打印一下:dd($this->id, $model->user_id, $model->exists), 从而得知 $model 并没有成功传递topic模型实例过来,因此考虑是bindings中间件的问题。
      public function isAuthorOf($model)
      {
      dd($this->id, $model->user_id, $model->exists); //结果为8, null, false.
      return $this->id == $model->user_id;
      }
    • 再加上binds中间件,上述打印结果为8,8,true.
    • 再回到id为1的用户,由于此用户有manage_contents权限,而在 \App\Policies\Policy::before中有如下代码,只要用户拥有管理内容的权限的话,即授权通过。
      public function before($user, $ability)
      {
      // 如果用户拥有管理内容的权限的话,即授权通过
      if ($user->can('manage_contents')) {
          return true;
      }
      }
    • $this->authorize('update', $topic);这句就会直接通过,然后到 $this->response->item($topic, new TopicTransformer());这句时报错,报错截图上很清楚写到是TopicTransformer文件29行。
      file
    • 'created_at' => $topic->created_at->toDateTimeString(),$topic都没有绑定成功,当然就是null了。$topic->created_at也就是null了。
5年前 评论
liyu001989

作用,路由模型绑定
使用 dingo 因为路由注册的部分被 dingo 接管了,所以中间件没有绑定上。不使用 dingo 因为 api 这个中间件组已经全局启用了 bindings 见 app/Http/Kernel.php

如果没有添加这个中间件,看到错误信息“Call to a member function toDateTimeString() on null”,怎么判断出来是bindings中间件导致的

谁判断的,只能判断那个对象是null 或者 created_at 、updated_at 的值是null。具体得自己调试。

5年前 评论
  • 如果没有添加这个中间件,看到错误信息“Call to a member function toDateTimeString() on null”,怎么判断出来是bindings中间件导致的?
    • 实际上,这个错误是在用户id为1或者2的时候,才会出现。假如你一开始就使用id为8的用户来测试(此用户应该没有manage_contents权限),那么在$this->authorize('update', $topic);这句就会报This action is unauthorized.的500错误。可以Trace如下:
      App\Models\User->isAuthorOf()
      App\Policies\TopicPolicy->update()
      Illuminate\Auth\Access\Gate->callPolicyMethod()
      Illuminate\Auth\Access\Gate->callAuthCallback()
      Illuminate\Auth\Access\Gate->raw()
      Illuminate\Auth\Access\Gate->authorize()
      App\Http\Controllers\Api\TopicsController->authorize()
      App\Http\Controllers\Api\TopicsController->update()
    • 不难发现,在 \App\Models\User::isAuthorOf方法中,有判断权限的代码如下,这里不相等,就会报错。
      public function isAuthorOf($model)
      {
      return $this->id == $model->user_id;
      }
    • 打印一下:dd($this->id, $model->user_id, $model->exists), 从而得知 $model 并没有成功传递topic模型实例过来,因此考虑是bindings中间件的问题。
      public function isAuthorOf($model)
      {
      dd($this->id, $model->user_id, $model->exists); //结果为8, null, false.
      return $this->id == $model->user_id;
      }
    • 再加上binds中间件,上述打印结果为8,8,true.
    • 再回到id为1的用户,由于此用户有manage_contents权限,而在 \App\Policies\Policy::before中有如下代码,只要用户拥有管理内容的权限的话,即授权通过。
      public function before($user, $ability)
      {
      // 如果用户拥有管理内容的权限的话,即授权通过
      if ($user->can('manage_contents')) {
          return true;
      }
      }
    • $this->authorize('update', $topic);这句就会直接通过,然后到 $this->response->item($topic, new TopicTransformer());这句时报错,报错截图上很清楚写到是TopicTransformer文件29行。
      file
    • 'created_at' => $topic->created_at->toDateTimeString(),$topic都没有绑定成功,当然就是null了。$topic->created_at也就是null了。
5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!