Larastan: Error when there is no database

Created on 10 Sep 2020  路  15Comments  路  Source: nunomaduro/larastan

  • Larastan Version: 0.6.4
  • --level used: max

Description

I'm using spatie/laravel-permission package in my app. That registers some stuffs in service provider. When i setup a pipeline this error occured.

Similar issue: https://github.com/symfony/symfony/issues/37069

Error Output

------ --------------------------------------------------------------------- 
  Line   Http/Controllers/Api/RoleController.php                              
 ------ --------------------------------------------------------------------- 
         Internal error: SQLSTATE[HY000] [2002] Connection refused (SQL:      
         select column_name as `column_name` from information_schema.columns  
         where table_schema = forge and table_name = roles)                   
         Run PHPStan with --debug option and post the stack trace to:         
         https://github.com/phpstan/phpstan/issues/new                        
 ------ --------------------------------------------------------------------- 
 ------ --------------------------------------------------------------------- 
  Line   Http/Resources/PermissionResource.php                                
 ------ --------------------------------------------------------------------- 
         Internal error: SQLSTATE[HY000] [2002] Connection refused (SQL:      
         select column_name as `column_name` from information_schema.columns  
         where table_schema = forge and table_name = permissions)             
         Run PHPStan with --debug option and post the stack trace to:         
         https://github.com/phpstan/phpstan/issues/new                        
 ------ --------------------------------------------------------------------- 
 ------ --------------------------------------------------------------------- 
  Line   Rules/EmptyRole.php                                                  
 ------ --------------------------------------------------------------------- 
         Internal error: SQLSTATE[HY000] [2002] Connection refused (SQL:      
         select column_name as `column_name` from information_schema.columns  
         where table_schema = forge and table_name = roles)                   
         Run PHPStan with --debug option and post the stack trace to:         
         https://github.com/phpstan/phpstan/issues/new                        
 ------ --------------------------------------------------------------------- 

Laravel code where the issue was found

class PermissionController extends Controller
{
    public function index(): JsonResponse
    {
        $permissions = Permission::all();

        return new JsonResponse([
            'data' => $permissions->pluck('name'),
        ]);
    }
}

Another example

ConnectionFactory reads Salesforce config from .env and creates a soap client.

    public function register(): void
    {
        $this->app->singleton(SforceEnterpriseClient::class, static function (): SforceEnterpriseClient {
            $factory = new ConnectionFactory();

            return $factory->createConnection();
        });
    }

Error Output

 ------ --------------------------------------------------------------------- 
  Line   Salesforce/Services/UserService.php                                  
 ------ --------------------------------------------------------------------- 
         Internal error: INVALID_LOGIN: Invalid username, password, security  
         token; or user locked out.                                           
         Run PHPStan with --debug option and post the stack trace to:         
         https://github.com/phpstan/phpstan/issues/new                        
 ------ --------------------------------------------------------------------- 
bug

All 15 comments

This occurs when you test a package for Laravel, not an application.
Testbench boots up Laravel which is not really _static_ analysis :)

AFAIK Larastan used to boot up Laraval but now it does real clean static analysis. @canvural ?

Hi,

Can you run PHPStan only on one file, Http/Controllers/Api/RoleController.php for example, with --debug flag and post the stack trace here?

@szepeviktor We still boot up the Laravel.

