dbms_primeidc/extdbms/lib/Core/Route.php

133 lines
3.7 KiB
PHP

<?php
namespace lib\Core;
use lib\Core\Controller;
abstract class Route
{
private string $_url = "";
protected ?Controller $_controller;
protected string $_method = "";
protected array $_segments = [];
public function __construct(string $url)
{
$this->_url = $url;
$this->init();
}
final public function getURL(): string
{
return $this->_url;
}
private function init(): void
{
$path = parse_url($this->getURL(), PHP_URL_PATH);
$arguments = explode('/', trim($path, '/'));
// 컨트롤러와 메서드를 설정
$this->setController($arguments);
$this->setMethod($arguments);
// 남은 세그먼트를 파라미터로 설정
$this->setSegments($arguments);
}
final protected function getController(): Controller
{
return $this->_controller;
}
protected function routeController(string $route): string
{
return $route;
}
private function setController(array &$segments): void
{
$route = $segments[0] ? $segments[0] : 'HomeController';
// echo $route;
// exit;
$controller = "lib\\Controllers\\" . ucfirst($this->routeController($route));
if (class_exists($controller)) {
$this->_controller = new $controller();
} else {
throw new \Exception("[{$controller}] 해당 Controller를 찾을수 없습니다.");
}
array_shift($segments);
}
final protected function getMethod(): string
{
return $this->_method;
}
protected function routeMethod(string $route): string
{
return $route;
}
final protected function setMethod(array &$segments): void
{
//$segments[0]인이유는 setController에서 $segments를 array_shift했기때문
$route = count($segments) ? $segments[0] : 'index';
// echo $route;
// exit;
$this->_method = strtolower($this->routeMethod($route));
array_shift($segments);
}
final public function getSegments(): array
{
return $this->_segments;
}
final protected function setSegments(array &$segments): void
{
// 세그먼트 배열을 key/value 쌍으로 변환
$params = [];
for ($i = 0; $i < count($segments); $i += 2) {
if (isset($segments[$i + 1])) {
$params[$segments[$i]] = $segments[$i + 1];
}
}
$this->_segments = $params;
}
final public function run(): mixed
{
$controller = $this->getController();
$method = $this->getMethod();
if (!method_exists($controller, $method)) {
throw new \Exception("해당 함수[{$method}]를 " . get_class($this->_controller) . "에서 찾을수 없습니다.");
}
// 컨트롤러에 세그먼트 전달
$controller->setSegments($this->getSegments());
// 키/값 형태로 세그먼트 처리
$params = [];
$segments = $this->getSegments();
// 메서드의 매개변수 정보 가져오기
$reflectionMethod = new \ReflectionMethod($controller, $method);
$parameters = $reflectionMethod->getParameters();
if (count($parameters) > 0) {
// 매개변수가 존재하면 URL 세그먼트를 순서대로 매개변수에 매핑
foreach ($parameters as $i => $param) {
// 매개변수 이름을 가져와서 세그먼트에서 값을 찾기
$paramName = $param->getName();
if (isset($segments[$paramName])) {
$params[] = $segments[$paramName];
} else if (isset($segments[$i])) {
$params[] = $segments[$i];
} else if ($param->isDefaultValueAvailable()) {
$params[] = $param->getDefaultValue();
} else {
$params[] = null;
}
}
} else {
// 매개변수가 없으면 빈 배열 전달
$params = [];
}
return call_user_func_array([$controller, $method], $params);
}
}