2011-01-13 89 views
72

Vấn đề là: Tôi có một ứng dụng web chạy trên máy chủ PHP. Tôi muốn xây dựng một api REST cho nó.
Tôi đã thực hiện một số nghiên cứu và tôi đã tìm ra rằng REST api sử dụng các phương thức HTTP (GET, POST ...) cho một số URI nhất định bằng khóa xác thực (không nhất thiết) và thông tin được trình bày trở lại như một phản hồi HTTP với thông tin dưới dạng XML hoặc JSON (tôi thích JSON).Làm thế nào để xây dựng một RESTful API?

Câu hỏi của tôi là:

  1. Làm thế nào để, như các nhà phát triển của ứng dụng, xây dựng những nhân URI? Tôi có cần viết mã PHP tại URI đó không?
  2. Làm cách nào để tạo các đối tượng JSON để trả về dưới dạng phản hồi?
+1

http://www.gen-x-design.com/archives/create-a-rest-api-with-php/ là một nguồn lực lớn về vấn đề này. –

+0

Tôi đã viết [bài đăng trên blog] này (https://www.leaseweb.com/labs/2015/10/creating-a-simple-rest-api-in-php/) chứa một số mã ví dụ và hướng dẫn cho việc này. – mevdschee

Trả lời

66

Đây là một ví dụ rất đơn giản trong php đơn giản.

Có 2 file client.php & api.php. Tôi đặt cả hai tập tin trên cùng một url: http://localhost:8888/, vì vậy bạn sẽ phải thay đổi liên kết đến url của riêng bạn. (tệp có thể nằm trên hai máy chủ khác nhau).

Đây chỉ là một ví dụ, nó rất nhanh chóng và dơ bẩn, cộng với nó đã được một thời gian dài kể từ khi tôi đã thực hiện php. Nhưng đây là ý tưởng của một api.

client.php

<?php 

/*** this is the client ***/ 


if (isset($_GET["action"]) && isset($_GET["id"]) && $_GET["action"] == "get_user") // if the get parameter action is get_user and if the id is set, call the api to get the user information 
{ 
    $user_info = file_get_contents('http://localhost:8888/api.php?action=get_user&id=' . $_GET["id"]); 
    $user_info = json_decode($user_info, true); 

    // THAT IS VERY QUICK AND DIRTY !!!!! 
    ?> 
    <table> 
     <tr> 
     <td>Name: </td><td> <?php echo $user_info["last_name"] ?></td> 
     </tr> 
     <tr> 
     <td>First Name: </td><td> <?php echo $user_info["first_name"] ?></td> 
     </tr> 
     <tr> 
     <td>Age: </td><td> <?php echo $user_info["age"] ?></td> 
     </tr> 
    </table> 
    <a href="http://localhost:8888/client.php?action=get_userlist" alt="user list">Return to the user list</a> 
    <?php 
} 
else // else take the user list 
{ 
    $user_list = file_get_contents('http://localhost:8888/api.php?action=get_user_list'); 
    $user_list = json_decode($user_list, true); 
    // THAT IS VERY QUICK AND DIRTY !!!!! 
    ?> 
    <ul> 
    <?php foreach ($user_list as $user): ?> 
     <li> 
     <a href=<?php echo "http://localhost:8888/client.php?action=get_user&id=" . $user["id"] ?> alt=<?php echo "user_" . $user_["id"] ?>><?php echo $user["name"] ?></a> 
    </li> 
    <?php endforeach; ?> 
    </ul> 
    <?php 
} 

?> 

api.php

<?php 

// This is the API to possibility show the user list, and show a specific user by action. 

function get_user_by_id($id) 
{ 
    $user_info = array(); 

    // make a call in db. 
    switch ($id){ 
    case 1: 
     $user_info = array("first_name" => "Marc", "last_name" => "Simon", "age" => 21); // let's say first_name, last_name, age 
     break; 
    case 2: 
     $user_info = array("first_name" => "Frederic", "last_name" => "Zannetie", "age" => 24); 
     break; 
    case 3: 
     $user_info = array("first_name" => "Laure", "last_name" => "Carbonnel", "age" => 45); 
     break; 
    } 

    return $user_info; 
} 

function get_user_list() 
{ 
    $user_list = array(array("id" => 1, "name" => "Simon"), array("id" => 2, "name" => "Zannetie"), array("id" => 3, "name" => "Carbonnel")); // call in db, here I make a list of 3 users. 

    return $user_list; 
} 

$possible_url = array("get_user_list", "get_user"); 

$value = "An error has occurred"; 

if (isset($_GET["action"]) && in_array($_GET["action"], $possible_url)) 
{ 
    switch ($_GET["action"]) 
    { 
     case "get_user_list": 
     $value = get_user_list(); 
     break; 
     case "get_user": 
     if (isset($_GET["id"])) 
      $value = get_user_by_id($_GET["id"]); 
     else 
      $value = "Missing argument"; 
     break; 
    } 
} 

exit(json_encode($value)); 

?> 

tôi không thực hiện bất kỳ cuộc gọi đến cơ sở dữ liệu ví dụ này, nhưng thông thường đó là những gì bạn nên làm . Bạn cũng nên thay thế hàm "file_get_contents" bằng "curl".

+0

Simon, cảm ơn bạn rất nhiều vì ví dụ của bạn. Tôi chỉ muốn chắc chắn: Giả sử tôi có tài nguyên được gọi là Người dùng, sau đó tôi cần phải đặt tệp API trong: http://www.mydomain.com/api/user Chính xác? –

+0

Bạn có thể đặt tên cho tệp như bạn muốn. Nhưng có, cách tốt hơn để gọi tệp bằng tên explicite. Nhìn vào tập tin api của tôi, tôi kiểm tra tham số get và gọi hàm nhờ giá trị này. Bạn có thể làm một bao gồm user.php và gọi một hàm có trong tệp này, hoặc bạn có thể đặt tệp tại api/user và xử lý các tham số từ đây. –

+0

Vì vậy, về cơ bản, tôi cần cập nhật bảng định tuyến máy chủ để ánh xạ một số URL nhất định tới một tệp PHP nhất định trên máy chủ. Chính xác? –

10

Điều đó khá giống với việc tạo trang web thông thường.

mô hình bình thường cho một trang web php là:

  1. Người dùng nhập url
  2. Máy chủ lấy url, phân tích nó và thực hiện một hành động
  3. Trong hành động này, bạn sẽ có được/tạo ra mỗi thông tin bạn cần cho trang
  4. Bạn tạo trang html/php có thông tin từ hành động
  5. Máy chủ tạo trang hoàn toàn html và gửi lại cho người dùng

Với api, bạn chỉ cần thêm một bước mới từ 3 đến 4. Sau 3, tạo một mảng với tất cả thông tin bạn cần. Mã hóa mảng này trong json và thoát hoặc trả về giá trị này.

$info = array("info_1" => 1; "info_2" => "info_2" ... "info_n" => array(1,2,3)); 
exit(json_encode($info)); 

Đó là tất cả cho api. Đối với phía máy khách, bạn có thể gọi api bằng url. Nếu api chỉ làm việc với nhận cuộc gọi, tôi nghĩ rằng nó có thể làm một cách đơn giản (Để kiểm tra, tôi thường sử dụng curl).

$info = file_get_contents(url); 
$info = json_decode($info); 

Nhưng việc sử dụng thư viện curl để thực hiện và nhận cuộc gọi trở nên phổ biến hơn. Bạn có thể hỏi tôi nếu bạn cần trợ giúp với curl.

Khi nhận được thông tin từ api, bạn có thể thực hiện 4 & 5 bước.

Tìm tài liệu php cho hàm json và file_get_contents.

curl: http://fr.php.net/manual/fr/ref.curl.php


EDIT

Không, chờ đợi, tôi không nhận được nó. "trang API php" ý bạn là gì?

Api chỉ là việc tạo/phục hồi dự án của bạn. Bạn KHÔNG BAO GIỜ gửi trực tiếp kết quả html (nếu bạn đang tạo một trang web) hãy gửi một api. Bạn gọi api với url, thông tin trả về api, bạn sử dụng thông tin này để tạo kết quả cuối cùng.

ví dụ: bạn muốn viết một trang html nói xin chào xxx.Nhưng để lấy tên người dùng, bạn phải lấy thông tin từ api. Vì vậy, giả sử api của bạn có một hàm có user_id làm đối số và trả về tên của người dùng này (giả sử getUserNameById (user_id)), và bạn gọi hàm này chỉ trên một url như/api/ulr/getUser của bạn /ID.

Function getUserNameById(user_id) 
{ 
    $userName = // call in db to get the user 
    exit(json_encode($userName)); // maybe return work as well. 
} 

Từ phía client bạn làm

$username = file_get_contents(your/api/url/getUser/15); // You should normally use curl, but it simpler for the example 
// So this function to this specifique url will call the api, and trigger the getUserNameById(user_id), whom give you the user name. 
    <html> 
    <body> 
    <p>hello <?php echo $username ?> </p> 
    </body> 
    </html> 

Vì vậy, khách hàng không bao giờ truy cập trực tiếp các cơ sở dữ liệu, mà vai trò của api.

Điều đó có rõ ràng hơn không?

+0

+1. Cũng cần lưu ý, API nên đặt đúng loại nội dung cho phản hồi. Đối với json, hãy xem http://stackoverflow.com/questions/477816/the-right-json-content-type – Ben

+0

Vì vậy, tôi nên có trên trang máy chủ một API php quản lý tất cả các yêu cầu? –

+0

Không, chờ đã, tôi không hiểu. "trang API php" ý bạn là gì? –

0

Như simon marc đã nói, quy trình này giống với quá trình này đối với bạn hoặc tôi đang duyệt một trang web. Nếu bạn cảm thấy thoải mái với việc sử dụng khung công tác Zend, có một số hướng dẫn dễ làm theo để làm cho cuộc sống trở nên khá dễ dàng để thiết lập mọi thứ. Phần khó nhất của việc xây dựng một api an toàn là thiết kế của nó, và làm cho nó thật sự yên tĩnh, hãy nghĩ CRUD trong các thuật ngữ cơ sở dữ liệu.

Có thể bạn thực sự muốn có giao diện xmlrpc hoặc một thứ gì đó tương tự. Bạn muốn giao diện này cho phép bạn làm gì?

--EDIT

Đây là nơi tôi bắt đầu với api và khung công tác Zend an toàn. Zend Framework Example

Trong ngắn hạn không sử dụng máy chủ phần còn lại Zend, nó đã lỗi thời.

+0

Làm thế nào để bạn sử dụng khung công tác của Zend để xây dựng một API RESTful? –

+0

Nếu bạn quan tâm, tôi sẽ đăng một cái gì đó lên blog của tôi về việc bắt đầu với các dịch vụ web ZF và RESTful với một ví dụ làm việc hoàn chỉnh. –

31

Trong năm 2013, bạn nên sử dụng một cái gì đó giống như Silex hoặc Slim

silex dụ:

require_once __DIR__.'/../vendor/autoload.php'; 

$app = new Silex\Application(); 

$app->get('/hello/{name}', function($name) use($app) { 
    return 'Hello '.$app->escape($name); 
}); 

$app->run(); 

Slim dụ:

$app = new \Slim\Slim(); 
$app->get('/hello/:name', function ($name) { 
    echo "Hello, $name"; 
}); 
$app->run(); 
+1

Cảm ơn bạn. Tôi đã sử dụng Slim và tôi đã có một api trần chạy trong vài phút. – user12345

+0

Bạn muốn giới thiệu gì cho một apis phức tạp hơn (chi tiết)? Slim rất tiện dụng nhưng tất cả các chức năng đều nằm trong một tệp duy nhất nên khả năng đọc khá khó. –

+2

@IlkerBaltaci Với Silex, bạn có thể trích xuất bộ điều khiển thành các lớp. Đây là một bài viết hay về điều đó, và một số ưu điểm và nhược điểm của việc sử dụng một khung công tác vi mô và khung công tác toàn diện https://igor.io/2012/11/09/scaling-silex.html.Cá nhân tôi thích Silex vì nó mang lại cho tôi những thứ quan trọng nhất và cho phép tôi chọn phần còn lại của ngăn xếp của mình. – finishingmove

2

Một khuôn khổ mà chưa được đề cập đến nay là Laravel . Thật tuyệt vời khi xây dựng các ứng dụng PHP nói chung nhưng nhờ vào bộ định tuyến tuyệt vời, nó thực sự thoải mái và đơn giản để xây dựng các API phong phú. Nó có thể không mỏng như Slim hay Sliex nhưng nó mang lại cho bạn một cấu trúc chắc chắn.

Xem Aaron Kuzemchak - Simple API Development With Laravel trên YouTube và

Laravel 4: A Start at a RESTful API trên nettuts +

2

Tôi biết rằng câu hỏi này được chấp nhận và có một chút tuổi nhưng điều này có thể hữu ích cho một số người vẫn thấy nó có liên quan. Mặc dù kết quả không phải là một API RESTful đầy đủ, nhưng hàm API Builder mini lib cho PHP cho phép bạn dễ dàng chuyển đổi cơ sở dữ liệu MySQL thành các API JSON có thể truy cập web.

5

(1) Làm cách nào để ... tạo các URI đó? Tôi có cần viết mã PHP tại URI đó không?

Không có tiêu chuẩn nào về cách thiết lập sơ đồ API URI, nhưng thông thường có giá trị được phân tách bằng dấu gạch chéo. Đối với điều này bạn có thể sử dụng ...

$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1)); 

