Reputation: 21
Class 'LoginController' not found, I load all my Controllers using PSR-4 autoloading.
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
In here, when ever I need to call methods on controllers I simply find the class, create a new instance of that class and then call the method on the class I just created.
if (!isset($result['error'])) {
$handler = $result['handler'];
$class = $handler[0];
$class = substr($class, strrpos($class, '\\') + 1);
$class = new $class();
$method = $handler[1];
var_dump($class); // it doesn't get this far
$class->$method();
}
For some reason, the $class = new $class();
line is throwing that LoginController.php
cannot be found, but I'm sure that PSR-4 autoloader was meant to auto load it in?
<?php declare(strict_types = 1);
namespace App\Controllers\Frontend\Guest;
class LoginController
{
public function getView()
{
echo 'it worked?';
}
}
The path to LoginController is /app/Controllers/Frontend/Guest/LoginController.php
I am declaring my routes like so,
$router->get('/', ['App\Controllers\Frontend\Guest\LoginController', 'getView']);
Upvotes: 1
Views: 876
Reputation: 46602
Some changes, to make it work.
Not important but also not required is the / slash in the psr-4
{
"require": {
"baryshev/tree-route": "^2.0.0"
}
"autoload": {
"psr-4": {
"App\\": "app"
}
}
}
I don't see require 'vendor/autoload.php';
which you need to include so composer can autoload your classes/packages.
Ok presuming that's in there, the following code is essentially basename'ing the namespace, which you don't want to do, as you need the namespace as part of the class name for composer to autoload it:
$class = $handler[0];
$class = substr($class, strrpos($class, '\\') + 1);
$class = new $class();
Instead just use the full value of $result['handler'][0]
.
Also, you should check that both the class exists and that the method exists in that class so you can handle any errors because a route matches but does not exist in your code. (that router does not check if the class exists).
So a working example:
<?php
require 'vendor/autoload.php';
$router = new \TreeRoute\Router();
$router->addRoute(['GET', 'POST'], '/', ['App\Controllers\Frontend\Guest\LoginController', 'getView']);
$method = $_SERVER['REQUEST_METHOD'];
$url = $_SERVER['REQUEST_URI'];
$result = $router->dispatch($method, $url);
if (!isset($result['error'])) {
// check controller
if (class_exists($result['handler'][0])) {
$class = $result['handler'][0];
$class = new $class();
// check method
if (method_exists($class, $result['handler'][1])) {
$class->{$result['handler'][1]}($result['params']);
} else {
// method not found, do something
}
} else {
// controller not found, do something
}
}
else {
switch ($result['error']['code']) {
case 404 :
echo 'Not found handler here...';
break;
case 405 :
$allowedMethods = $result['allowed'];
if ($method == 'OPTIONS') {
echo 'OPTIONS method handler here...';
}
else {
echo 'Method not allowed handler here...';
}
break;
}
}
This was tested and working with the following filesystem structure which you have also noted in your question if it's not the same, it won't work.
No change to LoginController.php
that works fine.
Result:
it worked?
Upvotes: 2