Slim: Class ‘X’ Not Found

PROBLEM

Let’s assume we have the following project structure with src/model/Person.php created…

.
├── composer.json
├── composer.lock
├── logs
├── public
├── src
│   ├── model
│   │   └── Person.php
│   ├── dependencies.php
│   ├── middleware.php
│   ├── routes.php
│   └── settings.php
├── templates
├── tests
└── vendor

… and the class may look something like this…

// src/main/Person.php

class Person
{
    public $name;
    public $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

… and it is being used in other file…

// src/routes.php

use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

When hitting the given route from the browser, we get the following error:-

Type   : Error
Message: Class 'Person' not found
File   : /path/to/app/src/routes.php
Line   : 7

SOLUTION #1: Using import/require

One way to solve this is to use include or require statement:-

// src/routes.php

require 'model/Person.php';

use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

SOLUTION #2: Using autoloading

Another approach is to leverage PSR-4 autoloading.

First, create a namespace in Person.php:-

// src/main/Person.php

namespace App\Model;

class Person
{
    public $name;
    public $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

Second, in the file that consumes that model, specify a use statement to alias that model so it doesn’t need to be fully qualified with the given namespace in order to use it:-

// src/routes.php

use App\Model\Person;
use Slim\Http\Request;
use Slim\Http\Response;

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    $person = new Person('mike', 50);

    // ... do something
    return ...
});

Third, in composer.json, create the autoload block and specify the namespace mapping in it:-

{
  ...
  "autoload": {
    "psr-4": {
      "App\\Model\\": "src/model/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Tests\\": "tests/"
    }
  },
  ...
}

Finally, run composer dump-autoload to regenerate vendor/composer/autoload_psr4.php. This file keeps track the list of classes needed to be included in the project.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s