Skip to content

Instantly share code, notes, and snippets.

@tops
Created January 24, 2017 09:16
Show Gist options
  • Select an option

  • Save tops/b514d0648e5efce0ca89e8387955a228 to your computer and use it in GitHub Desktop.

Select an option

Save tops/b514d0648e5efce0ca89e8387955a228 to your computer and use it in GitHub Desktop.
Objektorienterat enkelt REST-API i PHP
<?php
#
# Den här klassen startar upp vårt API och hämtar allt det vi behöver från själva HTTP-anropet
#
class API{
private $method, // GET, POSt, PUT, DELETE ...
$input, // Data sent with request
$resource, // REST Resource to call
$resource_id, // Id of the resource
$request; // The rest of the URL
# En "magisk" get funktion som gör att det går att hämta alla våra variabler inom objektet fast att de är privata, men vi kan inte lägga in värden i dem utanför objektet
function __get($k){
return $this->$k;
}
# Här är konstruktorn som körs när objektet skapas
function __construct(){
# Get the HTTP request method
$this->method = $_SERVER['REQUEST_METHOD'];
# Get the input data fot POST, PUT and DELETE request
$input = [];
parse_str(file_get_contents("php://input"), $input);
$this->input = $input;
# Get and split the URL of the request into parts
$path = array_keys($_GET)[0];
$request = explode('/',$path);
$request = array_filter($request, function($v){ return $v !== '';});
$request = array_values($request);
# Get the first resource of the request if exists
if(count($request) > 0)
$this->resource = array_shift($request);
# Get the forst resources id if exists
if(count($request) > 0)
$this->resource_id = array_shift($request);
# Save the rest of the path
$this->request = $request;
}
}
<?php
#
# Den här klassen ska köras om vi anropat resursen usebookr i vårt API genom /?/book
#
class _book extends Resource{ // Klassen ärver egenskaper från den generella klassen Resource som finns i resource.class.php
# Den här funktionen skriver över den ärvda funktionen output() från Resource
function output(){
echo "Nonono";
}
function GET(){
echo "GET book";
}
function POST(){
echo "post book";
}
function PUT(){
echo "put book";
}
function DELETE(){
echo "DELETE book";
}
}
<!--
Den här filen användet JS för att koppla upp till vårt API och visa att det fungerar
-->
<!doctype html>
<html>
<head>
<script src='http://code.jquery.com/jquery-latest.min.js'></script>
<script>
$(function(){
$("#user_id").on('change', function(e){
$.ajax({
url: "./?/user/"+e.target.value,
data: "",
type: "GET",
dataType: 'json',
success: function(data){
console.log(data);
$("#user").html(data.username);
}
});
});
$("#user_delete").on('change', function(e){
$.ajax({
url: "./?/user/"+e.target.value,
data: "",
type: "DELETE",
dataType: 'json',
success: function(data){
console.log(data);
$("#user").html("Done!");
}
});
});
});
</script>
</head>
<body>
<input type='text' id='user_id'>
<input type='text' id='user_delete'>
<div id='user'></div>
</body>
</html>
<?php
#
# Det här är indexfilen som hela API:et utgår från
#
# Här sätter vi en HTTP-header som säger att svaret kommer som json
header('Content-Type: application/json');
# En vanlig uppkoppling till databasen samt att vi sätter uppkopplingen till uft8
$db = mysqli_connect("localhost","root","root","apitest");
mysqli_query($db, "SET NAMES utf8");
# Här inkluderar vi två filer som innehåller två classer som behövs för vårt API
require_once "api.class.php";
require_once "resource.class.php";
# Här skapas ett API-object av classen API
$API = new API();
# Vi skapar en sträng som består av ett _ samt namnet på den resurs vi efterfrågar, exempelvis som vi anropar /?/user kommer vår sträng blir _user. Detta gör vi för att skapa lite säkerhet så man inte kan anropa klasser/objekt som vi inte vill ska kunna köras via vårt API
$class = "_".$API->resource;
# Vi inkluderar filen med klassen för den resurs som efterfrågats, exempelvis user.resource.php och denna fil innehåller en class med _user
require_once $API->resource.".resource.php";
# Här händer "magin" och vi skapar ett objet av den klass som motsvarar den resurs som efterfrågats, exempelvis _user
# Till det objekt som skapas skickar vi med två saker till konstruktorn (funktionen som körs när objektet skapas)
# De två parametrar vi skickar med är resursens id (ex. 15 i /?/user/15) och sen resten av URL:en som en array (Ex. i /?/user/15/friends/all kommer arrayen innehålla [0] "friends" och [1] "all")
$resource = new $class($API->resource_id, $API->request);
# Här anropar vi en metod/funktion i det objekt som skapas med samma namn som den HTTP-metod som anropats, exempelvis GET() eller POST()
$method = $API->method;
$resource->$method($API->input, $db);
# Här körs metoden/funktionen output() i det objekt vi skapat
$resource->output();
<?php
#
# Det här är den generells klassen Resource som våra olika resurser ärver från så att de får med alla de funktioner och variabler som denna klass har så vi inte behöver deklarera dem i varje resurs vi skapar
#
class Resource{
private $id, $request;
# En generell konstruktor som gör samma sak som vår konstruktor i _user klassen
function __construct($resource_id, $request){
if(is_numeric($resource_id))
$this->id = $resource_id;
$this->request = $request;
}
# En generell output() funktion som skriver ut det egna objektet som JSON
function output(){
echo json_encode($this);
}
}
<?php
#
# Den här klassen ska köras om vi anropat resursen user i vårt API genom /?/user
#
class _user extends Resource{ // Klassen ärver egenskaper från den generella klassen Resource som finns i resource.class.php
# Här deklareras de variabler/members som objektet ska ha
public $username, $real_name, $id, $users, $request;
# Här skapas konstruktorn som körs när objektet skapas
function __construct($resource_id, $request){
# Om vi fått med ett id på resurser (Ex /?/user/15) och det är ett nummer sparar vi det i objektet genom $this->id
if(is_numeric($resource_id))
$this->id = $resource_id;
# Vi sparar också det som kommer med i URL:en efter vårt id som en array
$this->request = $request;
}
# Denna funktion körs om vi anropat resursen genom HTTP-metoden GET
function GET($input, $db){
# Här kollar vi om det efterfrågats en "collection" inom resursen, exempelvis "friends" i URL:en /?/user/15/friends
$collection = "";
if(isset($this->request[0])) $collection = $this->request[0];
# Beroende på vilken "collectsion" som anropats gör vi olika saker
switch($collection){
case 'friends':
echo "friends!";
break;
case 'books':
echo "books!";
break;
case 'posts':
echo "posts!";
break;
default: // Om det inte är en collection, eller om den inte är definierad ovan
$this->getUserData($input, $db);
}
}
# Den här funktionen är privat och kan bara köras inom objektet, inte utanför
private function getUserData($input, $db){
if($this->id){ // Om vår URL innehåller ett ID på resursen hämtas bara den usern
$query = "
SELECT *
FROM users
WHERE id = $this->id
";
$result = mysqli_query($db, $query);
$user = mysqli_fetch_assoc($result);
$this->username = $user['username'];
$this->real_name = $user['real_name'];
}else{ // om vår URL inte innehåller ett ID hämtas alla users
$query = "
SELECT *
FROM users
";
$result = mysqli_query($db, $query);
$data = [];
while($row = mysqli_fetch_assoc($result)){
$data[] = $row;
}
$this->users = $data;
}
}
# Denna funktion körs om vi anropat resursen genom HTTP-metoden POST
function POST($input, $db){
# I denna funktion skapar vi en ny user med den input vi fått
$username = mysqli_real_escape_string($db, $input['username']);
$real_name = mysqli_real_escape_string($db, $input['real_name']);
$query = "
INSERT INTO users
(username, real_name)
VALUES ('$username','$real_name')
";
mysqli_query($db, $query);
}
# Denna funktion körs om vi anropat resursen genom HTTP-metoden PUT
function PUT($input, $db){
# I denna funktion uppdateras en specifik user med den input vi fått
# Observera att allt uppdaterad varje gång och att denna borde byggas om så att bara det vi skickar med uppdateras
if($this->id){
$username = mysqli_real_escape_string($db, $input['username']);
$real_name = mysqli_real_escape_string($db, $input['real_name']);
$query = "
UPDATE users
SET username = '$username',
real_name = '$real_name'
WHERE id = $this->id
";
mysqli_query($db, $query);
}else{
echo "No resource given";
}
}
# Denna funktion körs om vi anropat resursen genom HTTP-metoden DELETE
function DELETE($input, $db){
# I denna funktion tar vi bort en specifik user med det ID vi fått med
if($this->id){
$query = "
DELETE FROM users
WHERE id = $this->id
";
mysqli_query($db, $query);
}else{
echo "No resource given";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment