Как передать контроллер другими способами, чем URL в PHP MVC

Я понимаю, что это может быть глупый вопрос, но я борюсь с собственным проектом MVC, который я начал для изучения PHP, и я не смог найти то, что искал где-либо еще.

Мой вопрос заключается в том, как передать контроллер на маршрутизатор таким образом, чтобы не использовать URL. Как бы я сделал так, чтобы href в моих ссылочных тегах предоставлял только категорию и идентификатор и все же заставлял это работать. На данный момент мои URL выглядят так:

сайт / контроллер / метод / арг

пример: сайт / статьи / пост /13

Я хочу, чтобы URL был похож на:

сайт / категория / Ид или-слизня от титула

Я был бы очень признателен за помощь, так как она беспокоит меня уже неделю. Заранее спасибо.

1 ответ

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

Следующие шаги будут примерными, и они не описывают весь процесс. Я опущу некоторые детали

  1. Предполагая, что вы пытаетесь реализовать MVC, у вас должен быть какой-то файл bootstrap.php (или что-то подобное)

  2. Итак, давайте создадим наш класс маршрутизатора

    /**
     * Current method
     * @var string
     */
    protected $method;
    
    /**
     * Current args
     * @var unknown
     */
    protected $args = array();  
    
    private static $instance;
    
    /**
     * That's how we retrieve class instance
     * @return app_router_http
     */
    public static function getInstance()
    {
        if (!isset(static::$instance))
        {
            static::$instance = new self;
        }
    
        return static::$instance;
    }
    
    private function __clone() {}
    
    /**
     * @throws app_exception
     */
    private function __construct()
    {
        /* парсим текущий урл */
        $url = parse_url (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : "/", PHP_URL_PATH);
    
        $url = preg_replace("/\\/{2,}/i", "/", $url);
    
        /* Let's retrieve static route (for example - /category/id-or-slug-from-title) */
        if ($_route = $this->getStaticRoute($url))
        {
            if ($_route->hasErrors())
            {
                throw new app_exception($_route->getErrors(";"));
            }
            $this
                ->setController($_route->getController())
                ->setMethod($_route->getMethod())
                ->setArgs($_route->getArgs() ? $_route->getArgs() : null)
            ;
    
            return;
        }
    
        /* Let's retrive dynamic route, because we didn't fing static */
        if ($_route = $this->getDynamicRoute($url))
        {
            if ($_route->hasErrors())
            {
                throw new app_exception($_route->getErrors(";"));
            }
    
            $this
                ->setController($_route->getController())
                ->setMethod($_route->getMethod())
                ->setArgs($_route->getArgs() ? $_route->getArgs() : null);
    
            return;
        }
    
        throw new app_exception("Can't found any route objects", 503);
    }
    
    /**
     * @param string $controller
     * @return Router
     */
    public function setController($controller)
    {
        $this->controller = $controller;
        return $this;
    }
    
    /**
     * @return string
     */
    public function getController()
    {
        return $this->controller;
    }
    
    /**
     * @param string $method
     * @return Router
     */
    public function setMethod($method)
    {
        $this->method = $method;
        return $this;
    }
    
    /**
     * @return string
     */
    public function getMethod()
    {
        return $this->method;
    }
    
    /**
     * @param array $args
     * @return Router
     */
    public function setArgs(array $args = null)
    {
        if (isset($args))
        {
            $this->args = $args;
        }
        return $this;
    }
    
    /**
     * @return mixed
     */
    public function getArgs()
    {
        return $this->args;
    }           
    
    /**
     * @param string $route
     * @param string $controller
     * @param string $method
     * @param string $objectId
     * @return Route|NULL
     */
    public function getStaticRoute($route = null, $controller = null, $method = null, $objectId = null)
    {
        $db = new DB(); //Some class for db connections
    
        if (isset($route) && !isset($controller) && !isset($method) && !isset($objectId))
        {
            $selector = "SELECT * FROM `routes` WHERE `route` = '".$db->escape($route)."'";
        }
    
        if (!isset($route) && isset($controller) && isset($method) && isset($objectId))
        {
            $selector = "SELECT * FROM `routes` WHERE `controller` = '".$db->escape($controller)."' && `method` = '".$db->escape($method)."' && `objectId` = '".$db->escape($objectId)."'";
        }
    
        if (!isset($selector))
        {
            throw new app_exception(get_class($this)."::getStaticRoute incorrect params", 503);
        }
    
        if ($db->query($selector)->rows())
        {
            $row = $db->fetch();
    
            $object = new Router();
            $object->setAttributes($row);
    
            if (!$object->hasErrors())
            {
                $object->setController("{$object->getController()}");//Here we are setting our awesome controller
    
                if (!$this->isControllerExist($object->getController()))
                {
                    return $object->addError("Controller {$object->getController()} missing (static route: #{$object->getId()})");
                }
    
                if (!$this->isMethodExist($object->getController(), $object->getMethod()))
                {
                    return $object->addError("Method {$object->getMethod()} missing (controller: {$object->getController()}) (static route: #{$object->getId()})");
                }
    
            }
    
            return $object; 
        }
    
        return null;
    
    }
    
    /**
     * @param string $path
     * @return Router
     */
    public function getDynamicRoute($path)
    {
        $object = new Router;
    
        //Here we will assume that our url looks like this /controller/method/args
    
        /* Url fragments */
        $fragments = explode("/", substr($path, 1));
    
        //Removing trailing slash
        if (!$fragments[sizeof($fragments)-1])
        {
            unset($fragments[sizeof($fragments)-1]);
        }
    
        if (!isset($fragments[0]))
        {
            $fragments[0] = APP_ROUTE_DEFAULT_CONTROLLER; //Some kind of magic constant
        }
    
        $controller = $fragments[0];
    
        if(!class_exists($controller)
        {
            throw new Exception("Ooops, controller not found", 404);
        }
    
        array_shift($fragments); //We don't need controller element anymore
    
    
        for ($i = 0; $i <= 1; $i++)
        {
            if ($i == 0)
            {
                $method = APP_ROUTE_DEFAULT_METHOD;//We also need to handle urls like /news. For example, each controllers has default method index()
            }
            else
            {
                $method = $fragments[0];
            }
    
            if ($this->isControllerExist($controller) && $this->isMethodExist($controller, $method))
            {
                return 
                    $object
                        ->setController($controller)
                        ->setMethod($method);
            }
        }       
    
        return $object->addError("Can't route to <strong>".implode("/", $fragments)."</strong> (dynamic route for module <strong>{$module}</strong>)");
    }
    
    /**
     * @param string $controller
     * @return boolean
     */
    public function isControllerExist($controller = null)
    {
        if (!isset($controller))
        {
            $controller = $this->getController();
        }
    
        return class_exists($controller);
    }
    
    /**
     * @param string $controller
     * @param string $method
     * @return boolean
     */
    public function isMethodExist($controller = null, $method = null)
    {
        if (!isset($controller))
        {
            $controller = $this->getController();
        }
    
        if (!isset($method))
        {
            $method = $this->getMethod();
        }
        return method_exists($controller, $method);
    }
    
    public function run()
    {
        $_str = $this->getController();
        $controller = new $_str;
    
        $return = call_user_func_array(array($controller, $this->getMethod()), $this->getArgs());
    
        return $return;
    }
    

    }

  3. Итак, в bootstrap.php вам просто нужно сделать звонок Router::getInstance()->run()

  4. Статический маршрут будет пытаться передать ваши параметры

  5. Для динамических маршрутов вы всегда можете прочитать аргументы из $ _REQUEST

PS По правде говоря, это вырезанный пример из моего старого проекта.

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