Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating API versioning for my php application (Social App)

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



?>

...

UPDATE 1

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?

like image 953
Kárpáti András Avatar asked May 28 '19 21:05

Kárpáti András


People also ask

How create post API in PHP?

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.

What is the most common method of versioning a REST API?

There are several methods for managing the version of your API. URI path versioning is the most common.


3 Answers

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.

like image 90
deej Avatar answered Oct 22 '22 23:10

deej


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.

like image 45
shn Avatar answered Oct 22 '22 23:10

shn


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.

  • At the first choose a framework to code with. Maybe CodeIgniter, It is a easy-to-use one [Read followings]
  • Study about MVC design-pattern that most of frameworks support that and it will make your life easy when you want to maintenance or extend your existing code - This is necessary and easy enough, don't be scared
  • Cloning your whole project for backward compatibility is an overkill (assume you want to simply fix a bug in database access layer (Model/Repository), you should repeat it for all other versions) - You can achieve this by cloning just Controllers and defining new routes - [Still you have previous problem in business-logic in Controller layer because of design-pattern]
  • If you want a stronger approach you should start coding with Repository pattern with service layer (aka MVCS) and using a desired framework maybe Laravel to prevent code-coupling in different versions Controller layer and keep your shared Business-logic in Service layer (Separate it from Controller)
  • Document the important things In Code via using documentation comment tags such as @deprecated and @since to specify when some functionalities are deprecated or added (Because you cannot clear the deprecated functionalities until that the related version has been retired.) [check this link to get idea]
  • Study about versioning standards - SEMVER
  • Do not code in plain PHP
like image 1
Rancbar Avatar answered Oct 22 '22 21:10

Rancbar