leni_m
@leni_m
ЧупаКобрус

Роутинг MVC на php?

Привет тостерята!
У меня есть простая реализация MVC
вот роутер:
<?php

class Router
{
    private $routes;

    public  function __construct()
    {
        $routesPath = ROOT.'/config/routes.php';
        $this->routes = include($routesPath);
    }

    private function getURI ()
    {
        if (!empty($_SERVER['REQUEST_URI'])) {
            return trim($_SERVER['REQUEST_URI'], '/');
        }
    }

    public function run ()
    {
        // Получить строку запроса
        $uri = $this->getURI();

        // Проверить наличие такого запроса в routes.php
        foreach ($this->routes as $uriPattern => $path) {
            // Сравниваем $uriPattern  и $uri
            if (preg_match("~$uriPattern~", $uri)) {

                // Получаем внутренний путь из внешнего согласно правилу
                $internalRoute = preg_replace("~$uriPattern~", $path, $uri);
                // Определить какой контроллер
                // и action обрабатывают запрос

                $segments = explode('/', $internalRoute);

                $controllerName = array_shift($segments).'Controller'; //array_shift выбирает 1-ый елемент и уничтожает его
                $controllerName = ucfirst($controllerName);

                $actionName = 'action'.ucfirst(array_shift($segments));

                $parameters = $segments; //т.к. после 2-ух array_shift останутся одни параметры, они сюда и запишутся

                // Подключить файл класса-контроллера
                $controllerFile = ROOT . '/controllers/' .
                    $controllerName . '.php';

                $internalRoute = preg_replace("~$uriPattern~", $path, $uri);



                if (file_exists($controllerFile)) {
                    include_once ($controllerFile);
                }
                // Создать обьект, вызвать метод (т.е. action)
                $controllerObject = new $controllerName;
                $result = call_user_func_array(array($controllerObject, $actionName), $parameters);
                if ($result != null) {
                    break;
                }
            }
        }
    }
}

в routes.php хранятся пути типа "products" => "site/products",
и получается, что по адресу domen.ru/products будет отрабатывать функция
public static function actionProducts()
{
...
return true;
}

в классе SiteController.php
И вот тут проблема в том, что если написать url отличный от тех, которые в routes.php, то возникает следующая ошибка: "Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'SiteController' does not have a method 'action..."
Я вот не знаю, как реализовать, что если нет такого адреса в routes.php, то отображалась бы 404 страничка например. Или выполнять какой-то код, если нету такого адреса в routes.php
Как тут быть?
  • Вопрос задан
  • 5883 просмотра
Решения вопроса 2
gobananas
@gobananas
finishhim.ru
Просто возьмите klein router или aura router разберите его по кусочкам весь, посмотрите что куда идёт, как почему и вам станет всё понятно.
И ещё ООП роутер != MVC приложение. Можно крутой роутер поставить а дальше наговнокодить.
Ответ написан
Комментировать
Akdmeh
@Akdmeh
PHP, Yii2, Music
Используйте готовые решения, посмотрите Slim, или разберитесь с Symfony. Сэкономьте свое время, не городите лишние велосипеды.
А вообще - просто делайте проверку на существование метода:
php.net/manual/ru/function.method-exists.php
То есть, если метода в искомом классе не существует - перебрасывайте на специальный метод.
Ну и такую же проверку делайте для самого класса.

То есть, добавить как минимум

if (class_exists($controllerName)) {
    $controllerObject = new $controllerName;
    if (method_exists($controllerObject, $actionName)) {
         $result = call_user_func_array(array($controllerObject, $actionName), $parameters);
    } else {
       //load 404 method
    }
} else {
//load 404
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы