🎁
What's new in v2
Version two of Saloon is an upgrade in everything you already love in version one but refines and improves your developer experience. It has many internal changes that make it more maintainable and lightweight. This results in a fantastic experience building API integrations or your next SDK.

Previously, Saloon had "Sammyjo20" in the namespace. This has now been removed so namespaces start with "Saloon". Many of the classes in Saloon had the word "Saloon" in, which has also been dropped, for example, the request and collection.
- SaloonRequest -> Request
- SaloonConnector -> Connector
Previously, Saloon was highly dependent on Guzzle as the underlying HTTP Client that sent requests. While this on its own is not inherently bad it meant that Saloon was very closely tied to Guzzle's versioning, support and breaking changes. Version two still requires Guzzle as its primary HTTP Client, but there have been many changes which decouple the library from Guzzle.
Saloon used to send a request through a class called
RequestSender.
this class would build up all the request properties like headers, config and body and would pass it into the Guzzle client. From version two, Saloon now has a new PendingRequest
class that is responsible for building up all the request properties. After a PendingRequest has been made, it is sent to a Sender.
This approach means that in theory you could use any HTTP client you like with Saloon, so if the maintainers of Guzzle decided to drop the project entirely, Saloon wouldn't be left in the dark.While Saloon still uses Guzzle for it's very useful PSR-compliant objects, in future versions of Saloon, it may not use Guzzle as a dependency. The work has already been completed to allow you to use any HTTP Client of your choice.

The flow of Saloon v2
Saloon's purpose is to make it easy for developers to build and maintain API integrations. From simple integrations in a small PHP or Laravel project to building SDKs as separate packages for people to enjoy. It must be fun for a developer to use so there has been many changes made.
One of the notable changes is the simplification of the request and connector API. Previously, the request class had over 50 methods available and many of those methods didn't add much value. With version two, there are now ~28 methods (at the time of writing). Every feature of Saloon has been re-evaluated to decide if it adds value.
Continue to read to see more information on the rest of the changes made in version two.
Version 1
Version 2
array:57 [
0 => "defineEndpoint"
1 => "__construct"
2 => "boot"
3 => "getMethod"
4 => "getConnector"
5 => "setConnector"
6 => "getFullRequestUrl"
7 => "traitExistsOnConnector"
8 => "setIsRecordingFixture"
9 => "isRecordingFixture"
10 => "isNotRecordingFixture"
11 => "__call"
12 => "make"
13 => "defaultData"
14 => "mergeData"
15 => "setData"
16 => "addData"
17 => "getData"
18 => "ignoreDefaultData"
19 => "defaultQuery"
20 => "mergeQuery"
21 => "setQuery"
22 => "addQuery"
23 => "getQuery"
24 => "ignoreDefaultQuery"
25 => "defaultHeaders"
26 => "mergeHeaders"
27 => "setHeaders"
28 => "addHeader"
29 => "getHeaders"
30 => "getHeader"
31 => "ignoreDefaultHeaders"
32 => "defaultConfig"
33 => "mergeConfig"
34 => "setConfig"
35 => "addConfig"
36 => "getConfig"
37 => "ignoreDefaultConfig"
38 => "addHandler"
39 => "mergeHandlers"
40 => "getHandlers"
41 => "addResponseInterceptor"
42 => "mergeResponseInterceptors"
43 => "getResponseInterceptors"
44 => "defaultAuth"
45 => "getAuthenticator"
46 => "withAuth"
47 => "authenticate"
48 => "withTokenAuth"
49 => "withBasicAuth"
50 => "withDigestAuth"
51 => "getResponseClass"
52 => "send"
53 => "sendAsync"
54 => "getRequestManager"
55 => "withMockClient"
56 => "getMockClient"
]
array:28 [
0 => "__construct"
1 => "createPendingRequest"
2 => "sender"
3 => "send"
4 => "sendAsync"
5 => "getMethod"
6 => "getAuthenticator"
7 => "authenticateWith"
8 => "withTokenAuth"
9 => "withBasicAuth"
10 => "withDigestAuth"
11 => "withQueryAuth"
12 => "headers"
13 => "queryParameters"
14 => "config"
15 => "middleware"
16 => "createDtoFromResponse"
17 => "getResponseClass"
18 => "withMockClient"
19 => "getMockClient"
20 => "hasMockClient"
21 => "when"
22 => "unless"
23 => "connector"
24 => "setConnector"
25 => "getRequestUrl"
26 => "boot"
27 => "make"
]
With previous versions of Saloon, the recommended way to send requests was with the request, and using the request
send
methods.$request = new UserRequest;
$response = $request->send();
One of the points developers found frustrating was defining a connector class on every request that you make. This was solely so you could make a request directly without instantiating the connector.
This approach was very minimalist, but it introduced complexity and friction for the developer.
From version two, the connector property is being dropped entirely from the request. This means that you must send your requests through the connector like this:
$connector = new TwitterConnector;
$response = $connector->send(new UserRequest);
// or
TwitterConnector::make()->send(new UserRequest);
This allows you to have constructor arguments on the connector, perfect for API tokens or configuration. Similar to before, the request can have its own headers, config, query parameters and body but the connector will provide the very top-level defaults.
Although this is being taken out of the request, you may still add the functionality back with the
HasConnector
trait on the request. Although, if you add it back - you need to be aware of the downsides like not being able to have constructor arguments on your connector.Saloon now has its own middleware pipeline which lets you tap into requests before they are sent and responses before they are handed back to the application. This is really handy to add additional logic to all your requests or modify something before a request is sent to the sender. Middleware methods are chain-able and you can use invokable classes for them too.
This replaces the legacy response interceptors. You may still use Guzzle middleware but you must add them from within the connector's constructor.
<?php
$request = new GetForgeServerRequest(12345);
$request->middleware()
->onRequest(function (PendingRequest $pendingRequest) {
// Run before the request is sent
})
->onResponse(function (Response $response) {
// Run after the request has been sent
});
Senders are responsible for taking a PendingRequest and actually sending it. Currently the default sender is the GuzzleSender, but other senders can be built and you can specify the default sender on the connector.
<?php
class ForgeConnnector extends Connector
{
protected function defaultSender(): Sender
{
return new CustomSender;
}
}
Previously, Saloon would create a new Guzzle client for every request. This means that it didn't support concurrent requests as the curl connection was closed after every request. With Saloon v2, the sender remains active on the connector until the connector is destructed. This means that concurrent requests and pools are supported! You can use the connector's
pool
method to create a pool of requests. Pools accept arrays, generators or closures.<?php
$forge = new ForgeConnector;
$forge->pool()
$pool = $connector->pool([
new GetForgeServersRequest,
new GetForgeServersRequest,
new GetForgeServersRequest,
]);
$pool->setConcurrency(10);