PHP/Modern PHP

[PHP] 게시판 만들기 with MVC - 2부 Routing

DSeung 2023. 12. 26. 22:41

 

이전글 : [PHP] 게시판 만들기 with MVC - 1부 Migration

 

.htaccess 분석하기 

이전 포스팅에서 만들었던 .htaccess의 내용은 다음과 같습니다.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /bbs
    RewriteCond %{REQUEST_FILENAME} !^/view/404\.php
    RewriteCond %{REQUEST_URI} !^/bbs/assets/
    RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>

 

-  RewriteCond %{REQUEST_FILENAME} !^/view/404\.php
-  RewriteCond %{REQUEST_URI} !^/bbs/assets/

 

파일 이름이 view/404.php나 요청 주소가 /bbs/assets/로 시작하는 게 아닌 파일은 전부 아래 규칙을 통해

- RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

 

index.php로 이동되며 기존 주소는 url 파라미터로 가게 됩니다.

추가적으로 같이 요청되었던 GET이나 POST 요청들 또한 그대로 index.php에 요청되게 됩니다.

이렇게 함으로써 진입점이 없던 php에 진입점을 만들 수 있게 됩니다.

 

Routing

Routing 파일을 만들 것입니다.

지금 만들 Routing의 구조는 아래와 같습니다.

index.php -> Route -> View or Controller 순으로 작동하게 됩니다. Controller는 추후에 나오는데 전형적인 웹 사이트의 백엔드 기능을 담는다고 생각하면 됩니다. Route는 index로 온 요청을 어디로 보내면 적당할지 정해줍니다.

 

예를 들어 localhost/bbs/post/list로 요청이 들어오면 list를 담당하는 view를 보여주는 것이고 글을 생성한다면 PostController에서 글 생성 코드를 실행한 다음 결과하면을 다시 view로 보여주는 것이죠.

 

이제 진입점인 index.php를 만듭시다, 아직 PostRoute 파일이 없으므로 에러가 발생할 겁니다.

bootstrap.php을 포함시켜 php에서 namespace를 autoload 해주게 합시다.

※ 만약 composer.json을 수정했을 경우 다시 composer install을 하거나 composer dump-autoload 실행

 

bbs/index.php

<?php
require_once "bootstrap.php";

use Route\PostRoute;

// URL 요청
$url = isset($_GET['url']) ? $_GET['url'] : '/';

// 루트 경로로 접근 시 게시글 목록으로 리다이렉트
if ($url == '/' || $url == '') {
    header('Location: post/list');
} else {
    $routes = array();
    $routes[] = new PostRoute();

    $ok = false;
    foreach ($routes as $route) {
        // routing 함수를 돌며 false 리턴하는 게 있다면 404 페이지 출력
        $ok = $route->routing($url);
        if ($ok) {
            break;
        }
    }

    // 404 페이지 출력
    if (!$ok) {
        header("HTTP/1.0 404 Not Found");
        require_once "view/404.php";
    }
}

 

 

우선 Route 파일들에서 사용할 함수를 Trait로 선업 합시다.

Trait는 쉽게 class에 포함시켜서 $this를 통해 쉽게 사용할 수 있습니다

bbs/Utils/RouteUtils.php

<?php

namespace Utils;

trait RouteUtils{
    // URL 요청이 해당 경로와 메소드와 일치하는지 확인
    public function routeCheck($origin, $path, $method): bool
    {
        return strpos($origin, $path) !== false
            && $_SERVER['REQUEST_METHOD'] == $method;
    }

    // 뷰 파일을 require 해줌
    public function requireView($viewName): bool
    {
        require_once(__DIR__ . '/../view/' . $viewName . '.php');
        return true;
    }
}

 

Route 파일을 만듭시다

index.php에서 모든 Route를 하나의 반복문으로 실행할 것이기에 

부모가 될 BaseRoute.php를 선언해서 이걸 상속받게 함으로 반복문이 실행 가능하게 합시다.

bbs/Route/BaseRoute.php

<?php

namespace Route;

use Utils\RouteUtils;

abstract class BaseRoute
{
    use RouteUtils;

    abstract function routing($url): bool;
}

 

이제 라우팅 파일은 만들었습니다, 하지만 view 페이지가 빠졌죠

bbs/Route/PostRoute.php

<?php

namespace Route;

class PostRoute extends BaseRoute
{
    function routing($url): bool
    {
        // 게시글 목록에 대한 라우팅
        if ($this->routeCheck($url, "post/list", "GET")) {
            return $this->requireView('index');
        } else {
            return false;
        }
    }
}

 

View

이제 화면에서 보여줄 View 페이지를 만듭시다.

index는 나중에 수정할 것이므로 간단하게 합니다.

bbs/view/index.php

index

 

bbs/view/404.php

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>404 Not Found</title>
</head>
<body>
<h1>404 Not Found</h1>
<p>죄송합니다. 찾으시는 페이지는 사용할 수 없거나 존재하지 않을 수 있습니다.</p>
</body>
</html>

 

다음 view 파일부터 포함시킬 header를 만들어줍시다.

이번 포스팅에서의 스타일은 부트스트랩으로 해결하고 아이콘은 구글 아이콘을 사용합니다.

bbs/view/part/header.php

<head>
    <meta charset="UTF-8">
    <title>게시판</title>
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
          integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>

 

결과

여기까지 하셨다면

http://localhost/bbs로 접근 시 http://localhost/bbs/post/list로 이동되며 파일 내용은 index가 나옵니다.

만약 다른 주소를 입력할 경우 아래처럼 나오게 될 것입니다.

 

반응형