phpno-framework

PHP autoloading class not found


let me first explain what I have done to reach this point. There is a tutorial on github called no-framework here it is https://github.com/PatrickLouys/no-framework-tutorial very good tutorial! I have completed it and am now wanting to add more libraries. I have composer setup with autoloading and the file looks like this.

{
"name": "xxx/no-framework",
"description": "no framework",
"authors": [
    {
        "name": "xxx",
        "email": "xxx@gmail.com"
    }
],
"require": {
    "php": ">=5.5.0",
    "filp/whoops": ">=1.1.2",
    "patricklouys/http": ">=1.1.0",
    "nikic/fast-route": "^0.7.0",
    "rdlowrey/auryn": "^1.1",
    "twig/twig": "~1.0",
    "illuminate/database": "*"
},
"autoload": {
    "psr-4": {
        "App\\": "src/"
    }
}

}

and In my src folder I have made a folder called Models and in there a Books.php and in the Books.php I have this

<?php
    class Book extends \Illuminate\Database\Eloquent\Model{
        protected $table = 'books';
    }

and in my Bootstrap.php file I've included this line after requiring the composer autoloader

include('Database.php');

The Database.php file is also in the src and looks like this

<?php

    use \Illuminate\Database\Capsule\Manager as Capsule;  

    $capsule = new Capsule; 

    $capsule->addConnection(array(
        'driver'    => 'mysql',
        'host'      => 'localhost',
        'database'  => 'test',
        'username'  => 'test',
        'password'  => 'l4m3p455w0rd!',
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => ''
    ));

    $capsule->bootEloquent();

And now the error. When I try to use to Book class by trying to use it in one of my controller like this

<?php

    namespace App\Controllers;

    use Http\Request;
    use Http\Response;
    use App\Template\Renderer;
    use App\Models\Book as Book;


    class Pages{
       private $request;
       private $response;
       private $renderer;

       public function __construct(Request $request, Response $response, Renderer $renderer){
           $this->request = $request;
           $this->response = $response;
           $this->renderer = $renderer;
       }

       public function index(){
          $book = new Book;
          $book->title = 'test';
          $book->save();

          $html = $this->renderer->render('index');
          $this->response->setContent($html);
      }
  }

I get an error saying "Class 'App\Models\Book' not found" I'm asuming im not autoloading something correctly, but the alias thing is there in the composer.json or maybe something else is wrong idk. help? The tutorial uses a dependency injector library called Auryn, maybe I'm missing something in there? idk doubt it though.

EDIT: If i change the use statement to to an include like so include('../src/Models/Book.php'); and put a \ in front of the class instantiation like so $book = new \Book; and then it works, BUT this is clearly not the right way.


Solution

  • I believe the Composer classmap merely tells the system where to find the files for a given class. PHP still needs to know the namespaces. Pages is in the App\Controllers namespace. Book is not given one, so it will exist in the global namespace at \Book. Your Books.php (names of files usually match the class they contain, so would be Book.php) should include a namespace declaration. I suggest namepsace App\Models;. You could also change your use statement to use \Book.

    Notice you don't need to alias it. It's the only Book class you're using so just as you did with Request the class can be referenced by the last segment of it's fully namespaced designation.