I'm currently working on a Social Application.
I would like to have a versioning system on my PHP backend, but I don't know where to start: I have looked up a bunch of articles online, but I couldn't really understand what I've found.
Let's say my application is v1.0. Then I create a new version v2.0 and of course I update the PHP files too. After this, if someone hasn't updated their app from v1.0, I would like them to reach myapp.com/v1.0/
so that the app doesn't crash.
What would you recommend?
A typical PHP file of mine looks like this, for example:
<?php
// Include files
include_once ('../../config.php');
include_once (ROOT_DIR . '/config/includes.php');
$_USERDATA = Validator::validateUser($_POST["userId"], $_POST["session"]);
// Valid session
$qry = $db->prepare('SELECT n.id, n.type, n.time, n.isRead, n.postId, n.commentId, n.text, n.inReplyToCommentId, u.id as byUserId,
( SELECT COUNT(nu.id)
FROM notificationUsers AS nu
WHERE nu.notificationId = n.id ) as detail1,
( SELECT nu2.userId
FROM notificationUsers AS nu2
WHERE nu2.notificationId = n.id ORDER BY nu2.id DESC LIMIT 1 ) as latestUserId FROM notifications AS n LEFT JOIN userData AS u ON n.byUserId = u.id
WHERE n.userId = :userId ORDER BY n.time DESC');
$qry->bindParam(':userId', $_USERDATA["userId"], PDO::PARAM_INT);
$qry->execute();
$notificationsArray = $qry->fetchAll(PDO::FETCH_ASSOC);
$returnValue = array();
$returnValue["status"] = "1";
$returnValue["title"] = "Success";
$returnValue["message"] = "Downloaded notifications";
$returnValue["data_notifications"] = $notificationsArray;
exit(json_encode($returnValue));
?>
...
So I decided to do the following:
Placing every not shared file inside a folder like so:
/api/v1.0/file.php
But every resource for example (images) is outside the API
/resources/images/profilepictures/image.jpg
If I make a minor change, I just update the files within the api/v1.0/
folder.
Then, all the users that are using the Application v1.1
, they are requesting myapp.com/api/v1.1/
, but I redirect them to api/v1.0/ where I can present the users the right data (depending on if the request was from v1.0 or v1.1)
If the versions add up and I release a bigger update, I'll create a new folder with the name v2.0
, and so it goes...
Or what do you think? How should I do it?
Create the Model/Database. php file with the following contents. This is a database access layer class, which allows us to set up a connection to the MySQL database. Apart from the connection setup, it contains generic methods like select and executeStatement that allow us to select records from a database.
There are several methods for managing the version of your API. URI path versioning is the most common.
You're defining your architecture to future proof your design, which is good first step.
If you use a framework like Laravel or Symfony, you may keep your Models and Helpers directory common while making Controllers directory versioned with sub-directory like v1.x, v2.x etc.
It can make your life easy if you use a routing mechanism so let us say for example your v1.0 has 50 API endpoints and you're planning to modify 5 of them for v1.2 w/o backwards compatibility, in that case all rest of the 45 API endpoints would still be identical to v1.0 and you don't want to duplicate them in your v1.2 directory.
<?php
$versions = ["v1.0", "v1.2"];
route("/api/v1.0/foobar", "Controllers/v1.0/FoobarController@doSomething");
route("/api/v1.0/footar", "Controllers/v1.0/FoobarController@doTar");
route("/api/v1.2/foobar", "Controllers/v1.2/FoobarController@doSomething");
function route($endpoint, $controller)
{
// Logic to call function of a respective class/file
// and call previous version of an API if function/endpoint is not redefined in current version
}
?>
So in above case, when client calls /api/v1.2/footar, it should execute /api/v1.0/footar for API consumer.
I hope it helps.
Many other answers recommend using frameworks(Symfony etc.), which have advantages(more plug-and-play) and disadvantages(they have a lot of boilerplate to set up). I will focus on the pure native PHP solution to this problem with the following goals:
1. Keep code base as small as possible (very little repetition)
2. Support the most simple implementations (main benefit over framework solutions since less boilerplate)
This would be a sample implementation of the solution. index.php (first file):
<?php
require_once("path/to/config");
require_once("path/to/helpers/that/are/used/by/both/apis");
//This is where we decide where to route the request
if(strpos('/v1/', $_SERVER["REQUEST_URI"])) {
//This is api v1 so use api v1
require_once("path/to/api/objects/1.0");
} else {
//This is api v2 (or the default since most recent)
require_once("path/to/api/objects/2.0");
}
//Use the classes just imported to handle the request:
$apiObject = new Responder(); //Imported from one of the two api versions
echo $apiObject->handle();
?>
The code above distinguishes between the two API's based on parsing the URL and imports a different class for each.
For the imported API files, of each type, they could both extend the same parent API class(reducing total code), have the exact same method names, and behave differently for a portion, or all, of their methods.
This is a more elegant solution for really simple and even more complicated backend PHP services.
As i can see you want to write your APIs in plain PHP without any frameworks. I just want to lead you to a correct way and give you some vision to starting server-side development in PHP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With