_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, '/')); // var_dump($arguments); //컨트롤러와 메서드를 설정 $this->setModule($arguments); $this->setController($arguments); $this->setMethod($arguments); // 남은 세그먼트를 파라미터로 설정 $this->setSegments($arguments); } protected function routeModule(string $route): string { return $route; } protected function routeController(string $route): string { return ucfirst($route . 'Controller'); } protected function routeMethod(string $route): string { return $route; } final protected function getModule(): string { return $this->_module; } private function setModule(array &$segments): void { $route = count($segments) ? $segments[0] : ''; $route = $this->routeModule($route); $module = "lib\\Controllers\\" . $route; if (is_dir(ROOT_PATH . DIRECTORY_SEPARATOR . $module)) { array_shift($segments); $this->_module = $module . DIRECTORY_SEPARATOR; } } final protected function getController(): Controller { return $this->_controller; } private function setController(array &$segments): void { $route = count($segments) ? $segments[0] : 'Home'; $route = $this->routeController($route); $controller = $this->getModule() . $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; } final protected function setMethod(array &$segments): void { //$segments[0]인이유는 setController에서 $segments를 array_shift했기때문 $route = count($segments) ? $segments[0] : 'index'; // echo "METHOD:{$route}\n"; $method = $this->routeMethod($route); // echo get_class($this->getController()) . ",METHOD2:{$method}\n"; if (method_exists($this->getController(), $method)) { array_shift($segments); } else { throw new \Exception("해당 함수[{$method}]를 " . get_class($this->getController()) . "에서 찾을수 없습니다."); } $this->_method = $method; } 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(); // 컨트롤러에 세그먼트 전달 $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); } }