On Monday, I wrote about serverless and functions-as-a-service.
But I'm going to let you in on a little secret: I think serverless is kind of overrated, and rarely use it for my own projects.
Don't get me wrong! I love small little functions and microservices. And as serverless vendors go, I think Cloudflare is the best and simplest option.
But I also think it's a lot easier to just drop a PHP file on my server and run with it. And today, I wanted to share with you exactly how I do that.
Let's dig in!
How it works
At a high level, it works like this…
- I create a PHP file for my API endpoint. For example, an endpoint to join a newsletter might be
newsletter.php
. I keep all of these in a/api
directory on my server. - I make a call to the PHP file using the JavaScript
fetch()
method. This causes the file to run, do some stuff, and return a JSON response. I could use a server-side language to do this, too.
That's the high level, but let's look at some of the implementation details.
PHP utility methods
I use a small handful of PHP utility methods to make getting data and responding to API requests a little bit easier.
First the get_method()
function tells me which HTTP method was used for the request: GET
, POSt
, and so on.
<?php /** * Get the API method * @return String The API method */ function get_method () { return $_SERVER['REQUEST_METHOD']; }
The get_request_data()
method returns an array (in JavaScript it would be an object of named key/value pairs) with all of the request data.
This includes query parameters on the endpoint itself, POST parameters, and any stringified objects or FormData
object values in the request body
.
<?php /** * Get data object from API data * @return Object The data object */ function get_request_data () { return array_merge(empty($_POST) ? array() : $_POST, (array) json_decode(file_get_contents('php://input'), true), $_GET); }
The send_response()
method set the HTTP response code (defaulting to a success code of 200
), returns a stringified JSON response, and ends the function.
<?php /** * Send an API response * @param * $response The API response * @param integer $code The response code * @param boolean $encode If true, encode response */ function send_response ($response, $code = 200) { http_response_code($code); die(json_encode($response)); }
In my PHP endpoints, I prefer to restrict access to Ajax requests (as-in, not let people directly access the file). The is_not_ajax()
function runs that check for me.
<?php /** * Check if request is not Ajax * @return Boolean If true, is not Ajax */ function is_not_ajax () { return empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest'; }
If you want to also call the file directly (with old-school form submissions, for example), you might either skip this function, or use it to conditionally control how the send_response()
function works.
For example, you might choose to echo
some text if the file is directly accessed.
An example API
I keep all of these utility functions in a helpers.php
file that I include in each of my API endpoint files, but for a single API endpoint, you can put them in the file directly.
At the top of the API file, the first thing I do is check if the request is_not_ajax()
. If it's not, I redirect the user back to wherever they came from.
<?php // Bail if not an Ajax request if (is_not_ajax()) { header('Location: ' . $_SERVER['HTTP_REFERER']); return; }
I also get the request $method
and extract any $data
from the request.
<?php // Bail if not an Ajax request if (is_not_ajax()) { header('Location: ' . $_SERVER['HTTP_REFERER']); return; } // Get the API method $method = get_method(); // Get any data sent with the request // Includes query parameters, post data, and body content $data = get_request_data();
Handling HTTP methods
I handle responses conditionally based on the request $method
used to make the call.
For example, if the $method
equals GET
, I might grab some data from my server or make an authenticated API call to another API. Then, I use the send_response()
method to respond with an array (equivalent to an object in JavaScript) of data.
<?php // GET request // Get some data and respond with it if ($method === 'GET') { // You'd normally do stuff here... // Let's just send back a success message send_response([ 'status' => 'success', 'message' => 'You did it, dude!', ]); }
For a POST
request, I might check to make sure the $data
object contains all of the required information first. If not, I use the send_response()
method to return an error response, passing in an object and error code as arguments.
If everything's fine, after saving my data and taking any server actions, I'll send back a successful response instead.
<?php // POST request // Store some data or something if ($method === 'POST') { // You'd normally do stuff here... // Example: Check that all required data was provided if (empty($data['favorite'])) { send_response([ 'status' => 'failed', 'message' => 'Please provide a favorite movie.', ], 400); } // If there are no issues, save your data or something... // Then, respond with a success send_response([ 'status' => 'success', 'message' => 'This movie was saved to your favorites!', ]); }
At the very end, I add a catchall response for any unsupported HTTP methods.
<?php // All other request methods send_response(array( 'code' => 405, 'status' => 'failed', 'message' => 'Method not allowed' ), 405);
Calling your endpoint
You can call your endpoint with the fetch()
method in JavaScript.
Use the path to your PHP file as the endpoint, and pass in an object with your method
, body
, and so on. If you're restricting your API to Ajax requests, make sure to include an X-Requested-With
header, with XMLHttpRequest
as its value.
fetch('/api/api.php', { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', }, body: JSON.stringify({ favorite: 'WALL-E' }) });
For GET
requests, include your parameters as query string parameters on the endpoint instead.
fetch('/api/api.php?favorite=WALL-E', { headers: { 'X-Requested-With': 'XMLHttpRequest', } });
A sample API endpoint
If you want to play around with this yourself, here's a sample API file you can download.
Drop it somewhere on a server (or run it locally). Then call it with some JavaScript using the fetch()
method.
I have a favor to ask. If you enjoyed this email, could you forward it to someone else who you think might also like it, or share a link to my newsletter on your favorite social media site?
Cheers,
Chris
Want to share this with others or read it later? View it in a browser.
0 Komentar untuk "[Go Make Things] How to create your own API endpoints with PHP"