이번 포스팅에서 다룰 내용은 PHP로 간단한 URL Router을 작성해보려고 합니다.
이전 PDO를 이용한 CRUD 코드를 Router을 통해서 간단히 연결해 보겠습니다.
사용된 모든 코드는 스틱코드 포스팅에 업로드 하였습니다.
stickode.com/detail.html?no=1925
라우터에 사용된 코드는
github.com/steampixel/simplePHPRouter/tree/master
에서 참고하였고 일부 수정되었습니다.
php라우팅을 적용하려면 우선 설치된 웹서버 Config파일 세팅이 선행되어야합니다.
설정후에 반드시 웹서버를 재시작 해주세요. https로 redirect 하는 세팅은 따로 적용하셔야합니다.
nginx 의 경우 nginx.conf 파일을 편집해줍니다.
server {
listen 80;
server_name example.com;
index index.php;
root /path/to/public;
location / {
try_files $uri /index.php$is_args$args; ## 이부분을 제외한 다른부분은 각 서버 환경에 맞게 작성
}
location ~ \.php {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
}
}
Apache 의 경우
Apache mod_rewrite모듈이 설치되고 활성화되어 있는지 확인하십시오 . 활성화 mod_rewrite하려면 터미널에 다음 명령을 입력 할 수 있습니다.
sudo a2enmod rewrite sudo a2enmod actions
.htaccess및 index.php파일이 동일한 공개 액세스 가능한 디렉토리에 있는지 확인하십시오 . .htaccess파일이 코드를 포함해야합니다 :
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
이 .htaccess파일은 URL 재 작성 이 필요합니다.
Apache mod_rewrite모듈 을 활성화 하고 가상 호스트가 다시 쓰기 규칙을 사용할 수 AllowOverride있도록 옵션으로 구성되어 있는지 확인하십시오 .htaccess. 이렇게하려면 파일 /etc/apache2/apache2.conf을 루트 권한으로 편집기에서 열어야합니다.
apache2.conf 예시
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
마지막으로 Apache 구성을 다시로드해야합니다. Apache 웹 서버를 다시 시작하려면 다음을 입력하십시오.
sudo service apache2 restart
이제 php 코드를 작성하겠습니다.
URL 라우팅에 이용할 Router 클래스 코드입니다.
Router.php
<?php
class Router
{
private static $routes = Array();
private static $pathNotFound = null;
private static $methodNotAllowed = null;
public static function add($method, $expression, $function){
array_push(self::$routes,Array(
'expression' => $expression,
'function' => $function,
'method' => $method
));
}
public static function pathNotFound($function){
self::$pathNotFound = $function;
}
public static function methodNotAllowed($function){
self::$methodNotAllowed = $function;
}
public static function run($basepath = '/'){
// Parse current url
$parsed_url = parse_url($_SERVER['REQUEST_URI']);//Parse Uri
if(isset($parsed_url['path'])){
$path = $parsed_url['path'];
}else{
$path = '/';
}
// 현재 리퀘스트 메서드 확인(get,post...ect)
$method = $_SERVER['REQUEST_METHOD'];
$path_match_found = false;
$route_match_found = false;
foreach(self::$routes as $route){
// If the method matches check the path
// Add basepath to matching string
if($basepath!=''&&$basepath!='/'){
$route['expression'] = '('.$basepath.')'.$route['expression'];
}
// Add 'find string start' automatically
$route['expression'] = '^'.$route['expression'];
// Add 'find string end' automatically
$route['expression'] = $route['expression'].'$';
// echo $route['expression'].'<br/>';
// Check path match
if(preg_match('#'.$route['expression'].'#',$path,$matches)){
$path_match_found = true;
// Check method match
if(strtolower($method) == strtolower($route['method'])){
array_shift($matches);// Always remove first element. This contains the whole string
if($basepath!=''&&$basepath!='/'){
array_shift($matches);// Remove basepath
}
call_user_func_array($route['function'], $matches);
$route_match_found = true;
// Do not check other routes
break;
}
}
}
// No matching route was found
if(!$route_match_found){
// But a matching path exists
if($path_match_found){
header("HTTP/1.0 405 Method Not Allowed");
if(self::$methodNotAllowed){
call_user_func_array(self::$methodNotAllowed, Array($path,$method));
}
}else{
header("HTTP/1.0 404 Not Found");
if(self::$pathNotFound){
call_user_func_array(self::$pathNotFound, Array($path));
}
}
}
}
}
코드를 간단하게 설명하면 추가되어있는 URL, 리퀘스트메서드(get,post,update...etc)를 확인후
파라미터, 정규식등확인하여 값을 파싱후 콜백함수를 리턴하도록 되어있습니다.
모든 경로를 순차적으로 라우터를 탐색하는 단순한 구조로 되어있습니다.
다음은 라우터가 실행되고 동작하는 index.php 파일입니다.
index.php
<?php
// Include router class
require 'Router.php';
//echo "hi";
// 일반적인 홈경로
Router::add('get','/',function(){
echo '라우터 홈입니다.';
});
// static html file 테스트
Router::add('get','/test.html',function(){
echo 'Hello from test.html';
});
// Post로 요청 보내기 테스트 하는 페이지
Router::add('get','/contact-form',function(){
echo '<form method="post"><input type="text" name="test" /><input type="submit" value="send" /></form>';
});
// Post 경로로 들어오는 값 확인하기 테스트
Router::add('post','/contact-form',function(){
echo '보낸 데이터 확인:<br/>';
print_r($_POST);
});
// Accept only numbers as parameter. Other characters will result in a 404 error
Router::add('get','/foo/([a-z-0-9-]+)/bar/([0-9]+)',function($var1,$var2){
echo '1번째 파라미터 :'.$var1.' 2번째 파라미터: '.$var2;
});
// idx(숫자, $var1) 값을 통해 유저 정보를 조회
Router::add('get','/user/([0-9-]+)',function($var1){
require_once 'select_from_idx.php';
});
// 유저 정보를 테이블에 저장
Router::add('post','/user',function(){
require_once 'insert.php';
});
Router::run();
가장 하단의 요청 2개를 제외하고 모두 웹 브라우저에서 테스트 가능합니다.
예를 들면 다음과 같이 확인이 가능합니다.
이제 이전 작성글인 stickode.tistory.com/19?category=921753 을 활용하여
POST 를 통한 유저 정보 추가, GET 요청을 통해 특정 idx 유저정보를 확인해보겠습니다.
dbconfig.php
<?php
return [
'server'=>'서버 ip',
'name'=>'DB 이름',
'username'=>'DB 유저 명',
'password'=>'DB 유저 비밀번호',
'charset'=>'utf8mb4'
];
dbconnect.php
<?php
//echo __DIR__;
$dbconfig = require_once __DIR__.'/dbconfig.php';
//echo $dbconfig['server'];
try {
return new PDO(
"mysql:host=" . $dbconfig['server'] . ";dbname=" . $dbconfig['name'] . ";
charset=" . $dbconfig['charset'], $dbconfig['username'], $dbconfig['password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
} catch (Exception $e) {
echo $e->getMessage();
// echo 'db connection error';
}
insert.php
<?php
$pdo = require_once __DIR__.'/dbconnect.php';
$data =json_decode(file_get_contents('php://input'), true);
try {
// if(!$this->pdo->inTransaction()) // 필요시 트랜잭션
// $this->pdo->beginTransaction();
$col1 = $data['id'];
$col2 = $data['pwd'];//패스워드
$col3 = $data['nick'];
$col2 = password_hash($col2,PASSWORD_BCRYPT);
// echo $col1;
$sql = "INSERT INTO user (id,password,nick) VALUES (?, ?,?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(array($col1,$col2,$col3));
$last_idx = $pdo->lastInsertId();
echo "insert ok : inserted idx is ".$last_idx;
// if($this->pdo->inTransaction()) // 필요시 트랜잭션
// $this->pdo->commit();
} catch (Exception $e){
if($pdo->inTransaction())
$pdo->rollBack();
echo $e->getMessage();
}
포스트맨을 통해 테스트 해보았습니다.
select_from_idx.php
<?php
$pdo = require_once __DIR__.'/dbconnect.php';
$sql ="SELECT id,nick FROM user WHERE idx=? ";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute(array($var1));
if ($stmt->rowCount()>0) { //
$result = $stmt->fetchAll();
echo json_encode($result,JSON_UNESCAPED_UNICODE);
}else{ // 결과값 없음.
echo "no user";
}
} catch (Exception $e){
if($pdo->inTransaction()) // 트랜잭션과 연관된 경우 롤백처리.
$pdo->rollBack();
echo $e->getMessage();
}
생성된 유저정보를 get요청으로 확인해보겠습니다.
아까 입력한 유저정보가 잘 보여지는것을 확인 가능합니다.
이런식으로 라우터를 통해 REST API를 구축할수도 있습니다.
'PHP' 카테고리의 다른 글
[PHP] phpmailer을 이용한 이메일 전송 (0) | 2021.04.15 |
---|---|
[PHP] 네이버 검색 API 빠르게 구현하기 (0) | 2021.04.11 |
[PHP] 쿠키를 사용하여 팝업창 만들기 (0) | 2021.04.07 |
[PHP] curl을 이용한 HTTP 통신 (0) | 2021.04.03 |
[PHP] PDO를 활용한 CRUD 구현 (0) | 2021.02.19 |