laraveleloquentlaravel-facade

Laravel Facade error: Non-static method should not be called statically


I have a simple modal having an index method to get data from DB

Modal: Nation

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Nation extends Model{
  function index(){
     Nation::where(['visible'=>1])->get();
  }
}

Now I want to call this function from a controller:

Controller:

 $nations = Nation::index();

To make this I created a Facade in this way:

  1. Created a Provider
  2. Registered the provider in config/app.php
  3. Created the Facade
  4. Registered the Alias in config/app.php

Step 1 - Provider:

php artisan make:provider NationServiceProvider

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

Step 2: Register the provider in config/app.php

In providers array:

    App\Providers\NationServiceProvider::class,

Step 3 Create the Facade

I created a folder App/Facades/ and inside the file NationFacade.php

namespace App\Facades;
use Illuminate\Support\Facades\Facade;

class NationFacade extends Facade{
protected static function getFacadeAccessor(){
    return 'nation';
   }
}

Step 4: Register the alias in config/app.php

In Aliases array:

    'Nation' => App\Facades\NationFacade::class

But, when I run the controller I got the error:

"message": "Non-static method App\\Models\\Nation::index() should not be called statically",

I also tried to clear cache and composer dump. What I'm missing here?

Thanks for any sugegstion!


Solution

  • AFAIK, when you use a class without namespace, php assumes the file should be in the same directory as current file. Only when it doesn't find, it calls the __autoload magic method. Laravel's/Composer's resolving logic sits inside __autoload method (this is the place where Laravel resolves the alias which you have registered with it).

    In your case, php detects a class with same name residing in its reach so it tries to use that.

    Solutions are

    1. Change the Alias to some class which is not current directory. In this case you have already named the facade a different name, so just use that

      // Register alias
      'NationFacade' => App\Facades\NationFacade::class
      
      // Call it like
      NationFacade::index()
      

      OR

      // Import
      use App\Facades\NationFacade
      
      // Call it like
      NationFacade::index()
      
    2. Use php's namespace with alias instead of Laravel's alias (i am not 100% sure if this will work)

      // Import the facade
      use App\Facades\NationFacade as Nation;
      
      // Call it like
      Nation::index()
      

    If you still have doubts, please feel free to comment down below