Reading Time: 6 minutes

PHP developers often use an environment composed of Linux, Apache, MySQL, PHP — often this environment is called LAMP (Linux, Apache, MySQL, PHP). Many applications are developed on LAMP, however, for most of those applications, there is no API to easily connect them. In this article, you will learn first how to design an API for your existing applications. In the later portion of this article, you’ll learn how to code your API interface to give access to your application implementation.

Mulesoft uses the API-led connectivity model to create application networks. That way is also called contract-first approach. 

latest report
Learn why we are the Leaders in API management and iPaaS

Unfortunately, that approach is not always possible. For example, you already have a running application and you want to re-use part of that application in your application networks. To make it, you will have to design your API and connect it to your application. This approach is called “Meet in the middle,” that’s probably the worst approach in terms of development but sometimes you don’t have choices.

Here is what you will do to solve this problem:

  1. Find what functionalities from your application you want to reuse.
  2. Create an API specification to specify those functionalities.
  3. Create the interface for the API specification.
  4. Connect the API specification to your application implementation.
  5. Listen to the correct HTTP resource.

#1 Functionality to expose

Your application proposes a calendar to the customers, you want to be able to see the calendar outside of your application thanks to a Rest API.

Your goal is to design a REST API, implement the interface and link it to the existing code.

Of course, if it is possible you can try to get a similar structure and similar field names that what you already develop in your PHP. (meet in the middle approach)

#2 API specification

Based on the existing PHP code, you now have to create the API specification.

Here is an example of a RAML specification that you can create using Anypoint API Designer:


#%RAML 1.0
title: Calendar

types:
 calendar: !include datatype/calendarDataType.raml

mediaType:
 - application/json

/calendar/{year}/{month}:
 uriParameters:
   year:
     type: string
     pattern: "[12][0-9]{3}"
   month:
     type: string
     pattern: "0[1-9]|1[0-2]"
 get:
   responses:
     200:
       body:
         type: calendar   

The calendar data type:


#%RAML 1.0 DataType
type: object
properties:
 month:                   string
 year:                    string
 days_in_month:           string
 first_day_of_the_month:  string
 events:
   type:                  array
   items:                 !include eventDataType.raml

The event data type:


#%RAML 1.0 DataType
type: object
properties:
 date:                string
 text:                string
 url:                 string
 type:                string
 time:                string

Of course, the event data type is probably a simple mapping of data type contained in your database.

The best practice is to provide an example of the data send back by the API into the specification, in this case:


{
  "month": "03",
  "year": "2020",
  "days_in_month": "31",
  "first_day_of_the_month": "Sun",
  "events": [
    {
      "date": "2020-03-05",
      "text": "Meeting Week 1",
      "url": "/news/meeting-05-03-2020/",
      "type": "Weekly meeting",
      "time": "20:30:00",
    },
    {
      "date": "2020-03-12",
      "text": "Meeting Week 2",
      "url": "/news/meeting-2020-03-12/",
      "type": "Weekly meeting",
      "time": "20:30:00",
    }
  ]
}

#3 Interface creation

In this section, you have to manually implement the PHP code attached to the specification. In the following code, this part is called CODE SECTION : INTERFACE. In that part, you have to be sure that your API specification is respected. For example, you can re-use regular expressions from your specification into your PHP code.


<?php 
// CODE SECTION : BACKEND FUNCTION
function my_calendar($month,$year)
{
  $types  =["audio conf","video conf","meeting"];
        $urls   =["http://meet/audio","http://meet/video","N/A"];
        $texts  =["Audio metting with a customer","Meeting with Team A","Team meeting"];

        for ($i=0;$i<rand(2,5);$i++)
        {
            $random=rand(0,sizeof($types)-1);
            $infos[$i]=new stdClass();
            $infos[$i]->date=$year.'-'.$month.'-'.sprintf("%'.02d", rand(0,28));
            $infos[$i]->text=$texts[$random];
            $infos[$i]->url=$urls[$random];
            $infos[$i]->type=$types[$random];
            $infos[$i]->time="20:00:00";
        }
        return $infos;
}

// CODE SECTION : INTERFACE
$year_month_regex="#^/calendar/([12]\d{3}/(0[1-9]|1[0-2]))$#";
    
if (preg_match($year_month_regex,$_SERVER['REQUEST_URI'],$match))
{
  // CODE SECTION : IMPLEMENTATION
  header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . 'GMT' );
        header('Cache-Control: no-cache, must-revalidate');
        header('Pragma: no-cache');  
        header('Content-Type: application/json');

        $cal  =explode("/", substr($match[0],-7));
        $year =$cal[0];
        $month=$cal[1];
       
        $infos=new stdClass();
        $infos->month                   = $month;
        $infos->year                    = $year;
        $infos->days_in_month           = date('j', mktime(0,0,0,$month+1,0,$year));
        $infos->first_day_of_the_month  = date('D', mktime(0,0,0,$month,1,$year));        
        
        $infos->events=my_calendar($month,$year);
        
        echo json_encode($infos);                    
    }
    else 
    {                        
        header("Status: 404 Not Found", false, 404);
    }        

?>

You can download the code here

#4 Connect the interface to the application

Once the interface is ready, you have to connect it to the feature that you want to expose. In the previous code example it is done in the CODE SECTION : IMPLEMENTATION. Here is a description of the different steps:

  • Specify that you don’t want cache. Here it is the role of the custom function header_no_cache.
  • Specify the return type: application/json.
  • Get the required information from the URL: date and year.
  • The last step is to create an object to return and to return it as JSON: echo json_encode($infos).

#5 Listen to the correct HTTP resource

In the previously created code the url to access to the REST API is: http://www.site.com/calendar/index.php

The url we want to respond is: http://www.site.com/calendar/2020/03

To do that you have to create an Apache rule to redirect all the traffic http://www.site.com/calendar/* to http://www.site.com/calendar/index.php

You have to put the following .htaccess file in your application /calendar directory.


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /calendar/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /calendar/index.php
</IfModule>

Conclusion

You are now able to create a REST API in front of your PHP program to expose your services.

The next steps will be:

  • Publish the specification in Anypoint Exchange.
  • Link the Anypoint Exchange previously created asset to your running PHP code by setting the corresponding endpoint in the tool.
  • Create the documentation of your service in Anypoint Exchange.
  • Engage internal users with Anypoint Exchange.
  • Engage external users with the Anypoint Exchange public portal or API Community Manager.

You can find the specification on my Anypoint Exchange public portal and the PHP code on GitHub.