해리의 데브로그

The PHP Practitioner 09 - Router

|

Laracasts - The PHP Practitioner 강의를 듣고 정리한 포스팅 입니다.

1. Router

어플리케이션의 url을 관장하는 역할(Django의 urls.py). 어플리케이션의 구조를 아래와 같이 좀 더 구체화시킴

  • Views: Template의 역할. 브라우저에 보여지는 부분
  • Controllers: router에 따라 연결된 controller를 호출하며 각 controller는 정해진 로직에 따라 views와 연결.
  • Core: Database, boostrap, 추가적인 클래스 정의

routes.php: root directory에 생성. 연습을 위해 “about”, “about-culture”, “contact”, “index” 페이지에 대한 views, controller, routes를 형성함.

1-1. Controllers & views의 예시
// controllers/about.php
<?php

require 'views/about.view.php';

//views/about.php
<body>
<h1>About Us</h1>
</body>

2. Routes.php

<?php

$router->define([
    '' => 'controllers/index.php',
    'about' => 'controllers/about.php',
    'about/culture' => 'controllers/about-culture.php',
    'contact' => 'controllers/contact.php'
]);

//아래와 같이 다양한 방법으로도 표현 가능

//$router->define('', 'controllers/index.php');
//$router->define('about', 'controllers/index.php');
// Router::define('', 'controllers/index.php');
//$router->define('', 'controllers/index.php');

3. core/bootstrap.php

router 관련 로직을 core/Router.phprouter 클래스에서 구현 & bootstrap.php 와 연결

  • Request.php : 서버 내 요청된 URItrim하는 클래스가 구현된 파일
<?php

$app = [];

$app['config'] = require 'config.php';

require 'core/Router.php';
require 'core/Request.php';
require 'core/database/Connection.php';
require 'core/database/QueryBuilder.php';

$app['database'] =  new QueryBuilder(
    Connection::make($app['config']['database'])
);

4. core/Router.php

define : $routes 를 프로퍼티에 저장하는 메서드

load : $fileroutes.php 의미함. routes.php 의 로직에 따라 ($router->define([])) 의 routing값들이 $routes 에 저장됨.

  • load 는 스태틱 메서드이므로 인스턴스를 생성하지 않음. 따라서, new static 또는 new self 를 사용해야함.
  • 인스턴스를 생성하지 않으므로 $this 는 사용이 불가능함. 따라서, new static 이 저장된 $router 을 return 함.

direct : 들어온 URI가 실제로 존재하는지 유무를 프로퍼티와 대조하여 검증함 (array_key_exists) . 존재할 경우, 대응되는 URI를 반환시킴. 존재하지 않을 경우 Throw

<?php

class router
{
    protected $routes = [];

    public static function load($file) // $file: routes.php
    {
        // static method는 인스턴스를 생성하지 않는 global method.
        // 인스턴스 생성을 위해서는 new static (or new self)
        $router = new static;

        require $file;

        // return $this; static method는 인스턴스를 생성하지 않으므로 $this는 사용이 불가능 함.
        return $router;

    }

    public function define($routes)
    {
        $this->routes = $routes;
    }

    public function direct($uri)
    {
        // about/culture
        // 들어온 uri와 매칭되는 key값이 있는지를 routes.php에서 검
        if (array_key_exists($uri, $this->routes)) {
            return $this->routes[$uri];
        }

        // 존재하지 않을 경우 Throw
        throw new Exception('No route defined for this uri');
    }

5. Request.php

<?php

class request
{
    public static function uri()
    {
        return trim($_SERVER['REQUEST_URI'],'/');
    }
}

6. index.php

bootstrap.php 를 호출함으로써, router, request 클래스 등 router에 필요한 모든 로직을 불러올 수 있음.

<?php

require 'core/bootstrap.php';

// option 1.
$router = new Router; // Router 클래스는 bootstrap과 연결되어 있음.
require 'routes.php'; // routes (uri list)를 불러오며 $route(route 인스턴스)의 프러퍼티에 경로 저장.

$uri = trim($_SERVER['REQUEST_URI'],'/'); // URI 경로 trim

require $router->direct($uri); // Router 클래스의 메서드: routes 존재 여부 검사후 redirect.

//die(var_dump($app));


// option 2.
$router = Router::load('routes.php'); 
require $router-> direct($uri);


// option 3.
require Router::load('routes.php')
    ->direct(Request::uri());

Comments