0

So I have a boot() in my AuthServiceProvider that reads some Permissions from the database:

    foreach (Permission::all() as $perm) {
        Gate::define($perm->name, function ($user) use ($perm) {
            return $user->hasPermission($perm->name);
        });
    }

Only problem is when I do migrate:fresh everything breaks (with an exception) because, well, the tables don't exist.

How can I tell the Permission model to only load data if the table exists?

Sammaye
  • 43,242
  • 7
  • 104
  • 146
  • @dparoli is that the best way? To include a migration level class? – Sammaye Mar 02 '19 at 18:21
  • In MySQL you can try with a query like that: `select * from information_schema.tables where table_schema = 'your_database' and table_name = 'your_table'` you can use the DB query builder for that but `Schema::hasTable('mytable');` is not dependent on database type. For your case probably is good even a `try .... catch` – dparoli Mar 02 '19 at 18:30
  • 1
    Sorry for the double comment. To answer your question: I have used The Schema class even in a middlware, so you can use it, i's very useful for this kind of things. – dparoli Mar 02 '19 at 18:41
  • This logic probably doesn't belong in your service provider, since providers are responsible for configuring services like database drivers, cache drivers, etc. If you describe more details of what this bit of code is setting up for your application I might be able to suggest another place to implement it that won't cause these errors – Travis Britz Mar 02 '19 at 19:43
  • @TravisBritz what it does is go through all the permissions I have stored in the DB and assigns the gates for them, so when it iterates through a permission it gets a "name" field and that is assigned as a gate and the logic within the gate basically takes the user model and checks if the user has that permission assigned – Sammaye Mar 02 '19 at 19:45

1 Answers1

2

To answer the question being asked, you can use this:

if (Schema::hasTable('mytable')) {

}

On a side note, registering gates from the database in this way is a bit of an anti-pattern. Service providers don't usually have access to the authenticated user yet because they're responsible for preparing the application, and run before things like the session middleware that authenticates users. There are many other ways to structure authorization that won't cause problems like these.

Travis Britz
  • 5,094
  • 2
  • 20
  • 35
  • But doesn't the can middleware etc use the gates? And the docs recommend making the gates in the service provider – Sammaye Mar 02 '19 at 20:40
  • 1
    @Sammaye Yes gates would be defined in AuthServiceProvider, but not dynamically from the database on each request for each user. It's sounding like you could use a single [middleware with parameters](https://laravel.com/docs/5.7/middleware#middleware-parameters) to replace all of those callbacks, but without knowing more about your application and how you're accessing those gates I don't know what the best solution is. I'm also getting a little off topic, so if you'd like to investigate it further I'd recommend asking a new question – Travis Britz Mar 02 '19 at 21:17
  • If I do that I lose the power of the inbuilt can() method and Laravel's own upholdings for permission handling, which extensions such as spatie etc explicitly suggest you don't do. Anyway, I might make a new question if I wish ti delve into this more – Sammaye Mar 02 '19 at 21:20