Как передать контроллер другими способами, чем URL в PHP MVC
Я понимаю, что это может быть глупый вопрос, но я борюсь с собственным проектом MVC, который я начал для изучения PHP, и я не смог найти то, что искал где-либо еще.
Мой вопрос заключается в том, как передать контроллер на маршрутизатор таким образом, чтобы не использовать URL. Как бы я сделал так, чтобы href в моих ссылочных тегах предоставлял только категорию и идентификатор и все же заставлял это работать. На данный момент мои URL выглядят так:
сайт / контроллер / метод / арг
пример: сайт / статьи / пост /13
Я хочу, чтобы URL был похож на:
сайт / категория / Ид или-слизня от титула
Я был бы очень признателен за помощь, так как она беспокоит меня уже неделю. Заранее спасибо.
1 ответ
Что ж, было бы сложно описать возможные шаги в разделе комментариев, поэтому я добавлю ответ.
Следующие шаги будут примерными, и они не описывают весь процесс. Я опущу некоторые детали
Предполагая, что вы пытаетесь реализовать MVC, у вас должен быть какой-то файл bootstrap.php (или что-то подобное)
Итак, давайте создадим наш класс маршрутизатора
/** * 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; }
}
Итак, в bootstrap.php вам просто нужно сделать звонок
Router::getInstance()->run()
Статический маршрут будет пытаться передать ваши параметры
Для динамических маршрутов вы всегда можете прочитать аргументы из $ _REQUEST
PS По правде говоря, это вырезанный пример из моего старого проекта.