... để có được một mảng các giá trị slash-tách ra trong URI sau tên tập tin.

Ví dụ: Giả sử bạn có tệp API api.php trong ứng dụng của bạn ở đâu đó và bạn yêu cầu api.php/members/3, sau đó $apiArgArray sẽ là một mảng chứa ['members', '3']. Sau đó, bạn có thể sử dụng các giá trị đó để truy vấn cơ sở dữ liệu của mình hoặc thực hiện xử lý khác.

(2) Làm cách nào để xây dựng các đối tượng JSON trả về dưới dạng phản hồi?

Bạn có thể lấy bất kỳ đối tượng PHP nào và biến thành JSON với json_encode. Bạn cũng sẽ muốn đặt tiêu đề phù hợp.

header('Content-Type: application/json'); 
$myObject = (object) array('property' => 'value'); // example 
echo json_encode($myObject); // outputs JSON text 

Tất cả điều này là tốt cho một API trả về JSON, nhưng câu hỏi tiếp theo bạn nên hỏi là:

(3) Làm thế nào để làm cho API RESTful của tôi?

Để làm điều đó, chúng tôi sẽ sử dụng $_SERVER['REQUEST_METHOD'] để có phương pháp được sử dụng và sau đó thực hiện các việc khác nhau dựa trên điều đó. Vậy kết quả cuối cùng là ...

header('Content-Type: application/json'); 
$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1)); 
$returnObject = (object) array(); 
/* Based on the method, use the arguments to figure out 
    whether you're working with an individual or a collection, 
    then do your processing, and ultimately set $returnObject */ 
switch ($_SERVER['REQUEST_METHOD']) { 
    case 'GET': 
    // List entire collection or retrieve individual member 
    break; 
    case 'PUT':  
    // Replace entire collection or member 
    break; 
    case 'POST':  
    // Create new member 
    break; 
    case 'DELETE':  
    // Delete collection or member 
    break; 
} 
echo json_encode($returnObject); 

Nguồn: https://stackoverflow.com/a/897311/1766230http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services

Các vấn đề liên quan