Saloon provides everything you need to build a great SDK for an API. Saloon already offers the ability to mock responses, provide authentication, implement OAuth2 boilerplate and even record your API requests in your tests so that you can write tests for the API integration without hitting the real API each time. With Saloon you will be up and running in minutes. No more writing HTTP boilerplate code!
Saloon has an official SDK template that you can clone straight from GitHub or download and use. It has everything you need to get started building an SDK, and even has a configuration command to set up the class namespace and file names. Click here to get started.
To start building an SDK with Saloon, we recommend that you create your base SDK class and extend the SaloonConnector class. The SaloonConnector class allows you to configure the base URL, default headers, configuration and apply plugins. You can also configure request mocking really easily, so this will come in really handy when you want to write tests for the API without making real requests.
Here is an example, I have created an SDK for the popular movie database API - TMDB. As you can see, I have defined the API base URL, as well as use the constructor to request that the person using the API always provides an authentication token.
<?php
namespace Sammyjo20\TMDB;
use Sammyjo20\Saloon\Http\SaloonConnector;
use Sammyjo20\TMDB\Responses\TMDBResponse;
use Sammyjo20\Saloon\Traits\Plugins\AcceptsJson;
class TMDB extends SaloonConnector
{
use AcceptsJson;
protected string $apiBaseUrl = 'https://api.themoviedb.org/3';
protected array $requests = [];
// Define the base URL.
public function defineBaseUrl(): string
{
return $this->apiBaseUrl;
}
// Constructor requires the token.
// Also allow to overwrite the API base URL for local servers.
public function __construct(string $token, string $baseUrl = null)
{
$this->withTokenAuth($token);
if (isset($baseUrl)) {
$this->apiBaseUrl = $baseUrl;
}
}
// Headers that will be used on all requests
public function defaultHeaders(): array
{
return [
'Content-Type' => 'application/json',
];
}
// Default Guzzle Config Options
public function defaultConfig(): array
{
return [
'timeout' => 30,
];
}
}
Now that we have created the SDK class that extends the SaloonConnector class, all we need to do is instansiate it and provide the API token.
<?php
use Sammyjo20\TMDB\TMDB;
$tmdb = new TMDB('my-api-token');
// Ready to make requests!
One of the ways that you can build SDKs in Saloon is by creating requests and then calling them from the SDK connector. This is the simplest way and you will get up and running really quickly with Saloon.
Firstly, you will need to make a SaloonRequest, this is exactly the same as making a normal request described in the documentation. Any requirements like data or pagination should just be provided in each request’s constructor.
When you have created the request, all that developers would need to do is run it! You can use the send
method to send a request straight away, or the request
method to instantiate the request.
<?php
use Sammyjo20\TMDB\TMDB;
$tmdb = new TMDB('my-api-token');
// Send a request straight away.
$response = $tmdb->send(new GetPopularMovies(page: 1));
// Or if you would like to do something with the request before sending it.
$request = $tmdb->request(new GetPopularMovies(page: 1));
With this method, it’s really simple to build your SDK. All you would need to do is create all the requests and then document them in your README. Developers using your SDK can just instantiate your SDK and then use the send
orrequest
methods.
Alternatively, you can define request classes and groups of requests on your SDK class by using the $requests
property to define requests. By using this method, you will have to register your API routes, but then developers can use methods to make API calls.
Here is an example using the same TMDB SDK as used earlier. You are able to register requests and request collections using Saloon.
$tmdb = new TMDB('my-api-token');
$request = $tmdb->movies()->getPopular(page: 1);
$response = $request->send();
If you define a $requests
array property on your connector. You can specify individual requests that will be converted into "magic" methods.
<?php
use Sammyjo20\Saloon\Http\SaloonConnector;
class TMDB extends SaloonConnector
{
protected array $requests = [
GetPopularMovies::class, // $tmdb->getPopularMovies()
];
// ...
}
Saloon will create a method for the request based on its name in camelCase. For example, our registered GetPopularMovies class will now have a method for it on the connector called GetPopularMovies
. When you call this method, Saloon will instantiate the GetPopularMovies class.
<?php
$tmdb = new TMDB('my-api-token');
$request = $connector->getPopularMovies(page: 1);
$response = $request->send();
You may want to use your own method names for requests on your connector. If you would like to do this, just add a key for the request to rename the method.
<?php
use Sammyjo20\Saloon\Http\SaloonConnector;
class TMDB extends SaloonConnector
{
protected array $requests = [
'get_popular_movies' => GetPopularMovies::class, // $tmdb->get_popular_movies()
];
// ...
}
You can also have many requests in an SDK, each separated into their own groups. Saloon also makes this easy with two ways of doing it. You can build custom request collections that will be returned automatically through magic methods. This is great if you would like to separate your SDK into different groups, like a "movies" group and a "tv shows" group containing different requests.
To get started, create a class and extend the base RequestCollection
abstract class. Request collections will be given an instance of the connector which you can access.
<?php
use Sammyjo20\Saloon\Http\RequestCollection;
class MoviesCollection extends RequestCollection
{
public function getPopular(int $page): array
{
// You can access $this->connector to make requests...
$request = $this->connector->request(new GetPopularMovies($page));
return $request->send();
}
// ... Your other methods...
}
{% hint style="info" %} The base RequestCollection class contains a constructor which provides the class with the connector instance. {% endhint %}
After you have created the class, specify the collection in your $requests
array on your connector.
<?php
use Sammyjo20\Saloon\Http\SaloonConnector;
class TMDB extends SaloonConnector
{
protected array $requests = [
'movies' => MoviesCollection::class,
];
// ...
}
Now you can call the custom collection and methods inside of it!
<?php
$tmdb = new TMDB('my-api-token');
$response = $tmdb->movies()->getPopular();
When using request collections and requests inside your SDK connector class, your IDE will not likely know that the methods exist since Saloon uses magic methods to call the requests. You can get around this by defining the methods in a doc-block above the class definition.
<?php
use Sammyjo20\Saloon\Http\SaloonConnector;
/**
* Define this in your doc-block.
*
* @method MoviesCollection movies
*/
class TMDB extends SaloonConnector
{
protected array $requests = [
'movies' => MoviesCollection::class,
];
// ...
}
You may wish to return a custom response instead of the default response to users to make it more developer-friendly. For example, if I wanted to return a TMDBResponse instead of SaloonResponse, I can create a custom response and define it on the SDK. Click here to read more.