Back to all blogposts

How do you create an API in PHP and successfully standardize endpoints? With JSON-API, of course!

Marcin Szołtysek

Marcin Szołtysek

Senior PHP Developer

Dear developers, have you ever worked on a brand new application programming interface? Those of you who have probably known that before writing the first endpoint, you need to determine the format in which the request parameters will be passed and the response returned. For inexperienced developers that might be a bother, but I just might have the solution to this annoying problem. It’s JSON-API — a set of ready-made rules and recommendations, specifying all elements of the endpoint interface. So if you want to learn how to create an API in PHP with JSON API, follow me!

Creating an API with PHP code poses some interesting challenges to any web developer. There aren’t that many PHP frameworks that cover this area and its various aspects such as accessing databases, CRUD operations, access control, environment variables, database functions and more.

JSON-API has many qualities that make it worthwhile, including defining API endpoints, solutions for HTTP requests and more for creating web services.

Let’s take a deeper look at JSON-API.

What you’ll learn

In this article, you’re going to learn more about:

  • what JSON-API is and the unique way it works with PHP,
  • the 5 query string parameters relevant in JSON-API,
  • the server responses typical for JSON-API,
  • easy ways to get started with JSON-API for PHP developers specifically,
  • further learning resources.

So what’s the deal with JSON-API and PHP development?

Why do I need JSON-API? Simple PHP API development

Since there is no single right solution for the API parameter schema and responses, any approach that coherently and consistently formulates all input and output data is sufficient. Meeting these conditions will ensure easy integration of customer applications and reduce the number of errors during development.

Having said that, if you decide to use your own structure, you should think about a few things. In terms of requests, it will be filters, pagination and sorting. As for the responses – formatting returned objects fields, nesting of related objects, metadata (e.g. pagination) and error messages.

It’s common practice to start implementation without comprehensive interface planning and then adding further elements as the work progresses and new needs arise. However, this strategy can lead to losing consistency and creating a pattern too difficult to process automatically in the client application.

If you don’t have your own proven and refined approach to this issue, it is worth applying a ready-made solution. I suggest looking for ideas used by a wider group of programmers – this way you will surely avoid all the aforementioned problems, save time and focus on the implementation of business logic and other priority tasks. And that’s where JSON API comes in.

What is JSON-API? Web application importance

Citing the standard documentation, JSON API is a specification of how to send requests to read or modify a resource, and how the database server responds to those requests. In short, it allows for database connection and interaction with MySQL database table or any other database. The data transport format is JSON, and requests and responses are sent as:

Content-type: application/vnd.api+json

💡 Building a restful API from scratch?

Request to the server according to JSON-API

So let’s start by building requests, focusing on resource collection (GET requests). Here, all relevant data is transmitted in the URL. The JSON API standard specifies how to name query string parameters. The parameters are divided into five groups:

  1. Pagination
  2. Sorting
  3. Filters
  4. Range of returned fields
  5. Including related objects

For this article, we will use a hypothetical endpoint to download a list of products:

GET /products

1. Pagination parameter

Pagination is the simplest of the aforementioned parameters. It typically consists of two values, specifying the number of elements per one “page” and which “page” is to be returned. There are various strategies based on page number and size, or limit and offset. In terms of pagination, JSON API only specifies that the parameter should be an array called page, leaving you the freedom to choose the strategy. Here’s the JSON API example:

GET /products?page[limit]=20&page[offset]=60 # return products 61-80

GET /products?page[size]=20&page[number]=2   # return products 41-60

2. Sorting parameter

Sorting results in accordance with the JSON API recommendations should be carried out using the sort parameter. The parameter values should refer to the field names of returned objects (although this is not a strict requirement, you’re allowed to bend this rule a little). Example – sort by title:

GET /products?sort=name

It is possible to sort by more than one attribute. The subsequent attributes should be separated by a comma. On the server’s side, sorting should be carried out in order from the first attribute to the last – in the example below you should sort first by the date of publication and then by title.

GET /products?sort=publish_date,name

