Фасад Laravel и поставщик услуг

Я впервые использую фасады и поставщиков услуг Laravel (я использую Laravel 5).

У меня такой ServiceProvider:

<?php namespace App\Providers;
...
class AccessServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->alias('access', 'App\Services\Permissions\Permissions');
        $this->app->bindShared('access', function() {
            return new Permissions();
        });
        return new App\Services\Permissions\Permissions();
    }

    public function provides(){
        return ['App\Services\Permissions\Permissions'];
    }
}

Мой класс разрешений выглядит так:

<?php namespace App\Services\Permissions;
class Permissions{
    private $permissions;
    public function __construct(){
        $this->permissions =  [
            "AssignQuotes" => new CanAssignQuotesPermission()
        ];
    }

    public function hasPermission($permission, $user){
        return $this->permissions[$permission]->canDo($user->role_id);
    }
}

Я добавил это в свой aliases в app.php:

'Access' => 'App\Services\Permissions\Access'

Я добавил это в свой providers в app.php:

'App\Providers\AccessServiceProvider',

Я создал этот Facade класс:

<?php namespace App\Services\Permissions;
use Illuminate\Support\Facades\Facade;

class Access extends Facade {
    protected static function getFacadeAccessor() { return 'access'; }
}

Насколько я понимаю, я регистрирую псевдоним, который указывает на класс фасада, который ссылается на привязку, указывающую на класс.

Я зарегистрировал привязку в ServiceProvider, которую зарегистрировал в app.php.

Теперь в моем файле маршрутов я тестирую следующий код:

Route::get('test', function(){
    $user = User::find(1);
    $access = Access::hasPermission("AssignQuotes", $user);
    return "test";
}

Однако я получаю эту ошибку:

FatalErrorException in Facade.php line 213:
Call to undefined method App\Services\Permissions\Access::hasPermission()

person ajon    schedule 23.09.2015    source источник
comment
Laravel 5. Извините, что не включил это. Я отредактировал свой пост   -  person ajon    schedule 23.09.2015
comment
Попробуйте использовать get_class в строке 213 Facade.php, чтобы увидеть, какой у вас там объект.   -  person bernie    schedule 23.09.2015
comment
Когда я использую get_class, я получаю: App\Services\Permissions\Access. Должен ли я получить другой класс или класс фасада?   -  person ajon    schedule 23.09.2015
comment
$instance определенно должен быть экземпляром App\Services\Permissions\Permissions, поскольку это класс с методом hasPermission. __callStatic перехватывает вызовы несуществующих статических методов на фасаде и передает их базовому экземпляру.   -  person bernie    schedule 23.09.2015
comment
@bernie, вы были правы ... когда я вызываю get_class теперь, когда он работает, он возвращает класс Permissions.   -  person ajon    schedule 23.09.2015


Ответы (3)


Я обнаружил только следующие проблемы:

Удалите ненужный код у поставщика услуг:

<?php namespace App\Providers;
...
class AccessServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->bind('access', 'App\Services\Permissions');
        // OR bindShared() if you need to share a single instance across the app
        $this->app->bindShared('access', function() {
            return new \App\Services\Permissions();
        });
    }

    // No need for a provides() method
}

in providers of app.php :

App\Providers\AccessServiceProvider::class,

in aliases of app.php :

'Access'      => App\Services\Permissions\Access::class,

Может, там что-нибудь исправит.

person bernie    schedule 23.09.2015
comment
Я получаю ошибку 500, когда использую ::class. У меня php 5.4, и я думаю, что это произошло в 5.5. Я перешел на использование привязки. - person ajon; 23.09.2015

У моего класса serviceProvider было несколько проблем. Должно получиться так:

public function register() {
    $this->app->bind('access', function($app) {
        return new Permissions();
    });
}

Я избавился от лишнего кода, включая функцию providers согласно @bernie. Я также добавил в привязку параметр $ app.

Полная проблема заключается в том, что поставщик услуг не загружался (возможно, потому, что композитор не нашел его). Если поставщик услуг не загружен, привязка не произойдет и фасад не будет работать.

person ajon    schedule 23.09.2015

Может в этом проблема? НЕТ

Изменение с (app.php):

'Access' => 'App\Services\Permissions\Access'

to

'Access' => 'App\Services\Permissions\Permissions'

Вы получаете ошибку

Call to undefined method App\Services\Permissions\Access::hasPermission()

показывает, что php пытается вызвать hasPermission в классе Access, а не в классе Permissions, который реализует этот метод.

person bernie    schedule 23.09.2015
comment
Когда я меняю его, я получаю Non-static method ...hasPermission() should not be called statically. Я думаю, что в app.php псевдоним должен указывать на класс фасада, тогда класс фасада должен создать экземпляр и вызвать метод класса разрешений. Я так понимаю это, но я явно не все правильно понимаю. - person ajon; 23.09.2015
comment
Извините, но у меня все в порядке ... Я не вижу проблемы. Я использую Laravel 4.2 и никогда не добавлял свой собственный фасад. Я оставлю этот ответ, чтобы другие люди его не предлагали. - person bernie; 23.09.2015