참고사이트
https://code.tutsplus.com/tutorials/how-to-build-a-simple-rest-api-in-php--cms-37000
REST는 API를 통해 데이터를 노출하고 웹 서비스를 구축할 때 사실상의 표준이 되었습니다.
대부분의 웹 애플리케이션은 REST API를 통해 데이터에 액세스하고 노출합니다.
프로젝트 구조를 간략하게 살펴보겠습니다.
├── Controller
│ └── Api
│ ├── BaseController.php
│ └── UserController.php
├── inc
│ ├── bootstrap.php
│ └── config.php
├── index.php
└── Model
├── Database.php
└── UserModel.php
index.php : 애플리케이션의 진입점. 우리 애플리케이션의 전면 컨트롤러 역할을 합니다.
inc/config.php : 우리 애플리케이션의 설정 정보를 담고 있습니다. 주로 데이터베이스 자격 증명을 보유합니다.
inc/bootstrap.php : 필요한 파일을 포함하여 애플리케이션을 부트스트랩하는 데 사용됩니다.
Model/Database.php : 기본 MySQL 데이터베이스와 상호 작용하는 데 사용되는 데이터베이스 액세스 계층입니다.
Model/UserModel.php : UserMySQL 데이터베이스의 users 테이블과 상호작용하는 데 필요한 메소드를 구현하는 모델 파일입니다.
Controller/Api/BaseController.php : 일반적인 유틸리티 메소드를 포함하는 기본 컨트롤러 파일입니다.
Controller/Api/UserController.php : UserREST API 호출을 즐겁게 하는 데 필요한 애플리케이션 코드가 들어 있는 컨트롤러 파일입니다.
다음은 데이터베이스와 사용자 테이블을 생성합니다.
또한 데이터베이스에서 사용자를 가져오는 데 사용할 필요한 모델 클래스를 만들 것입니다.
데이터베이스 및 사용자 테이블 생성
MySQL 터미널에서 다음 명령을 실행하여 데이터베이스를 생성합니다.
CREATE DATABASE rest_api_demo;
데이터베이스 작업을 phpMyAdmin 과 같은 도구를 사용할 수도 있습니다 .
rest_api_demo 데이터베이스가 생성 되면, 다음 명령문을 실행하여 users 테이블을 생성합니다.
use rest_api_demo;
CREATE TABLE `users` (
`user_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_email` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_status` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
그러면 데이터베이스에 users테이블이 생성됩니다.
모델 클래스 생성
다음은 필요한 모델 클래스를 생성합니다.
다음 내용으로 Model/Database.php 파일을 생성합니다 .
<?php
class Database
{
protected $connection = null;
public function __construct()
{
try {
$this->connection = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_DATABASE_NAME);
if ( mysqli_connect_errno()) {
throw new Exception("Could not connect to database.");
}
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
public function select($query = "" , $params = [])
{
try {
$stmt = $this->executeStatement( $query , $params );
$result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
$stmt->close();
return $result;
} catch(Exception $e) {
throw New Exception( $e->getMessage() );
}
return false;
}
private function executeStatement($query = "" , $params = [])
{
try {
$stmt = $this->connection->prepare( $query );
if($stmt === false) {
throw New Exception("Unable to do prepared statement: " . $query);
}
if( $params ) {
$stmt->bind_param($params[0], $params[1]);
}
$stmt->execute();
return $stmt;
} catch(Exception $e) {
throw New Exception( $e->getMessage() );
}
}
}
이것은 MySQL 데이터베이스에 대한 연결을 설정할 수 있는 데이터베이스 액세스 계층 클래스입니다.
연결 설정 외에도 데이터베이스에서 레코드를 선택할 수 있도록 하는 select와 executeStatement 같은 메서드가 포함되어 있습니다.
Database클래스를 직접 사용하지 않을 것입니다. Database대신 기본 MySQL 데이터베이스에 액세스하기 위해 클래스를 확장하는 해당 모델 클래스를 생성 합니다.
다음으로 아래와 같은 내용으로 Model/UserModel.php 클래스를 생성해 보겠습니다 .
<?php
require_once PROJECT_ROOT_PATH . "/Model/Database.php";
class UserModel extends Database
{
public function getUsers($limit)
{
return $this->select("SELECT * FROM users ORDER BY user_id ASC LIMIT ?", ["i", $limit]);
}
}
UserModel클래스가 Database 클래스를 확장 한다는 점에 유의하는 것이 중요합니다 .
그 외에도 MySQL 데이터베이스에서 사용자를 선택할 수 있는 getUsers 메서드가 포함되어 있습니다. 한 번에 모든 레코드를 선택하지 않도록 하는 $limit 매개변수 를 전달하는 것은 필수 입니다.
물론 요구 사항에 따라 UserModel 클래스에서 더 많은 메서드를 정의할 수 있습니다.
이제 데이터베이스와 모델 클래스가 설정되었습니다.
다음는 데모 애플리케이션에서 컨트롤러와 나머지 파일을 만드는 방법을 살펴보겠습니다.
데모 응용 프로그램이 작동하는 데 필요한 나머지 파일을 만듭니다.
Inc 디렉토리
우선 필요한 구성 파일을 생성하겠습니다.
다음 내용으로 inc/config.php 파일을 생성합니다 .
<?php
define("DB_HOST", "localhost");
define("DB_USERNAME", "demo");
define("DB_PASSWORD", "demo");
define("DB_DATABASE_NAME", "rest_api_demo");
설치에서 사용 중인 실제 값으로 모든 값을 업데이트해야 합니다.
다음으로 진행 하여 다음 내용으로 inc/bootstrap.php 파일을 만듭니다.
<?php
define("PROJECT_ROOT_PATH", __DIR__ . "/../");
// include main configuration file
require_once PROJECT_ROOT_PATH . "/inc/config.php";
// include the base controller file
require_once PROJECT_ROOT_PATH . "/Controller/Api/BaseController.php";
// include the use model file
require_once PROJECT_ROOT_PATH . "/Model/UserModel.php";
?>
먼저 애플리케이션의 디렉토리 루트로 PROJECT_ROOT_PATH 상수를 초기화했습니다.
이런 식으로 PROJECT_ROOT_PATH상수를 사용하여 응용 프로그램에서 절대 경로를 준비할 수 있습니다.
다음으로 데이터베이스 연결 정보를 담고 있는 config.php 파일을 포함시켰습니다.
마지막으로 컨트롤러 및 모델 파일을 포함했습니다.
컨트롤러 디렉토리
애플리케이션 논리를 보유하는 컨트롤러를 구현합니다.
BaseController.php 파일
다음 내용으로 Controller/Api/BaseController.php 파일을 생성합니다 .
BaseController클래스에는 다른 컨트롤러에서 사용하는 유틸리티 메서드가 포함되어 있습니다 .
<?php
class BaseController
{
/**
* __call magic method.
*/
public function __call($name, $arguments)
{
$this->sendOutput('', array('HTTP/1.1 404 Not Found'));
}
/**
* Get URI elements.
*
* @return array
*/
protected function getUriSegments()
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode( '/', $uri );
return $uri;
}
/**
* Get querystring params.
*
* @return array
*/
protected function getQueryStringParams()
{
return parse_str($_SERVER['QUERY_STRING'], $query);
}
/**
* Send API output.
*
* @param mixed $data
* @param string $httpHeader
*/
protected function sendOutput($data, $httpHeaders=array())
{
header_remove('Set-Cookie');
if (is_array($httpHeaders) && count($httpHeaders)) {
foreach ($httpHeaders as $httpHeader) {
header($httpHeader);
}
}
echo $data;
exit;
}
}
__call메소드는 존재하지 않는 메소드를 호출하려고 할 때 호출됩니다.
누군가 우리가 구현하지 않은 메서드를 호출하려고 할 때 HTTP/1.1 404 Not Found 오류를 발생 시키기 위해 사용하고 있습니다.
다음 으로 URI 세그먼트의 배열을 반환하는 getUriSegments메서드가 있습니다.
사용자가 호출한 REST 끝점의 유효성을 검사할 때 유용합니다.
그 다음은 들어오는 요청과 함께 전달되는 쿼리 문자열 변수의 배열을 반환하는 getQueryStringParams메서드가 있습니다.
마지막으로 응답을 보내는 데 사용되는 sendOutputAPI 메서드가 있습니다.
API 응답을 사용자에게 보내고 싶을 때 이 메서드를 호출합니다.
UserController.php 파일
다음으로 Controller/Api/UserController.php 파일을 생성합니다.
<?php
class UserController extends BaseController
{
/**
* "/user/list" Endpoint - Get list of users
*/
public function listAction()
{
$strErrorDesc = '';
$requestMethod = $_SERVER["REQUEST_METHOD"];
$arrQueryStringParams = $this->getQueryStringParams();
if (strtoupper($requestMethod) == 'GET') {
try {
$userModel = new UserModel();
$intLimit = 10;
if (isset($arrQueryStringParams['limit']) && $arrQueryStringParams['limit']) {
$intLimit = $arrQueryStringParams['limit'];
}
$arrUsers = $userModel->getUsers($intLimit);
$responseData = json_encode($arrUsers);
} catch (Error $e) {
$strErrorDesc = $e->getMessage().'Something went wrong! Please contact support.';
$strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
}
} else {
$strErrorDesc = 'Method not supported';
$strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
}
// send output
if (!$strErrorDesc) {
$this->sendOutput(
$responseData,
array('Content-Type: application/json', 'HTTP/1.1 200 OK')
);
} else {
$this->sendOutput(json_encode(array('error' => $strErrorDesc)),
array('Content-Type: application/json', $strErrorHeader)
);
}
}
}
UserController클래스는 BaseController 클래스를 확장 한다.
이상적으로는 이 클래스에 사용자 엔터티에 대해 정의된 REST endpoint과 연결된 작업 메서드가 포함됩니다.
예를 들어 /user/list 경우 REST 끝점은 listAction메서드에 해당합니다.
이러한 방식으로 다른 REST endpoint에 대해 다른 메서드를 정의할 수도 있습니다.
이 listAction 메소드는 MySQL 데이터베이스에서 사용자 목록을 가져오는 데 사용됩니다.
여기에는 /user/list REST endpoint의 전체 논리가 포함됩니다.
이 listAction 메서드에서 $requestMethod 와 $arrQueryStringParams 같은 몇 가지 변수를 처음에 초기화했습니다.
다음으로 사용자가 GET 메서드 로 user/list 엔드포인트를 호출했는지 확인합니다.
그렇지 않으면 더 이상 처리하지 않습니다.
마지막으로 UserModel객체 를 만들고 getUsers 메서드를 호출하여 데이터베이스에서 사용자 목록을 가져옵니다.
또한 이 json_encode함수를 사용하여 배열을 사용자에게 보내기 전에 JSON 객체로 변환했습니다.
마지막으로 JSON 응답을 사용자에게 보내는 sendOutput 메소드를 사용했습니다.
JSON 응답을 보내는 중이므로 응답 콘텐츠 유형 헤더 값이 application/json 로 설정된다는 점에 유의하는 것이 중요합니다 .
마찬가지로 다른 endpoint에 대해 다른 메서드도 정의할 수 있습니다.
index.php 파일
index.php 파일은 애플리케이션의 진입점입니다.
<?php
require __DIR__ . "/inc/bootstrap.php";
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode( '/', $uri );
if ((isset($uri[2]) && $uri[2] != 'user') || !isset($uri[3])) {
header("HTTP/1.1 404 Not Found");
exit();
}
require PROJECT_ROOT_PATH . "/Controller/Api/UserController.php";
$objFeedController = new UserController();
$strMethodName = $uri[3] . 'Action';
$objFeedController->{$strMethodName}();
?>
먼저 URI 세그먼트를 $uri 배열 변수 로 초기화하기 위해 parse_url과 explode 함수를 사용했습니다.
다음으로 URI 세그먼트의 유효성을 검사합니다.
마지막으로 UserController 컨트롤러를 초기화하고 해당 작업 메서드를 호출했습니다.
이를 통해 데모 REST 애플리케이션에 필요한 모든 파일을 만들었습니다.
다음에는 최종 사용자 관점에서 호출하는 방법을 살펴보겠습니다.
REST API를 호출하는 방법
데모 애플리케이션을 호출하는 방법을 살펴보겠습니다.
애플리케이션에서는 사용자 목록을 가져오기 위해 REST 엔드포인트를 구축했습니다.
엔드포인트의 URL이 어떻게 보이는지 봅시다.
index.php 파일 을 떠올리면 $uri[2]변수가 user로 설정되어 있는지 확인했습니다 .
또한 $uri[3]변수 값은 메서드 이름으로 작동합니다.
위의 경우 $uri[3]변수는 list 로 설정됩니다 .
따라서 UserController 클래스 의 listAction메서드를 호출하게 됩니다.
출력은 다음과 같아야 합니다.
[
{
"user_id":1,
"username":"Bob",
"user_email":"bob@gmail.com",
"user_status":0
},
{
"user_id":2,
"username":"John",
"user_email":"john@gmail.com",
"user_status":1
},
{
"user_id":3,
"username":"Mark",
"user_email":"mark@gmail.com",
"user_status":1
},
{
"user_id":4,
"username":"Ville",
"user_email":"ville@gmail.com",
"user_status":0
}
]
사용자 목록을 JSON 개체로 반환합니다.
그 외에도 응용 프로그램 오류가 있으면 디버깅 목적으로도 JSON 개체로 반환됩니다.