The default sorting direction is ascending (ASC). In order to change the direction to descending (DESC), any of the attributes should be preceded with a minus sign, as presented below:

GET /products?sort=-publish_date,name

The specification also provides sorting by fields from related objects. In this case, you should provide a path consisting of attribute names that lead to the desired field, separated by periods. Example – sorting by product category name:

GET /products?sort=category.name

Are you searching for developers familiar with developing PHP-based APIs?

In the Zinio project, our developers created a highly customized and scalable backend API for a popular magazine subscription system. Before they struggled with high traffic, now they enjoy it.

3. Filters parameter

Filtering results is probably the most complex issue here. But fear not – JSON API leaves a lot of freedom, requiring only that all filtering data is sent in an array parameter called (unsurprisingly) a filter. For example, filters can be passed in the request:

GET /products?filter[name]=SSD drive

Similarly to sorting, filtering can apply to the associated object attribute. In a situation like that, you can use the same syntax:

GET /products?filter[category.name]=Storage

We can assume that the basic filters are strict filters, i.e. they require a perfect match of the filter value to the attribute. If you need to filter the range of values (e.g. minimum and/or maximum value for a numeric attribute) you can add suffix __min or __max (double underscore is necessary so that the server can distinguish the range filter from the field ending with the word min or max). Let’s look at an example:

GET /products?filter[price__min]=100&filter[price__max]=500

Depending on your domain requirements, you can define additional suffixes and corresponding filtering methods, e.g. __in, __like etc. Remember to maintain consistency – a specific suffix (or its absence) must cause the same behavior in every filter. For example, if it is assumed that filters without a suffix work on the exact match principle, there can be no case of a filter that works differently.

4. Range of returned fields

The range of returned fields can reduce the amount of data in the server response. For example, when downloading a list of items, you may not always need to download the date when the item was added to the offer, or availability in various stores – you may only need the name and price. In such cases, you can explicitly provide in the request which fields are to be returned in the response. For this purpose, the JSON API reserves a parameter called fields. The syntax is as follows – fields should be listed after the decimal point. Fields from the object to which the request relates should be explicitly mentioned:

GET /products?fields=name,price,publish_date

Fields from related objects should be listed with the path leading to the object. The following example specifies that a product with id = 1 should be returned, together with the name of the category and the name and shipment price available for the packaging in which the product is delivered.

GET /products/1?fields[category]=name&fields[package.shipping]=name,price

5. Including related objects

I’ve already mentioned including related objects several times in this article (just checking if you were paying attention 😏). You need to indicate in the request which of the objects associated with the main object should be included in the response. A good example is returning products along with customer feedback. This allows you to reduce the number of queries to the server, which always positively influences the performance of the application. According to the JSON API rules, the request parameter for this purpose is called include. Its value is a list of paths to the desired associations, separated by a comma:

GET /products?include=reviews,category

Just like in previous cases, reference may be made to further associations:

GET /products?include=reviews.author

how to create API in PHP JSON meme fridy the 13th character Jason Voorhees
oopsie…

Server responses according to JSON-API

The content of the GET request response must be saved in JSON format. The structure of the response is strictly defined. The first level of response must contain at least one of the keys: data, errors, meta. The meta key can return any additional information. An example of its use can be information about the pagination of results:

The errors key should contain messages from potential errors. JSON API defines this key as an array of objects. Each of them may have several of the defined keys. The most important of them are status, code, title. Example:

The data key is intended for storing the main content of the response, i.e. in most cases the content of objects returned by an endpoint. This response section is most closely defined in the JSON API. The returned resource (single object or array of objects) must appear directly under the data key. Each resource must be returned as an object containing type and id keys.

The first key must contain a unique, global name for the object type, which is immutable within the entire API for each object (e.g. product). The second key is the identifier – it can successfully be the primary key from the database. Other allowed keys are attributes, relationships, links, meta. From this set, attributes and relationships are the most commonly used for transporting other object fields and information about related objects. Below you can find an example using the most important of the keys I’ve just described:

