php composer autoload и имя класса в переменной (класс не найден)

Вопрос или проблема

Я подхожу к программе с использованием MVC, автозагрузки и composer… вероятно, есть что-то, что ускользает от меня. Когда я открываю корень моего сайта (www.mysite.com), он должен вызывать метод index класса UserController, но, к сожалению, этого не происходит, и я получаю ошибку (строка 25 — это там, где я делаю $class=new $controller() в Router.php):

Фатальная ошибка: Необработанная ошибка: Класс "UserController" не найден в /Users/denis/Herd/ctf/App/Core/Router.php на строке 25

Ошибка: Класс "UserController" не найден в /Users/denis/Herd/ctf/App/Core/Router.php на строке 25

Я также пробовал сделать $class = new $controller, но ничего не изменилось… Если вместо этого я делаю $class = new UserController(); всё работает нормально… так что я предполагаю, что автозагрузка работает при написании имени класса, но не в переменной…

Структура папок:

\App\
    Controllers\
        UserController.php
    Core\
        Controller.php
        Router.php
    routes.php
    
\Public\
    index.php

\composer.json

composer.json:

"autoload": {
  "psr-4": {
    "App\\": "App/"
  }
}

index.php:

use App\Controllers\UserController;

require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../config.php';

App\Core\Router::route();

Router.php:

namespace App\Core;

use App\Controllers;

class Router{
   public static function route(){
      require __DIR__ . '/../routes.php';

      $request = trim($_SERVER['REQUEST_URI']);

      if (array_key_exists($request, routes)) {
         $controller = routes[$request][0];
         $method = routes[$request][1];

         if (file_exists(BASE_PATH . '/App/Controllers/' . $controller . '.php')) {
            //$a = new UserController();    <-- Работает!!!
            $class = new $controller(); 
            if (method_exists($controller, $method)) {
               $class->$method();
               exit;
            }
         }
      }
    // Не найдено
   }
}

routes.php:

const routes = array(
   "https://stackoverflow.com/"             => array('UserController', 'index'),
   ...
);

UserController.php:

namespace App\Controllers;

use App\Core\Controller;

Class UserController extends Controller{

   public function index(){
    ...
   }
}

Controller.php:

namespace App\Core;
use Smarty\Smarty;

Class Controller{
   public function __construct(){
      session_start();
      error_reporting(E_ALL);

      $smarty = new Smarty();
      $smarty->setTemplateDir(BASE_PATH.'/templates')
         ->setCompileDir(BASE_PATH.'/templates_c')
         ->setCacheDir(BASE_PATH.'/cache');
      ini_set('display_errors', 'On');

      $smarty->assign('APP_TITLE', APP_TITLE);
   }
}

Ответ или решение

Проблема, с которой вы столкнулись, связана с тем, как PHP обрабатывает пространства имен и класс при создании экземпляров классов. Ошибка Fatal error: Uncaught Error: Class "UserController" not found возникает из-за того, что при вызове new $controller() PHP не может найти класс UserController, потому что в этом случае не учитывается пространство имен.

Решение

Вам нужно убедиться, что вы правильно указываете пространство имен при создании экземпляра класса UserController. Чтобы это сделать, вы можете использовать конструкцию, которая позволяет динамически использовать пространство имен. Вот несколько способов решить вашу проблему.

1. Полное пространство имен

Если вы хотите продолжать использовать переменную для создания объектов, вам нужно указать полное пространство имен класса. Обновите строку, где создается экземпляр класса в Router.php, следующим образом:

namespace App\Core;

use App\Controllers;

class Router {
   public static function route() {
      require __DIR__ . '/../routes.php';

      $request = trim($_SERVER['REQUEST_URI']);

      if (array_key_exists($request, routes)) {
         $controller = routes[$request][0];
         $method = routes[$request][1];

         // Добавляем пространство имен к контроллеру
         $fullClassName = "App\\Controllers\\$controller";

         if (class_exists($fullClassName) && file_exists(BASE_PATH . '/App/Controllers/' . $controller . '.php')) {
            $class = new $fullClassName(); 
            if (method_exists($class, $method)) {
               $class->$method();
               exit;
            }
         }
      }
      // Если не найдено
   }
}

2. Проверка наличия класса

Также убедитесь, что вы проверяете существование класса перед его созданием. В этом примере используется class_exists($fullClassName) для проверки, существует ли класс перед его созданием.

3. Структура маршрута

Убедитесь, что ваши маршруты определены правильно и указывают на контроллеры в именно тех пространствах имен, которые вы определили.

routes.php:

const routes = array(
   "/" => array('UserController', 'index'),
   // Другие маршруты...
);

Заключение

Используя правильное пространство имен и проверяя его наличие, вы сможете избежать проблемы с классом "не найден". После внесения изменений у вас все должно заработать правильно. Теперь вы можете динамически загружать свои контроллеры без ошибок.

Оцените материал
Добавить комментарий

Капча загружается...