За последние 24 часа нас посетили 22730 программистов и 1217 роботов. Сейчас ищут 748 программистов ...

Странное поведение PHP - не видит метод

Тема в разделе "PHP для новичков", создана пользователем Schizoid, 17 фев 2018.

Метки:
  1. Schizoid

    Schizoid Новичок

    С нами с:
    19 янв 2018
    Сообщения:
    6
    Симпатии:
    0
    Доброго времени суток. Около года изучаю PHP. Учил по разным видео и книгам. Вот сейчас делаю свой cms-велосипед используя связку PHP7 + MVC, для собственных нужд и для получения практического опыта.

    Есть фронт-контроллер - файл index.php на который перенаправляются все запросы. В нём есть вызов статического метода класса Request. Но PHP наотрез отказывается его вызывать говоря:

    Fatal error: Uncaught Error: Call to undefined method Request::getInstance()

    Сам класс подключается с помощью spl_autoload_register как и многие другие.

    Вот содержимое index.php

    PHP:
    1. // Подключаем файлы системы
    2. define('ROOT', dirname(__FILE__));
    3. require_once(ROOT.'/core/autoload.php');
    4. require_once(ROOT.'/core/helpers.php');
    5. require_once(ROOT.'/core/validators.php');
    6. require_once(ROOT.'/config/config.php');
    7.  
    8. // Запускаем сессию
    9.  
    10. // Проверяем авторизацию
    11. Auth::checkAuth();
    12.  
    13. // Инициализируем ядро
    14. $core = Core::getInstance();
    15.  
    16. // Устанавливаем язык
    17. $core->setLocale();
    18.  
    19. // Запускаем роутинг
    20. $core->run();
    21.  
    22. // Устанавливаем часовой пояс
    23. $core->setTimezone();
    24.  
    25. // Обрабатыаем запросы
    26. Request::getInstance()->capture();
    27.  
    28. // Запускаем контроллер
    29. $core->runController();
    30.  
    31. // Запускаем шаблонизатор
    32. Template::getInstance()->render();

    А вот файл класса Request

    PHP:
    1. <?php
    2.  
    3. class Request
    4. {
    5.     public $post;
    6.     private static $instance;
    7.  
    8.     // Создаем экземпляр объекта
    9.     public static function getInstance()
    10.     {
    11.         self::$instance = self::$instance ?? new self();
    12.         return self::$instance;
    13.     }
    14.  
    15.     private function __clone(){}
    16.     private function __wakeup(){}
    17.     private function __construct(){}
    18.  
    19.     // Принимаем данные из массива $_POST
    20.     public function capture()
    21.     {
    22.         if (empty($_POST)) {
    23.             return;
    24.         }
    25.      
    26.         if (Auth::isLogged()) {
    27.             $this->checkToken();
    28.             return;
    29.         }
    30.      
    31.         $this->post = $_POST;
    32.     }
    33.  
    34.     // Проверяем есть ли в массиве токен
    35.     private function checkToken()
    36.     {
    37.         if (isset($_POST['_token'])) {
    38.             $this->validToken();
    39.             return;
    40.         }
    41.      
    42.         $_POST = null;
    43.      
    44.         Auth::logout();
    45.      
    46.         // Далее следуют вызовы методов записи в лог и оповещение
    47.         // пользователя о подозрительной активности
    48.      
    49.     }
    50.  
    51.     // Валидируем токен
    52.     private function validToken()
    53.     {
    54.         $token = $_POST['_token'];
    55.      
    56.         // Здесь будет проверка токена
    57.         // и в зависимости от результата действие с post
    58.     }
    59.  
    60. }

    При автоподгрузке классов файл подключатся и если из него вывести что-либо через echo то все выводится. Но ни один метод не вызывается как их не именуй. Интересно то, что метод не вызывается если имя класса именно Request. Если поменять его например на Requests то все прекрасно работает.

    И еще, если в файле index.php подключить напрямую файл request.php то тоже все работает.

    Гуру, подскажите, я сколько не читал, вроде это имя не зарезервировано и никаких упоминаний о нем в документации не нашёл. В чём может быть причина такого поведения? Все файлы классов которые которые вызываются из index.php лежат в той же директории что и request.php и прекрасно работают. Спасибо.
     
    #1 Schizoid, 17 фев 2018
    Последнее редактирование: 17 фев 2018
  2. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    Лезь в свой коллбек spl_autoload_register, дампай (феликс, кукусики) итоговый путь файла, сверяй.
    Если на Core::getInstance() не ругается, то дело в файле request.php, который не подключается, ввиду неправильной генерации пути до него.
    --- Добавлено ---
    Если же file_exists вернёт true, то моя не знать. Нужен будет код на руки.
    --- Добавлено ---
    Но, можно настроить xDebug и посмотреть логику выполнения твоего велосипеда. Пошагово.
     
    Schizoid нравится это.
  3. Schizoid

    Schizoid Новичок

    С нами с:
    19 янв 2018
    Сообщения:
    6
    Симпатии:
    0
    В том то и дело, в spl_autoload_register путь формируется правильно. Условие file_exists выполняется и если сделать echo в теле условия то то выдаёт корректный путь.

    Что такое феликс и кукусики не понял. Про xDebug не знал, попробую покурить. Что-то именно с именем класса. Именую класс Pupkin (сам файл и вызов естественно меняю тоже на него же) - все работает.

    И опять же, если в index.php перед вызовом метода подключаю класс напрямую
    PHP:
    1. require_once(ROOT.'/core/request.php');
    - все работает с Request.
     
  4. Schizoid

    Schizoid Новичок

    С нами с:
    19 янв 2018
    Сообщения:
    6
    Симпатии:
    0
    Поставил xDebug, сейчас ошибка выглядит так:
    [​IMG]
    Пока ничего информативного. Ну по крайней мере для меня... Может что нужно подкрутить?

    По большему счёту, конечно я могу просто задать другое имя для класса и все будет работать, но все же, хотелось бы разобраться.
     
  5. Schizoid

    Schizoid Новичок

    С нами с:
    19 янв 2018
    Сообщения:
    6
    Симпатии:
    0
    Проблема относительно решена. Буду разбирать свой код.

    Создал новый index.php. Поместил в него автозагрузчик и создал класс Request в файле request.php по тому же пути что и ранее. Сделал вывод echo из метода - все работает.

    Из этого следует, что проблема в коде. Какая я понять не могу. Куда копать пока не знаю.

    Если попробовать подключать классы по пространствам имён как в фреймворках? Перелопатить придется много, но пока понять откуда растёт проблем не могу.

    Какие идеи, уважаемые форумчане, можете предложить? Как отследить проблему? Исходники могу предоставить.
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Переименуй Request в Hujnane и поправь соответствующий вызов. Будет работать?
     
  7. Schizoid

    Schizoid Новичок

    С нами с:
    19 янв 2018
    Сообщения:
    6
    Симпатии:
    0
    Будет. Но проблема решилась другим способом.

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

    Спасибо за помощь! Abyss спасибо за xDebug. Прошу прощения за нубство, учусь.
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    и опыт сын ошибок трудных, и гений парадоксов друг
    — А.С.Пушкин
    :D