Sure.
```
$ php vendor/bin/phpstan analyse app/Http/Controllers/Api/RoleController.php --debug
Note: Using configuration file ./phpstan.neon.
Http/Controllers/Api/RoleController.php

Illuminate\Database\QueryException

SQLSTATE[HY000] [2002] Connection refused (SQL: select column_name as column_name from information_schema.columns where table_schema = forge and table_name = roles)

at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
667| // If an exception occurs when attempting to run a query, we'll format the error
668| // message to include the bindings with SQL, which will make this exception a
669| // lot more helpful to the developer instead of just the database's errors.
670| catch (Exception $e) {

671| throw new QueryException(
672| $query, $this->prepareBindings($bindings), $e
673| );
674| }
675|

````

Maybe we need the xdebug extension to get a stack trace...

Can you show your phpstan config, maybe there is some autoloader configured?

@voku

includes:
    - vendor/nunomaduro/larastan/extension.neon
    - vendor/timeweb/phpstan-enum/extension.neon
    - vendor/phpstan/phpstan-strict-rules/rules.neon

parameters:
    paths:
        - app

    level: max

    ignoreErrors:
        - '#Dynamic call to static method#'
        - '#Access to an undefined property SObject::#'
        - '#Variable property access on SObject#'

    checkMissingIterableValueType: false
  • Larastan version: 0.6.4
  • --level: 5

I'm also using spatie/laravel-permission and got this similar error as mentioned in the issue. --debug gives the same stack trace posted in https://github.com/nunomaduro/larastan/issues/656#issuecomment-690099511

-- --------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Error                                                                                                                                                    
 -- --------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Internal error: Internal error: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known (SQL:  
     select column_name as `column_name` from information_schema.columns where table_schema = my_app and table_name = roles) in file                 
     app/Policies/RolePolicy.php                                                                                          
     Run PHPStan with --debug option and post the stack trace to:                                                                                             
     https://github.com/phpstan/phpstan/issues/new                                                                                                            
     Internal error: Internal error: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known (SQL:  
     select column_name as `column_name` from information_schema.columns where table_schema = my_app and table_name = roles) in file                 
     app/Http/Controllers/Backend/RoleController.php                                                                      
     Run PHPStan with --debug option and post the stack trace to:                                                                                             
     https://github.com/phpstan/phpstan/issues/new                                                                                                            
 -- --------------------------------------------------------------------------------------------------------------------------------------------------------- 

This may not help but we're striving to release Laravel 1.0
Currently Laravel is booted up

https://github.com/nunomaduro/larastan/issues/656#issuecomment-690098048 馃憖

Totally looking forward to Laravel 1.0 release 馃コ

馃槒

I'm experiencing the same error. Here's a simple piece of code that will throw the error:

use Spatie\Permission\Models\Role;

public function doSomething(Role $role)
{
   return $role->permissions;
}

I did some debugging and I'm pretty sure this change is the culprit. Specifically, this part:

if (! isset(static::$guardableColumns[get_class($this)])) {
            static::$guardableColumns[get_class($this)] = $this->getConnection()
                        ->getSchemaBuilder()
                        ->getColumnListing($this->getTable());
}

Larastan seems to call the constructor for the Role class at some point, which will in turn end up performing a query here.

To temporarily fix this, one could use a Laravel version before this change was added. E.g. 7.23.2 (Note that this was a security fix so using a version of Laravel that does not have this change can be a bit dangerous)

In work projects, we are extending the \Spatie\Permission\Models\Role model and using our own Role model. So at first, I did not see this error.

But when I explicitly use that model like so:

public function doSomething(\Spatie\Permission\Models\Role $role): Collection
{
    return $role->permissions;
}

it produces the same error as in the original issue.

The error originates from here. The solution I'm thinking is wrapping this statement in try/catch block. And fallback to "guessing" the table name in catch block. Like this:

--- src/Properties/ModelPropertyExtension.php
+++ src/Properties/ModelPropertyExtension.php
@@ -73,9 +73,16 @@
         }

         $modelName = $classReflection->getNativeReflection()->getName();
+
         /** @var Model $modelInstance */
-        $modelInstance = new $modelName;
-        $tableName = $modelInstance->getTable();
+        try {
+            $modelInstance = new $modelName;
+
+            $tableName = $modelInstance->getTable();
+        } catch (\Exception $e) {
+            $tableName =  Str::snake(Str::pluralStudly(class_basename($modelName)));
+        }
+

         if (! array_key_exists($tableName, $this->tables)) {
             return false;

Or we can just return false from the catch block. Ignoring this model.

Any other suggestions?

@canvural

Seems good to me. Can't think of another solution.

@eislambey and @Daanra Can you test master and check if it fixed the issue for you?

@canvural That fixed it for me. Thanks!

Was this page helpful?
0 / 5 - 0 ratings