调用未定义的方法“ Illuminate \\ Database \\ Query \\ Builder :: can()”

时间:2018-11-16 09:38:55

标签: php laravel laravel-5.5 laravel-passport

无法在任何地方找到答案

我正在使用Laravel 5.5策略来限制用户列出用户未注册的属性(通过API进行身份验证)。 我有两个类User和HostProperty。此外,我已经注册了一个策略,供用户按ID访问其托管属性列表。

这是我的模特。

主要问题无法调用控制器方法-抛出上述错误:

$authUser = auth('api')->user();
if ($authUser->can('access', $property)) {
              return response()->json(['success' => 'success']); 
            } else {
              return response()->json(['error' => 'error']); 
            }

User.php

namespace App;

use Illuminate\Notifications\Notifiable;
use Cartalyst\Sentinel\Users\EloquentUser;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laravel\Passport\HasApiTokens;
use Illuminate\Auth\Authenticatable as AuthenticableTrait;
use Illuminate\Contracts\Auth\Authenticatable;

class User extends EloquentUser implements Authenticatable
{
    use HasApiTokens, Notifiable;
    use SoftDeletes;
    use AuthenticableTrait;
    protected $guarded=[];
    protected $dates = ['deleted_at'];
    protected $hidden = [
        'password', 'remember_token',
    ];

    //hosts relation
    public function hostproperty()
    {
        return $this->hasMany('App\Models\Hosts\HostProperty','user_id');
    }
}

HostProperty.php

namespace App\Models\Hosts;

use Illuminate\Database\Eloquent\Model;

class HostProperty extends Model
{
    public $timestamps = true;
    protected $guarded=[];
    protected $hidden = [
        'user_id',
    ];
    public function user()
    {
        return $this->belongsTo('App\User','user_id');
    }
}

HostPropertyPolicy

namespace App\Policies\Host;

use App\User;
use App\Models\Hosts\HostProperty; 
use Illuminate\Auth\Access\HandlesAuthorization;

class HostPropertyPolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    public function access(User $user, HostProperty $HostProperty)
    {return TRUE;
        //return $user->id === $HostProperty->user_id;
    }
}

AuthServiceProvider

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Models\Hosts\HostProperty;
use App\Policies\Host\HostPropertyPolicy;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
        HostProperty::class=>HostPropertyPolicy::class,
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
         Passport::routes();

    }
}

HostPropertyController

    use App\User;
    use App\Models\Hosts\HostProperty; 
    use App\Http\Controllers\Controller;
class HostPropertyController extends Controller
{
    public function listOneProperty($propertyId)
        {
            $authUser = auth('api')->user();
            $property=HostProperty::with('user')->find($propertyId);
            if ($authUser->can('access', $property)) {
              return response()->json(['success' => 'success']); 
            } else {
              return response()->json(['error' => 'error']); 
            }
    }

}

路线

Route::get('listOneProperty/{propertyId}',  array('as' => 'listOneProperty.get', 'uses' => 'HostPropertyController@listOneProperty'));

请注意:我是从API调用的-上面的路由用于API,我无法在API路由上使用该策略。呼叫此路线时,我不断收到上述错误。

我尝试过

$this->authorize('access', $property);

但是,由于API不存储登录会话,因此上述操作无法完成,因此我再次尝试

$authUser = auth('api')->user();
$authUser->authorize('access', $property);

也不起作用。我已经尽力了,但仍然做不到。

如果某人有在Passport身份验证的API中使用Laravel策略的示例,则对希望正确完成此操作的任何人都是有帮助的。

致谢

2 个答案:

答案 0 :(得分:0)

看起来像

$authUser = auth('api')->user();

返回查询而不是User模型。

在调用$authUser

之前,请确保->can()是用户模型。

答案 1 :(得分:0)

  

但是,由于API不存储登录会话,因此上述操作无法完成,因此我再次尝试使用

身份验证通常由Laravel中的中间件处理。如果您使用的是Passport,则只要发送正确的Authorization标头和令牌,就应该能够使用auth:api中间件对请求进行身份验证。

尝试更改此内容

$authUser = auth('api')->user();

对此

$authUser = auth()->user();

并将身份验证中间件添加到您的路由:

Route::get('listOneProperty/{propertyId}', 'HostPropertyController@listOneProperty')
     ->name('listOneProperty.get')
     ->middleware('auth:api');

如果您要从自己的Web视图中使用该api,并且希望它与当前会话配合使用,请查看Passport文档的使用JavaScript使用API​​ 部分: https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript