class Router {
private $routes;
public function __construct(){
$routerPath = ROOT.'/routing/routes.php';
$this->routes = include($routerPath);
}
private function getURI(){
if(!empty($_SERVER['REQUEST_URI'])){
return trim($_SERVER['REQUEST_URI'], '/');
}
}
public function Run(){
$uri = $this->getURI();
if(!array_key_exists($uri, $this->routes)){
echo "Такой старницы нет!";
//Перенаправить на 404.
exit();
}
foreach($this->routes as $pattern=>$path){
if($pattern == $uri){
$controllerAndAction = explode('/',$path);
//Узнаем имя контроллера и экшена:
$controllerName = $controllerAndAction[0];
$actionName = $controllerAndAction[1];
//Назначаем имена файлу контроллера:
$controllerFileName = $controllerName . 'Controller.php';
//Подключаем файл контроллера:
include ROOT . '/controllers/'.$controllerFileName;
//Создаем класс контроллера:
$controllerObject = new $controllerName;
//Вызываем метод класса контроллера:
$result = $controllerObject->$actionName();
}
}
}
}
?>
как лучше всего реализовать и использовать не готовый контроллер, а свой собственный.- я тебе показал код простейшего роутера который пишется по памяти в блокноте в перерыве на обед. Там даже параметры экшена не определяются, только сам контроллер и метод.
Где же не говнокод? Как писать правильно? Писать правильно без модных фреймворков вообще возможно?
Я пользовался Laravel, пользовался Yii, даже просматривал какую-то часть их исходного кода.
use FastRoute\Dispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
//$container - использование любого контейнера
**
* Routes
*/
$dispatcher = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $r) {
$routes = require __DIR__ . '/routes.php';
foreach ($routes as $route) {
$r->addRoute($route[0], $route[1], $route[2]);
}
});
/**
* Dispatch
*/
$request = Request::createFromGlobals();
$route_info = $dispatcher->dispatch($request->getMethod(), $request->getPathInfo());
switch ($route_info[0]) {
case Dispatcher::NOT_FOUND:
Response::create("404 Not Found", Response::HTTP_NOT_FOUND)->send();
break;
case Dispatcher::METHOD_NOT_ALLOWED:
Response::create("405 Method Not Allowed", Response::HTTP_METHOD_NOT_ALLOWED)->send();
break;
case Dispatcher::FOUND:
$class_name = $route_info[1][0];
$method = $route_info[1][1];
$vars = $route_info[2];
$object = $container->get($class_name);
$response = $object->$method($vars);
if ($response instanceof Response) {
$response->prepare(Request::createFromGlobals());
$response->send();
}
break;
}
$invoker = new Invoker\Invoker(null, $container);
$callable = $route_info[1];
$vars = $route_info[2];
$response = $invoker->call($callable, $vars);
class Controller
{
public function __construct(FooService $fooService)
{
}
public function __invoke(BarService $barService, $id)
{
}
}
$invoker->call('Controller::__invoke', [
'id' => 'id',
]);
FooService
, но не BarService
$container
->inflector('LoggerAwareInterface')
->invokeMethod('setLogger', ['Acme\Logger']) // Acme\Logger will be resolved via the container
;
Controller
(FooService
будет заинжектен в него, тут все как обычно)__invoke
у полученного объекта, передав туда все нужные параметрыBarService
будет вытащен из контейнераid
возьмется из переданных параметров$response = $invoker->call(/**/)
setLogger
, во-вторых, передать туда какие-то свои параметры, которые пришли из реквеста.