8

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?

Rahul
  • 18,271
  • 7
  • 41
  • 60
Kárpáti András
  • 1,221
  • 1
  • 16
  • 35
  • does this help ? https://stackoverflow.com/questions/389169/best-practices-for-api-versioning –  May 30 '19 at 21:39

3 Answers3

8

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.

deej
  • 2,536
  • 4
  • 29
  • 51
3

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.

shn
  • 865
  • 5
  • 14
1

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
Rancbar
  • 184
  • 12
  • Hmm, interesting. I've read your answer, I read the versioning standarts you linked, it was very useful thank you, and your proposing to user MVC design pattern with a framework is also useful. One thing is: I don't have views. My iOS application needs only the data. What do you think, should I still stick with a framework, or in this case pure PHP is enough? – Kárpáti András May 31 '19 at 07:32
  • Absolutely you need a framework to work with. And the purpose of these types of design patterns is about separating the layers of codes in programming. you can use MVC design pattern even if you don't have any View layer, just for APIs.. – Rancbar May 31 '19 at 08:02
  • I'm downvoting purly because you said Code Igniter instead of Symfony which a huge portion of the internet is built on top of. – Lulceltech May 31 '19 at 20:14
  • Dear @Lulceltech. At the first, the market-share of CI **for projects** is quite equal to Symphony or even bigger than Symphony. Second, as you can see, this question is not about framework competitions or "What is best PHP framework" and i wrote a notice why i suggest CI, and why maybe Laravel would be good choice and etc... I will say again that starting with a quick-start one like CI is better than plain PHP. But there is more frameworks like Laravel, Symphony, Yii, CakePHP, Lumen, Phalcon and so on to choose. – Rancbar May 31 '19 at 21:10
  • @Rancbar you do understand Laravel, wordpress, any many other CMS's and Frameworks are built on top of Symfony? Symfony powers a huge portion of the internet. – Lulceltech Jun 03 '19 at 15:21
  • As you can see i made `for projects` sentence bold for you to make you understand i'm not speaking about count of running instances of projects, but projects instead. But again, this thread is not about **Which is the best PHP framework** so this conversation is worthless and **every framework has its own's use cases**. – Rancbar Jun 05 '19 at 06:18
  • Using a framework will make you life easier. No use to invent the wheel for the umptienth time. I would choose a very modular framework e.g. Symfony or even the slimmer variations like Laravel or Silex. They help you with security and usually direct you in a good direction with the code structure. – Calamity Jane Jun 05 '19 at 12:14