Search code examples
phplaravel-5autoloader

Custom Class not loading in Controller


I have a file called InvoiceDataSource.php and it's path is app\Core\Forms\Invoice\InvoiceDataSource.php, and that file contains this.

<?php

namespace App\Core\Forms\Invoice;

class InvoiceDataSource {

public function getAllCustomers(){

    return Customer::selectRaw('id as `value`,'.
                     'name as `label`')
                    ->get()
                    ->toArray();
}

}

?>

I have included this in composer.json file as well like so,

"autoload": {
    "classmap": [
        "database/seeds",
        "database/factories",
        "app/Core/Forms/Invoice/InvoiceDataSource.php" 
    ],
    "psr-4": {
        "App\\": "app/"
    }
},

It has also been added to autoloader in autoload_classmap.php file.

Now when I am trying to access this in the controller like this

//
public function getDataSource($id,Request $request){

    return InvoiceDataSource::getAllCustomers();

}

But for some reason the error read this,

{message: "Class 'App\Http\Controllers\InvoiceDataSource' not found",…}
exception: "Symfony\Component\Debug\Exception\FatalThrowableError"
file: "/home/zrehan/projects/erp/app/Http/Controllers/FormController.php"
line: 88
message: "Class 'App\Http\Controllers\InvoiceDataSource' not found"
trace: [{function: "getDataSource", class: "App\Http\Controllers\FormController", type: "->"},…]

Can someone help me with this?


Solution

  • The error is triggered because your code is not using the right class, this is what it is looking for:

    App\Http\Controllers\InvoiceDataSource
    

    Which would simply be looking for the file InvoiceDataSource.php in your controller folder.

    To change the class it is looking for use use.

    This is because since you are in the controller namespace, when you name a class without the use attribute, it defaults to the controller (App\Http\Controllers) namespace.

    <?php
    
    namespace App\Http\Controllers;
    
    // ...
    
    use App\Core\Forms\Invoice\InvoiceDataSource;
    
    // ...
    
    class SomeController expands Controller {
      // ...
    
      public function getDataSource($id,Request $request){
    
          return InvoiceDataSource::getAllCustomers();
    
      }
    
    // ...
    
    }
    

    UPDATE:

    As mentioned in the comments you have different alternatives as well when including a class with a different namespace:

    1) Use the entire class namespace

      public function getDataSource($id,Request $request){
    
          return App\Core\Forms\Invoice\InvoiceDataSource::getAllCustomers();
    
      }
    

    2) Or if you have multiple classes with the same name under different namespaces you can use as:

    use App\Core\Forms\Invoice\InvoiceDataSource as DataSource
    use App\Core\Mailer\Invoice\InvoiceDataSource as DataSourceMailer
    // ... etc