GET /products

Please note that the relationships section doesn’t show related object fields, only types and identifiers. This information is sufficient for the client application to automatically read further objects automatically.

Related objects can also be returned in the same request. For the server to add these objects to the response, they must be listed in the include parameter. As a result, the JSON document with the response will receive another key called included, which will contain the full data of the indicated objects (or only selected fields if they are specified by the fields parameter). Example:

GET /products?include=reviews,category

As the example shows, the included section contains data about the objects previously listed in the product relationships section.

when third party API sends xmlinstead of json meme guy with a facepalm

💡 PHP for life? If yes, check out

JSON-API in PHP applications

The tobyzerner/json-api-php project allows quick implementation of the JSON API standard in PHP applications. You can quickly build responses under all the rules described above. Installation with the help of a composer:

composer require tobscure/json-api

Request parameters

To parse the parameters in the request, you can use theParametersclass. It provides access control allow methods to the parameters (described in the first part) defined by the JSON API standard. As for the PHP file:

Arrays with acceptable names should be provided for include and sort parameters (parameters from URL will be automatically validated for correctness). You can specify the maximum limit and default offset for pagination.

Response building

To build a response in the controller of a given endpoint, all you have to do is create a collection object or a single resource, specifying in the constructor objects for serialization (e.g. Doctrine entities) and a serializer able to serialize a given object:

At this stage, you can indicate which of the related objects should be added to the response…

…and what fields of objects should be included in the response:

Then build a document and serialize it:

As you can see, the Document object enriches the response with metadata:

Serialization

Resource and Collection objects require you to point a serializer for each resource that you upload. At the same time, an abstract class is available, which can be used as a base to create your own serializers. In the minimum version, it is only necessary to implement a method that returns the attributes of a serialized object:

The $type property is used in the type key in the endpoint response. By default, the id field uses the $id of the serialized object, but you can add your own serializer method that will be used to retrieve the id:

For bundle mechanisms to be able to add related objects to responses, the serializer must have methods by which these objects can be retrieved and serialized. The names of these methods must be exactly the same as the names of the attached relations. For example, for product-related reviews and categories:

The mechanism above may work recursively, for example: by adding the user($review) method in the ReviewSerializer class, you can attach reviews with user data to the product.

How to create API in PHP – summary

The information I provided in this article only addresses some of the most important issues regarding the JSON API standard. For now, we established that:

  • JSON-PHP offers great ready-made solutions to a lot of typical API development problems that arise in PHP development,
  • doing standard projects using JSON-PHP is simple enough but the complex ones will still have you work on custom code so it’s not a cure-all for your PHP woes,
  • it’s still hugely helpful though!

So when it comes to basics, you are already a pro!

Need more information on the JSON-API standard?

But if you want to master the advanced features, you need to continue your research. There a lot of interesting JSON-API resources for you out there.

If you are interested in creating API in PHP, or want to create REST API in PHP, simple REST API, simple CRUD REST API etc., then the documentation of JSON API and practical examples for the representational state transfer are available for you on the project home page.

The Symfony bundle can be found on JSON-API Github. It includes elements such as request method, access control, PHP data objects, file structure, PHP classes and more.

Good luck! 👍

Are you looking for developers who can create highly efficient APIs?

Contact us and schedule free consultation. Ask us anything about your next project.

The Software House is promoting EU projects and driving innovation with the support of EU funds

What would you like to do?

    Your personal data will be processed in order to handle your question, and their administrator will be The Software House sp. z o.o. with its registered office in Gliwice. Other information regarding the processing of personal data, including information on your rights, can be found in our Privacy Policy.

    This site is protected by reCAPTCHA and the Google
    Privacy Policy and Terms of Service apply.

    We regard the TSH team as co-founders in our business. The entire team from The Software House has invested an incredible amount of time to truly understand our business, our users and their needs.

    Eyass Shakrah

    Co-Founder of Pet Media Group

    Thanks

    Thank you for your inquiry!

    We'll be back to you shortly to discuss your needs in more detail.