-
[PHP] CodeIgniter4 Controllers 알아보기Programming/프로그래밍 2021. 5. 1. 21:32
CodeIgniter 4.1.1 의 컨트롤러 분석
심심해서 해보는 거라 그냥 참고만 하면 될 듯 싶다.
하지만 피드백을 주신다면 항상 감사합니다.
코드이그나이터는 컴포저로 파일을 받아와서
rewrite.php를 시작으로 index.php 를 불러온다.
index.php
// Valid PHP Version? $minPHPVersion = '7.3'; if (version_compare(PHP_VERSION, $minPHPVersion, '<')) { die("Your PHP version must be {$minPHPVersion} or higher to run CodeIgniter. Current version: " . PHP_VERSION); } unset($minPHPVersion); // Path to the front controller (this file) define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR); /* *--------------------------------------------------------------- * BOOTSTRAP THE APPLICATION *--------------------------------------------------------------- * This process sets up the path constants, loads and registers * our autoloader, along with Composer's, loads our constants * and fires up an environment-specific bootstrapping. */ // Ensure the current directory is pointing to the front controller's directory chdir(__DIR__); // Load our paths config file // This is the line that might need to be changed, depending on your folder structure. require realpath(FCPATH . '../app/Config/Paths.php') ?: FCPATH . '../app/Config/Paths.php'; // ^^^ Change this if you move your application folder $paths = new Config\Paths(); // Location of the framework bootstrap file. $bootstrap = rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; $app = require realpath($bootstrap) ?: $bootstrap; /* *--------------------------------------------------------------- * LAUNCH THE APPLICATION *--------------------------------------------------------------- * Now that everything is setup, it's time to actually fire * up the engines and make this app do its thang. */ $app->run();
public/index.php의 모든 부분이고 상세한 건 더 봐야겠지만 여기서부터 $app->run() 부분에서 실제 어플리케이션이 시작되는 것 같다.
$app->run()의 내부로 들어가게 되면
아래와 같은 코드들을 확인할 수 있는데 꽤 알기좋게 잘 만들어져 있어서 확인이 편하다.
run 함수 내부
public function run(RouteCollectionInterface $routes = null, bool $returnResponse = false) { $this->startBenchmark(); $this->getRequestObject(); $this->getResponseObject(); $this->forceSecureAccess(); $this->spoofRequestMethod(); Events::trigger('pre_system'); // Check for a cached page. Execution will stop // if the page has been cached. $cacheConfig = new Cache(); $response = $this->displayCache($cacheConfig); if ($response instanceof ResponseInterface) { if ($returnResponse) { return $response; } $this->response->pretend($this->useSafeOutput)->send(); $this->callExit(EXIT_SUCCESS); } try { return $this->handleRequest($routes, $cacheConfig, $returnResponse); } catch (RedirectException $e) { $logger = Services::logger(); $logger->info('REDIRECTED ROUTE at ' . $e->getMessage()); // If the route is a 'redirect' route, it throws // the exception with the $to as the message $this->response->redirect(base_url($e->getMessage()), 'auto', $e->getCode()); $this->sendResponse(); $this->callExit(EXIT_SUCCESS); } catch (PageNotFoundException $e) { $this->display404errors($e); } }
run()의 함수 내부 구조이고 위치는 vendor 폴더에서 codeigniter4/framework/system/Codeigniter.php 에서 확인할 수 있다.
return $this->handleRequest($routes, $cacheConfig, $returnResponse);
위 코드블록에서 handleRequest로 들어가면 컨트롤러가 어떻게 만들어져 있는지 확인할 수 있는데,
그전에 tryToRouteIt함수를 통해서 라우팅 과정도 확인할 수 있었다.
handleRequest 함수 내부
protected function handleRequest(?RouteCollectionInterface $routes, Cache $cacheConfig, bool $returnResponse = false) { $routeFilter = $this->tryToRouteIt($routes); // Run "before" filters $filters = Services::filters(); // If any filters were specified within the routes file, // we need to ensure it's active for the current request if (! is_null($routeFilter)) { $filters->enableFilter($routeFilter, 'before'); $filters->enableFilter($routeFilter, 'after'); } $uri = $this->request instanceof CLIRequest ? $this->request->getPath() : $this->request->getUri()->getPath(); // Never run filters when running through Spark cli if (! defined('SPARKED')) { $possibleResponse = $filters->run($uri, 'before'); // If a ResponseInterface instance is returned then send it back to the client and stop if ($possibleResponse instanceof ResponseInterface) { return $returnResponse ? $possibleResponse : $possibleResponse->pretend($this->useSafeOutput)->send(); } if ($possibleResponse instanceof Request) { $this->request = $possibleResponse; } } $returned = $this->startController(); // Closure controller has run in startController(). if (! is_callable($this->controller)) { $controller = $this->createController(); if (! method_exists($controller, '_remap') && ! is_callable([$controller, $this->method], false)) { throw PageNotFoundException::forMethodNotFound($this->method); } // Is there a "post_controller_constructor" event? Events::trigger('post_controller_constructor'); $returned = $this->runController($controller); } else { $this->benchmark->stop('controller_constructor'); $this->benchmark->stop('controller'); } // If $returned is a string, then the controller output something, // probably a view, instead of echoing it directly. Send it along // so it can be used with the output. $this->gatherOutput($cacheConfig, $returned); // Never run filters when running through Spark cli if (! defined('SPARKED')) { $filters->setResponse($this->response); // Run "after" filters $response = $filters->run($uri, 'after'); } else { $response = $this->response; // Set response code for CLI command failures if (is_numeric($returned) || $returned === false) { $response->setStatusCode(400); } } if ($response instanceof ResponseInterface) { $this->response = $response; } // Save our current URI as the previous URI in the session // for safer, more accurate use with `previous_url()` helper function. $this->storePreviousURL((string) current_url(true)); unset($uri); if (! $returnResponse) { $this->sendResponse(); } //-------------------------------------------------------------------- // Is there a post-system event? //-------------------------------------------------------------------- Events::trigger('post_system'); return $this->response; }
여기서 아래 코드에서 컨트롤러가 실행되는 코드인데,
$returned = $this->runController($controller);
runController 함수 내부
protected function runController($class) { // If this is a console request then use the input segments as parameters $params = defined('SPARKED') ? $this->request->getSegments() : $this->router->params(); // @phpstan-ignore-line if (method_exists($class, '_remap')) { $output = $class->_remap($this->method, ...$params); } else { $output = $class->{$this->method}(...$params); } $this->benchmark->stop('controller'); return $output; }
$output 변수가 있는 라인줄에서 개발자가 만들어놓은 컨트롤러 클래스의 함수로 접근하고 있는 것을 확인할 수 있었다.
위와 같은 과정은 Xdebug에서 callStack을 확인하면 알 수 있으므로 알아보면 된다.
버전이 바뀌면 위 코드 과정은 비슷하겠지만 코드들은 바뀔 수 있으므로 어떻게 동작하는지만 확인하면 좋을 것 같다.
반응형'Programming > 프로그래밍' 카테고리의 다른 글
[PHP7] VSCode XDebug 사용 (0) 2021.01.15 [C#] .Net Core / .Net Framework 차이 (0) 2020.12.15 [Python] 함수 (0) 2020.10.01 [Python] 데이터형 (0) 2020.09.23 [PHP] 표준 권고 ( PSR ) (0) 2020.09.07