
Representational State Transfer یک سبک معماری در وب سرویس است که در آن از آدرس ها برای دستیابی به منابع استفاده می شود. داده ها و توابع در معماری RESTful منابع نامیده می شوند به این جهت که داده ها و توابع در واقع آنچیزی هستند که ما می خواهیم از طریق سرویس به آن متصل شویم.
در این پست می خواهیم نشان دهیم که چطور می توان یک وب سرویس RESTful را بدون استفاده از هیچ نوع Framework خاصی در PHP ایجاد کرد.
در ادامه مطلب همراه من باشید.
مواردی که در این پست بررسی می کنیم:
- ایجاد وب سرویس RESTful با استفاده از PHP و بدون استفاده از فریمورک خاصی
- تعیین الگوی آدرس بر طبق اصول RESTful
- قابلیت ایجاد پاسخ های وب سرویس در قالب JSON و XML
- نمایش کدهای وضعیت HTTP بر طبق سناریوهای مختلف
- استفاده از هدرهای درخواست
- آزمایش وب سرویس RESTful
وب سرویس RESTful:
در زیر یک کلاس برای نمایش وب سرویس RESTful را مشاهده می کنید. یک فایل با نام Mobile.php در وب دایرکتوری خود ایجاد کنید و کد زیر را در آن بنویسید.
<?php
/*
A domain Class to demonstrate RESTful web services
*/
Class Mobile {
private $mobiles = array(
1 => 'Apple iPhone 6S',
2 => 'Samsung Galaxy S6',
3 => 'Apple iPhone 6S Plus',
4 => 'LG G4',
5 => 'Samsung Galaxy S6 edge',
6 => 'OnePlus 2');
/*
you should hookup the DAO here
*/
public function getAllMobile(){
return $this->mobiles;
}
public function getMobile($id){
$mobile = array($id => ($this->mobiles[$id]) ? $this->mobiles[$id] : $this->mobiles[1]);
return $mobile;
}
}
?>
تعیین آدرس های سرویس RESTful:
وب سرویس های RESTful باید دارای یک آدرس مرتب و تمیز باشند، فایل .htaccess برای انجام نگاشت URL بین درخواست و فایل استفاده می شود و در این مثال ما از دو آدرس زیر استفاده می کنیم:
آدرس برای دریافت لیست همه موبایل ها:
http://localhost/restexample/mobile/list
آدرس برای دریافت جزئیات موبایل خاص با استفاده از id:
http://localhost/restexample/mobile/list/2
در زیر فایل .htaccess را برای هدایت درخواست ها به سمت فایل RestController.php مشاهده می کنید:
# Turn rewrite engine on
Options +FollowSymlinks
RewriteEngine on
# map neat URL to internal URL
RewriteRule ^mobile/list$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/list/([0-9]+)$ RestController.php?view=single&id=$1 [nc,qsa]
کنترلر وب سرویس RESTful:
در htaccess. همه درخواست ها را به فایل RestController.php با یک کلید به نام 'view' برای شناسایی درخواست ها هدایت کردیم. در زیر فایل RestController.php را مشاهده می کنید که درخواست را دریافت می کند و به متدی برای رسیدگی به درخواست می فرستد. کلید 'view' برای مشخص کردن آدرس درخواست استفاده می شود.
<?php
require_once("MobileRestHandler.php");
$view = "";
if(isset($_GET["view"]))
$view = $_GET["view"];
/*
controls the RESTful services
URL mapping
*/
switch($view){
case "all":
// to handle REST Url /mobile/list/
$mobileRestHandler = new MobileRestHandler();
$mobileRestHandler->getAllMobiles();
break;
case "single":
// to handle REST Url /mobile/show/<id>/
$mobileRestHandler = new MobileRestHandler();
$mobileRestHandler->getMobile($_GET["id"]);
break;
case "" :
//404 - not found;
break;
}
?>
کلاس پایه ساده RESTful:
در زیر کلاسی را مشاهده می کنید که دارای دو متد است که اغلب در رسیدگی کننده وب سرویس RESTful استفاده می شود یک متد برای ساخت پاسخ و متد دیگر برای نگه داشتن کد وضعیت HTTP و هدایت پیام مربوط استفاده می شود. می توان متدهای دیگری را به این کلاس اضافه کرد.
<?php
/*
A simple RESTful webservices base class
Use this as a template and build upon it
*/
class SimpleRest {
private $httpVersion = "HTTP/1.1";
public function setHttpHeaders($contentType, $statusCode){
$statusMessage = $this -> getHttpStatusMessage($statusCode);
header($this->httpVersion. " ". $statusCode ." ". $statusMessage);
header("Content-Type:". $contentType);
}
public function getHttpStatusMessage($statusCode){
$httpStatus = array(
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported');
return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $status[500];
}
}
?>
رسیدگی کننده (Handler) وب سرویس RESTful:
این کلاس به درخواست های REST رسیدگی می کند. در رابطه با این کلاس باید به دو نکته توجه داشت: اولین نکته اینکه رسیدگی کننده REST چه نوعی از قالب پاسخ را برگرداند. این تصمیم بر پایه پارامتر 'accept' در هدر درخواست است. پروتکل موجود باید زمانی که درخواست ارسال می شود پارامتر 'accept' را مقدار دهی و ارسال کند. مقادیر می تواند 'application/json' یا 'application/xml' باشد و دومین نکته، استفاده از کدهای وضعیت است که در وضعیت موفق، باید کد وضعیت 200 در پاسخ قرار بگیرد و ارسال شود. مشابه این، کدهای وضعیت مختلفی در دسترس هستند که بر طبق موقعیت های دیگر استفاده می شوند.
<?php
require_once("SimpleRest.php");
require_once("Mobile.php");
class MobileRestHandler extends SimpleRest {
function getAllMobiles() {
$mobile = new Mobile();
$rawData = $mobile->getAllMobile();
if(empty($rawData)) {
$statusCode = 404;
$rawData = array('error' => 'No mobiles found!');
} else {
$statusCode = 200;
}
$requestContentType = $_SERVER['HTTP_ACCEPT'];
$this ->setHttpHeaders($requestContentType, $statusCode);
if(strpos($requestContentType,'application/json') !== false){
$response = $this->encodeJson($rawData);
echo $response;
} else if(strpos($requestContentType,'text/html') !== false){
$response = $this->encodeHtml($rawData);
echo $response;
} else if(strpos($requestContentType,'application/xml') !== false){
$response = $this->encodeXml($rawData);
echo $response;
}
}
public function encodeHtml($responseData) {
$htmlResponse = "<table border='1'>";
foreach($responseData as $key=>$value) {
$htmlResponse .= "<tr><td>". $key. "</td><td>". $value. "</td></tr>";
}
$htmlResponse .= "</table>";
return $htmlResponse;
}
public function encodeJson($responseData) {
$jsonResponse = json_encode($responseData);
return $jsonResponse;
}
public function encodeXml($responseData) {
// creating object of SimpleXMLElement
$xml = new SimpleXMLElement('<?xml version="1.0"?><mobile></mobile>');
foreach($responseData as $key=>$value) {
$xml->addChild($key, $value);
}
return $xml->asXML();
}
public function getMobile($id) {
$mobile = new Mobile();
$rawData = $mobile->getMobile($id);
if(empty($rawData)) {
$statusCode = 404;
$rawData = array('error' => 'No mobiles found!');
} else {
$statusCode = 200;
}
$requestContentType = $_SERVER['HTTP_ACCEPT'];
$this ->setHttpHeaders($requestContentType, $statusCode);
if(strpos($requestContentType,'application/json') !== false){
$response = $this->encodeJson($rawData);
echo $response;
} else if(strpos($requestContentType,'text/html') !== false){
$response = $this->encodeHtml($rawData);
echo $response;
} else if(strpos($requestContentType,'application/xml') !== false){
$response = $this->encodeXml($rawData);
echo $response;
}
}
}
?>
کلاینت وب سرویس RESTful:
برای آزمایش وب سرویس RESTful، باید یک کلاینت REST را برنامه نویسی کنید و از سرویس استفاده کنید. راه های دیگری برای استفاده از کلاینت REST موجود است. تعداد زیادی کلاینت REST مستقل عرضه شده است که در اینجا ما از یک پلاگین Google Chrome Rest Client استفاد می کنیم.
"Advanced Rest Client" یک افزونه Chrome است که تصویر محیط این افزونه و تست انجام شده را در زیر مشاهده می کنید:
php | restful | web service |