Twig\Loader\FilesystemLoader не найден при возникновении ошибки 404

Я новичок в ООП и MVC с PHP, и в настоящее время я учусь, создавая собственное приложение MVC для целей тестирования. Я еще не использую Symfony, но я интегрировал Twig, и у меня есть проблема с ним, когда я вызываю ошибку 404 вне контроллера в двух следующих случаях:

  • Когда запрошенная страница не существует на сервере (например, http://localhost/test/)
  • Когда запрошенный URL-адрес не соответствует существующему контроллеру и методу (например, http://localhost/test/task/)

У меня есть следующая ошибка:

Fatal error: Uncaught Error: Class 'Twig\Loader\FilesystemLoader' not found in /Applications/XAMPP/xamppfiles/htdocs/librairies/Renderer.php:32
Stack trace: #0 /Applications/XAMPP/xamppfiles/htdocs/librairies/Renderer.php(21): Renderer::loadTwig() 
#1 /Applications/XAMPP/xamppfiles/htdocs/librairies/Http.php(26): Renderer::render('errors/404', Array) 
#2 /Applications/XAMPP/xamppfiles/htdocs/librairies/Application.php(35): Http::error404() 
#3 /Applications/XAMPP/xamppfiles/htdocs/index.php(9): Application::process() 
#4 {main} thrown in /Applications/XAMPP/xamppfiles/htdocs/librairies/Renderer.php on line 32

Однако, если я вызываю нужный контроллер с помощью существующего метода, все работает нормально (например, http://localhost/article/show/123). Если я вызываю ошибку 404 внутри метода контроллера (например, если $_GET ID статьи не существует в БД), все тоже работает нормально, и мой шаблон ошибки 404 отображается правильно.

Как вызвать ошибку 404?

Я использую статический метод Http::error404(), который отображает мой шаблон Twig с ошибкой 404.

class Http
{
    /**
     * Display a 404 error - page not found
     *
     * @return void
     */
    public static function error404(): void
    {
        header('HTTP/1.1 404 Not Found');
        $pageTitle = "Erreur 404 - Page non-trouvée";
        Renderer::render('errors/404', compact('pageTitle'));
        exit;
    }
}

Класс приложения

В моем приложении используется мини-маршрутизатор с именем Application. Он проверяет, существуют ли контроллер и вызываемый метод. Если нет, вызовите ошибку 404 с помощью Http::error404(), и именно в этом случае появляется вышеуказанная фатальная ошибка.

class Application
{
    /**
     * This is the app process, called in index.php file.
     * Use controllers and methods directly in URL.
     * URL are rewritten by .htaccess file at app root.
     *
     * Usage :    https://example.com/controller/task/{optionnal_parameter}
     *            Ex : https://example.com/article/show/145
     *
     * @return void
     */
    public static function process()
    {
        // By default, call homepage
        $controllerName = 'ArticleController';
        $task = 'home';

        if (!empty($_GET['controller'])) {
            $controllerName = ucfirst($_GET['controller'] . 'controller');
        }

        if (!empty($_GET['task'])) {
            $task = $_GET['task'];
        }

        $controllerPath = "\controllers\\" . $controllerName;

        // Check if this controller & method exists
        if (!method_exists($controllerPath, $task)) {
            Http::error404(); // <-- Here, i'm not in a controller (line 35)
        }

        $controller = new $controllerPath();
        $controller->$task();
    }
}

Здесь есть странная вещь: если я определяю какой-либо контроллер перед вызовом ошибки 404, все работает так, как я хотел, и мой шаблон ошибки 404 отображается правильно. Но это не чистое и элегантное решение...

        // Check if this controller & method exists
        if (!method_exists($controllerPath, $task)) {
            new \Controllers\ArticleController(); // <-- Not clean, but solve my fatal error
            Http::error404();
        }

То же самое происходит в моем 404.php файле, который вызывается сервером и объявляется в .htaccess, когда файл вызывается, а он не существует. Мой файл 404 PHP содержит всего несколько строк:

require_once 'librairies/autoload.php';

Http::error404();

Если я определяю какой-либо контроллер, он работает отлично, и фатальная ошибка исчезает.

require_once 'librairies/autoload.php';

new Controllers\ArticleController();
Http::error404();

Класс рендеринга

Это мой класс рендеринга. В этом файле появляется фатальная ошибка, как показано в строке 32 ниже, когда класс Http с методом error404 отображает ошибки/шаблон Twig 404.

require_once 'librairies/autoload.php';

use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFunction;

class Renderer
{
    /**
     * Print a HTML template with $var injection
     *
     * @param string $path
     * @param array $var
     */
    public static function render(string $path, $var = [])
    {
        $template = self::loadTwig()->load("$path.html.twig");
        echo $template->display($var);
    }

    /**
     * Load Twig
     *
     * @return Environment
     */
    public static function loadTwig()
    {
        $loader = new FilesystemLoader('templates'); // <-- Line 32 is here !

        $twig = new Environment($loader, [
            'auto_reload' => true,
            'autoescape' => 'html'
        ]);
        $twig->addFunction(
            new TwigFunction('notificationDisplay', function() { return Notification::display(); })
        );
        return $twig;
    }
}

Я добавил только код, который, как мне кажется, связан с моей проблемой. Не стесняйтесь спрашивать, есть ли какие-то моменты, которые необходимо уточнить.

Я искал решение этой ошибки в течение семи дней и не нашел решения. Ваша помощь - моя последняя надежда. Большое спасибо!

Зачем вам автозагрузчик во всех файлах? Вы проверили, может ли автозагрузчик найти данный класс?

Nico Haase 17.03.2022 10:34

Вы уверены, что twig загружается в require_once 'librairies/autoload.php';? Does the controller ArticleController`, загружая какие-либо дополнительные зависимости?

DarkBee 17.03.2022 10:35

@NicoHaase Это, безусловно, ошибка с моей стороны, плохая практика. Каково правило включения автозагрузчика? Должен ли я добавить его только в файл index.php?

Loraga 17.03.2022 10:43

@DarkBee Да, мой собственный автозагрузчик зарегистрирован в файле composer.json. Мое приложение использует только две зависимости: Twig и PHP Mailer, и все работает нормально, мои шаблоны Twig правильно загружаются и отображаются, за исключением случая этой ошибки 404...

Loraga 17.03.2022 10:47

Обычно это нужно только один раз. Кроме того, что вы пытались проверить, почему ошибка не возникает при загрузке любого дополнительного контроллера?

Nico Haase 17.03.2022 10:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
48
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я удалил весь ненужный require_once автозагрузчик в файлах приложения и оставил только один в index.php, как указал @NicoHaase.

С этого момента Twig больше не обнаруживается, и при всех запросах появляется одно и то же сообщение об ошибке!

Решение было легко найти: в моем файле index.php я использовал неправильный автозагрузчик. Я вызывал свой пользовательский автозагрузчик вместо того, который был в Composer...

Я просто меняю:

require_once 'librairies/autoload.php';

\Application::process();

К :

require_once 'vendor/autoload.php';

\Application::process();

И теперь все работает нормально! Спасибо @NicoHaase и @DarkBee за то, что направили меня на правильный путь!

Другие вопросы по теме