Wie erstelle ich eine RESTful API?

77

Das Problem ist folgendes: Ich habe eine Webanwendung, die auf einem PHP-Server ausgeführt wird. Ich möchte eine REST-API dafür erstellen.
Ich habe einige Nachforschungen angestellt und festgestellt, dass die REST-API HTTP-Methoden (GET, POST ...) für bestimmte URIs mit einem Authentifizierungsschlüssel verwendet (nicht unbedingt) und die Informationen als HTTP-Antwort mit den Informationen als XML oder JSON zurückgegeben werden (Ich würde lieber JSON).

Meine Frage ist:

  1. Wie erstelle ich als Entwickler der App diese URIs? Muss ich an dieser URI einen PHP-Code schreiben?
  2. Wie erstelle ich die JSON-Objekte, um sie als Antwort zurückzugeben?
Sharon Haim Pour
quelle
1
gen-x-design.com/archives/create-a-rest-api-with-php ist hierfür eine großartige Ressource.
Geoffrey Wagner
Ich habe diesen Blog-Beitrag geschrieben , der einen Beispielcode und Anweisungen dazu enthält.
Mevdschee

Antworten:

68

Hier ist ein sehr einfaches Beispiel in einfachem PHP.

Es gibt 2 Dateien client.php & api.php . Ich habe beide Dateien auf dieselbe URL gesetzt : http://localhost:8888/, sodass Sie den Link zu Ihrer eigenen URL ändern müssen. (Die Datei kann sich auf zwei verschiedenen Servern befinden.)

Dies ist nur ein Beispiel, es ist sehr schnell und schmutzig, und es ist lange her, seit ich PHP gemacht habe. Aber das ist die Idee einer 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));

?>

Ich habe für dieses Beispiel keine Datenbank aufgerufen, aber normalerweise sollten Sie dies tun. Sie sollten auch die Funktion "file_get_contents" durch "curl" ersetzen.

Simon Marc
quelle
Simon, vielen Dank für dein Beispiel. Ich möchte nur sicher gehen: Angenommen, ich habe eine Ressource namens Benutzer, dann muss ich die API-Datei in Folgendes einfügen : mydomain.com/api/user Richtig?
Sharon Haim Pour
Sie können die Datei wie gewünscht benennen. Aber ja, es ist viel besser, die Datei mit einem expliziten Namen aufzurufen. Schauen Sie in meine API-Datei, ich überprüfe den get-Parameter und rufe dank dieses Wertes eine Funktion auf. Sie können user.php einschließen und eine Funktion aufrufen, die sich in dieser Datei befindet. Oder Sie können die Datei unter api / user ablegen und die Parameter von hier aus verarbeiten.
Simon Marc
Grundsätzlich muss ich die Server-Routing-Tabelle aktualisieren, um bestimmte URLs einer bestimmten PHP-Datei auf dem Server zuzuordnen. Richtig?
Sharon Haim Pour
1
Ja, aber genau wie beim Erstellen einer normalen Website senden Sie nur die Informationen zurück, die Sie ändern.
Simon Marc
6
Dies verwendet nur "GET" und betrachtet niemals die Anforderungsmethode, daher ist es nicht RESTful . Ein Beispiel finden Sie unter stackoverflow.com/a/897311/1766230 und en.wikipedia.org/wiki/…
Luke,
34

Im Jahr 2013 sollten Sie so etwas wie Silex oder Slim verwenden

Silex-Beispiel:

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(); 

Schlankes Beispiel:

$app = new \Slim\Slim();
$app->get('/hello/:name', function ($name) {
    echo "Hello, $name";
});
$app->run();
holographisches Prinzip
quelle
1
Vielen Dank. Ich habe Slim benutzt und in wenigen Minuten lief eine nackte API.
user12345
Was würden Sie für eine kompliziertere (detaillierte) API empfehlen? Slim ist praktisch, aber alle Funktionen befinden sich in einer einzigen Datei, sodass die Lesbarkeit ziemlich schwierig ist.
Ilker Baltaci
2
@IlkerBaltaci Mit Silex können Sie die Controller in Klassen extrahieren. Hier finden Sie eine gute Zusammenfassung und einige der Vor- und Nachteile der Verwendung eines Mikro-Frameworks im Vergleich zu einem Full-Stack-Framework igor.io/2012/11/09/scaling-silex.html . Ich persönlich bevorzuge Silex, da es mir die wichtigsten Dinge gibt und ich den Rest meines Stapels auswählen kann.
Holographisches Prinzip
10

Das ist so ziemlich das gleiche wie beim Erstellen einer normalen Website.

Normales Muster für eine PHP-Website ist:

  1. Der Benutzer gibt eine URL ein
  2. Der Server erhält die URL, analysiert sie und führt eine Aktion aus
  3. In dieser Aktion erhalten / generieren Sie alle Informationen, die Sie für die Seite benötigen
  4. Sie erstellen die HTML / PHP-Seite mit den Informationen aus der Aktion
  5. Der Server generiert eine vollständige HTML-Seite und sendet sie an den Benutzer zurück

Mit einer API fügen Sie einfach einen neuen Schritt zwischen 3 und 4 hinzu. Erstellen Sie nach 3 ein Array mit allen Informationen, die Sie benötigen. Codieren Sie dieses Array in json und beenden Sie diesen Wert oder geben Sie ihn zurück.

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

Das alles für die API. Für die Client-Seite können Sie die API über die URL aufrufen. Wenn die API nur mit get call funktioniert, denke ich, ist es möglich, einfach zu machen (Zur Überprüfung verwende ich normalerweise Curl).

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

