1

This is my first time using Laravel's Facades and Service Providers (I'm on Laravel 5).

I have this 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'];
    }
}

My Permissions class looks like this:

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

I added this to my aliases in app.php:

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

I added this to my providers in app.php:

'App\Providers\AccessServiceProvider',

I created this Facade class:

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

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

From my understanding, I register an alias, which points to a Facade class which references a binding which points to a class.

I registered the binding in the ServiceProvider which I registered in the app.php.

Now in my routes file I am testing with the following code:

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

However I am getting this error:

FatalErrorException in Facade.php line 213:
Call to undefined method App\Services\Permissions\Access::hasPermission()
ajon
  • 7,868
  • 11
  • 48
  • 86
  • Laravel 5. Sorry for not including that. I've edited my post – ajon Sep 23 '15 at 17:42
  • Try to use `get_class` in Facade.php line 213 to see what kind of object you have there. – bernie Sep 23 '15 at 18:42
  • When I use `get_class` I get: `App\Services\Permissions\Access`. Should I be getting the other class or the facade class? – ajon Sep 23 '15 at 19:09
  • The `$instance` should definitely.be an instance of `App\Services\Permissions\Permissions` since that's the class with the `hasPermission` method. The `__callStatic` intercepts calls to non-existent static methods on the Facade and transfers it to the underlying instance. – bernie Sep 23 '15 at 20:03
  • @bernie you were right... when I call get_class now that it is working it returns the Permissions class. – ajon Sep 23 '15 at 20:59

3 Answers3

1

The only issues I found are :

Remove unnecessary code from your service provider:

<?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,

Maybe something in there will fix it.

bernie
  • 9,820
  • 5
  • 62
  • 92
  • I get 500 error when I use `::class` I have php 5.4 and I think that came around in 5.5. I switched to just using bind. – ajon Sep 23 '15 at 20:42
1

My serviceProvider class had a few issues. It should be like this:

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

I got rid of the extra code including the providers function as per @bernie. I also added the $app parameter to the binding.

The full issue is that the service provider wasn't being bootstrapped (maybe because composer wasn't finding it). If the service provider isn't bootstrapped then the binding won't happen and the facade doesn't work.

ajon
  • 7,868
  • 11
  • 48
  • 86
0

Could this be the problem? NO

Change from (app.php):

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

to

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

The error you get

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

shows that php is trying to call hasPermission on the Access class instead of on the Permissions class which implements that method.

bernie
  • 9,820
  • 5
  • 62
  • 92
  • When I Change it I get `Non-static method ...hasPermission() should not be called statically`. I think that in `app.php` the alias should point to the Facade class, then the facade class is supposed to create an instance and call the method of the Permissions class. That is how I understand it, but I clearly don't understand it all properly. – ajon Sep 23 '15 at 18:31
  • I'm sorry but everything looks good to me... I can't see the problem. I'm on Laravel 4.2 and never added my own Facade though. I'll leave this answer up so other people don't suggest it. – bernie Sep 23 '15 at 18:37