Es ist jedoch üblicher, die Curl-Bibliothek zu verwenden, um einen Anruf abzurufen und zu senden. Sie können mich fragen, ob Sie Hilfe beim Locken benötigen.

Sobald Sie die Informationen von der API erhalten haben, können Sie die 4 und 5 Schritte ausführen.

Suchen Sie im PHP-Dokument nach json-Funktion und file_get_contents.

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


BEARBEITEN

Nein, warte, ich verstehe es nicht. "php API page" was meinst du damit?

Die API ist nur die Erstellung / Wiederherstellung Ihres Projekts. Sie senden NIEMALS direkt das HTML-Ergebnis (wenn Sie eine Website erstellen) und werfen eine API. Sie rufen die API mit der URL auf, die API-Rückgabeinformationen, und verwenden diese Informationen, um das Endergebnis zu erstellen.

Beispiel: Sie möchten eine HTML-Seite schreiben, die Hallo xxx sagt. Aber um den Namen des Benutzers zu erhalten, müssen Sie die Informationen von der API erhalten.

Nehmen wir also an, Ihre API hat eine Funktion, die user_id als Argument hat und den Namen dieses Benutzers zurückgibt (sagen wir getUserNameById (user_id)), und Sie rufen diese Funktion nur unter einer URL wie Ihrer / api / ulr / getUser / id auf.

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

Von der Client-Seite aus tun Sie dies

    $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>

Der Client greift also niemals direkt auf die Datenbanken zu, die die Rolle der API übernehmen.

Ist das klarer?

Simon Marc
quelle
+1. Beachten Sie auch, dass die API den richtigen Inhaltstyp für die Antwort festlegen sollte. Für json siehe stackoverflow.com/questions/477816/the-right-json-content-type
Ben
Also sollte ich auf dem Server eine PHP-API-Seite haben, die alle Anfragen verwaltet?
Sharon Haim Pour
Nein, warte, ich verstehe es nicht. "php API page" was meinst du damit?
Simon Marc
Meine Frage ist, wohin sollen die API-Anfragen gerichtet werden? Zu welcher Datei auf dem Server?
Sharon Haim Pour
Welche Dateien Sie möchten, es ist genau das gleiche wie beim Erstellen einer Website, außer dass Sie die API von einem Client und nicht von einem Browser aus aufrufen. Aber für die API ändert sich nichts. Wenn Sie die URL auf dem Serveur erhalten, entscheiden Sie dank der Parameter get und post, was damit geschehen soll. Haben Sie bereits eine Website erstellt? Haben Sie ein Framework wie Cake, Symfony oder Zend verwendet?
Simon Marc
7

(1) Wie ... erstelle ich diese URIs? Muss ich an dieser URI einen PHP-Code schreiben?

Es gibt keinen Standard für die Einrichtung eines API-URI-Schemas, aber es ist üblich, durch Schrägstriche getrennte Werte zu verwenden. Hierfür können Sie verwenden ...

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

... um ein Array von durch Schrägstriche getrennten Werten im URI nach dem Dateinamen abzurufen.

Beispiel: Angenommen, Sie haben api.phpirgendwo eine API-Datei in Ihrer Anwendung und stellen eine Anfrage für api.php/members/3, dann $apiArgArraywird ein Array enthalten sein ['members', '3']. Sie können diese Werte dann verwenden, um Ihre Datenbank abzufragen oder eine andere Verarbeitung durchzuführen.

(2) Wie erstelle ich die JSON-Objekte, um sie als Antwort zurückzugeben?

Sie können jedes PHP-Objekt mit json_encode in JSON umwandeln . Sie möchten auch den entsprechenden Header festlegen.

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

All dies ist gut für eine API, die JSON zurückgibt, aber die nächste Frage, die Sie stellen sollten, ist:

(3) Wie mache ich meine API RESTful?

Dafür werden wir $_SERVER['REQUEST_METHOD']die verwendete Methode abrufen und dann basierend darauf verschiedene Dinge tun. Das Endergebnis ist also so etwas wie ...

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);

Quellen: https://stackoverflow.com/a/897311/1766230 und http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services

Luke
quelle
2

Ich weiß, dass diese Frage akzeptiert wird und etwas alt ist, aber dies könnte für einige Leute hilfreich sein, die sie immer noch für relevant halten. Obwohl das Ergebnis keine vollständige RESTful-API ist, können Sie mit dem API Builder mini lib für PHP MySQL-Datenbanken einfach in über das Internet zugängliche JSON-APIs umwandeln.

Brannon
quelle
0

Wie Simon Marc sagte, ist der Prozess ähnlich wie bei Ihnen oder mir beim Surfen auf einer Website. Wenn Sie mit der Verwendung des Zend-Frameworks vertraut sind, gibt es einige leicht zu befolgende Tutorials, mit denen Sie das Leben ganz einfach einrichten können. Der schwierigste Teil beim Erstellen einer erholsamen API ist das Design der API. Wenn Sie sie wirklich erholsam machen, denken Sie an CRUD in Bezug auf die Datenbank.

Es kann sein, dass Sie wirklich eine xmlrpc-Schnittstelle oder etwas Ähnliches wollen. Was soll diese Schnittstelle Ihnen ermöglichen?

--BEARBEITEN

Hier habe ich mit Restful API und Zend Framework angefangen. Zend Framework Beispiel

Kurz gesagt, verwenden Sie keinen Zend Rest Server, er ist veraltet.

James Butler
quelle
Wenn Sie interessiert sind, werde ich in meinem Blog etwas über den Einstieg in ZF- und RESTful-Webdienste mit einem vollständigen Arbeitsbeispiel veröffentlichen.
James Butler