🌿
Upgrading from v1
It's time for the big upgrade to version two! There have been several major changes to Saloon in version two, so it's recommended that you read through what's new in v2 before starting the upgrade. You'll definitely need a cup of tea, coffee or beer if you fancy.
Simple integrations: 15-30 minutes
Advanced integrations and SDKs: ~30-45 minutes
First, update Saloon in your
composer.json
file to use the version ^2.0
. if you are using the additional Laravel package, you should update this to ^2.0
too. After that, run composer update
.Additionally, Saloon has moved to it's own Github organization so the name has been changed from
sammyjo20
to saloonphp
and the Laravel package has been renamed from sammyjo20/saloon-laravel
to saloonphp/laravel-plugin.
Non-Laravel
Laravel
"require": {
"saloonphp/saloon": "^2.0"
}
"require": {
"saloonphp/saloon": "^2.0",
"saloonphp/laravel-plugin": "^2.0"
}
If you previously usedsammyjo20/saloon-laravel
orsaloonphp/laravel-plugin
it's recommended that you addsaloonphp/saloon
as an additional required dependency.
Version two requires PHP 8.1 and Laravel 9 if you are using the additional Laravel helper package.
Estimated Impact: High
All of Saloon’s classes have a new namespace
Saloon
instead of Sammyjo20\Saloon
. This change will affect every use of Saloon’s internal classes, so it’s recommended to run a find-and-replace.- Find:
use Sammyjo20\Saloon
- Replace:
use Saloon
Estimated Impact: High
If you are using the Laravel helpers package for Saloon, you should also change the namespaces.
- Find:
use Sammyjo20\SaloonLaravel
- Replace:
use Saloon\Laravel
Estimated Impact: High
To help make Saloon more readable and to improve the developer experience, Saloon’s classes have changed names. There were a number of classes that had the name
Saloon
within, like SaloonRequest
and SaloonConnector.
you should find and replace these too. Please make sure that you have renamed the namespaces as instructed above first.- Find:
use Saloon\Http\SaloonConnector
- Replace:
use Saloon\Http\Connector
- Find:
extends SaloonConnector
- Replace:
extends Connector
- Find:
use Saloon\Http\SaloonRequest
- Replace:
use Saloon\Http\Request
- Find:
extends SaloonRequest
- Replace:
extends Request
- Find:
use Saloon\Clients\MockClient
- Replace:
use Saloon\Http\Faking\MockClient
- Find:
use Saloon\Http\MockResponse
- Replace:
use Saloon\Http\Faking\MockResponse
- Find
use Saloon\Http\SaloonResponse
- Replace:
use Saloon\Http\Response
- Find:
extends SaloonResponse
- Replace:
extends Response
Estimated Impact: High
Saloon has also had a major refactor with the methods that are used to build and interact with connectors and requests. You should carefully find and replace the given strings.
The connector’s base URL method has changed.
- Find:
public function defineBaseUrl(): string
- Replace:
public function resolveBaseUrl(): string
The method to define a custom response has changed.
- Find:
public function getResponseClass(): string
- Replace:
public function resolveResponseClass(): string
The
request
method has been removed.The
__call
and __callStatic
methods have been removed alongside the magic methods that build up requests. Including the requests
property.Estimated Impact: High
The request’s
defineEndpoint
method has changed.- Find:
public function defineEndpoint(): string
- Replace:
public function resolveEndpoint(): string
The method to define a custom response has changed.
- Find:
public function getResponseClass(): string
- Replace:
public function resolveResponseClass(): string
The
send
, sendAsync
, getConnector
and setConnector
methods and the connector
property has been removed from the request. Please see below to add connector support back to your request if you need itThe
getFullRequestUrl
method has been removed from the request. You can get the URL of the request with the PendingRequest
inside of the boot method, traits and middleware.The
__call
method has been removed from the request. Any methods that no longer exist on the request will not be proxied to the connector.The
traitExistsOnConnector
method has been removed from the request.The request’s method property has changed to use a new
Saloon\Enums\Method
Enum. Make sure to migrate to use the new Enum too. For example: protected Method $method = Method::GET
.- Find:
protected ?string $method
- Replace:
protected Method $method
Estimated Impact: High
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.
You should make sure that your requests use this new way of sending requests.
Although this is being taken out of the request, you may still add the functionality back with the
HasConnector
trait on the request. However, if you add it back - you need to be aware of the downsides like not being able to have constructor arguments on your connector.Estimated Impact: High
Another notable change would be the simplification of interacting with headers, config and request body. Instead of individual methods for interacting with these properties, they are now wrapped in easy-to-understand methods with unified method names. Additionally, previously you wouldn't be able to access the default properties after instantiating the request, but now you can. You should make sure any references to headers, query parameters or config use the new methods.
Version 1
Version 2
<?php
$request = new GetForgeServerRequest(12345);
$request->addHeader($value);
$request->getHeader($value);
$request->setHeaders($value);
$request->mergeHeaders(...$values);
$request->getHeaders();
$request->addQuery($value);
$request->getQuery(?$value);
$request->setQuery($value);
$request->mergeQuery(...$values);
$request->addConfig($value);
$request->getConfig(?$value);
$request->setConfig($value);
$request->mergeConfig(...$values);
$request->addData($value);
$request->getData(?$value);
$request->setData($value);
$request->mergeData(...$values);
<?php
$request = new GetForgeServerRequest(12345);
$request->headers()->add($value);
$request->headers()->get($value, $default);
$request->headers()->set($value);
$request->headers()->merge(...$values);
$request->headers()->all();
$request->query()->add($value);
$request->query()->get($value, $default);
$request->query()->set($value);
$request->query()->merge(...$values);
$request->query()->all();
$request->config()->add($value);
$request->config()->get($value, $default);
$request->config()->set($value);
$request->config()->merge(...$values);
$request->config()->all();
// Data has been moved to body()... more on that below
Estimated Impact: High
Saloon has also rebuilt the way that request data/body is sent using POST/PUT/PATCH requests. First, make sure that your data traits are using the new namespaces. It's recommended that you read through the new section on request body/data to understand why the changes have been made.
HasJsonBody
- Find:
use Saloon\Traits\Plugins\HasJsonBody
- Replace:
Saloon\Traits\Body\HasJsonBody
HasFormParams
- Find:
use Saloon\Traits\Plugins\HasFormParams
- Replace:
use Saloon\Traits\Body\HasFormBody
HasMultipartBody
- Find:
use Saloon\Traits\Plugins\HasMultipartBody
- Replace:
use Saloon\Traits\Body\HasMultipartBody
HasXMLBody
- Find:
use Saloon\Traits\Plugins\HasXMLBody
- Replace:
use Saloon\Traits\Body\HasXmlBody
- Replace:
use HasXMLBody
- Find:
use HasXmlBody
HasBody
- Find:
use Saloon\Traits\Plugins\HasBody
- Replace:
use Saloon\Traits\Body\HasBody
Next, add the
HasBody
interface to your request or connector. This interface is required for Saloon to properly detect if you are using request body or not. Since you have already added a body trait, the required body
method should be implemented. You may need to re-index your IDE before it understands the changes made.Previously, Saloon called request body "data". To match PSR standards better, this has been renamed to "body".
Previously, you may have defined a method like
defaultData
this needs to be renamed to defaultBody
. The methods have also changed from being public to protected.Version One
Version Two
<?php
class GetServersRequest extends Request
{
// {...}
public function defaultData(): array
{
return [
// ...
];
}
}
<?php
class GetServersRequest extends Request
{
// {...}
public function defaultBody(): array
{
return [
// ...
];
}
}
Make sure that you define the correct return type for your request body trait.
Saloon has removed the
defineXmlBody
method when you use the HasXmlTrait
. You must replace this with defaultBody
Saloon has also changed the previous request data methods. You should update your code accordingly if you used these old methods.
Version One
Version Two
<?php
$request = new CreateForgeSiteRequest($serverId, $domain);
$request->setData(['domain' => $customDomain]);
$request->mergeData(['database' => 'test123']);
$request->addData('name', 'my-saloon-server');
$request->getData('name');
<?php
$request = new CreateForgeSiteRequest($serverId, $domain);
$request->body()->set(['domain' => $customDomain]);
$request->body()->merge(['database' => 'test123']);
$request->body()->add('name', 'my-saloon-server');
$request->body()->get('name');
Estimated Impact: High
With regards to request collections/request groups, Saloon has removed support for them entirely in v2. Previously, Saloon had a lot of "magic" logic which was cool, but tricky for IDEs to support. As request collections were just classes that passed in the connector, it's recommended that you create your own classes that support this, and then add methods into your connector.
Estimated Impact: High
Saloon version two has removed the
withAuth
method. You should use the authenticate
method instead.Estimated Impact: High
Previously, Saloon had the concept of
ResponseInterceptors
which were functions that Saloon would call before returning the response back to the application. This API has been removed in favour of using the new Middleware API. It's recommended that you get yourself familiar with middleware, but here is an example of migrating from response interceptors to response middleware.Version One
Version Two
<?php
$request->addResponseInterceptor(function (SaloonRequest $request, SaloonResponse $response) {
$response->throw();
return $response;
});
<?php
use Saloon\Contracts\Response;
$request->middleware()->onResponse(function (Response $response) {
$response->throw();
});
Estimated Impact: High
From Saloon version two, the
AlwaysThrowsOnErrors
trait has been renamed to AlwaysThrowOnErrors
.- Find:
Saloon\Traits\Plugins\AlwaysThrowsOnErrors
- Replace:
Saloon\Traits\Plugins\AlwaysThrowOnErrors
- Find:
use AlwaysThrowsOnErrors
- Replace:
use AlwaysThrowOnErrors
Estimated Impact: High
Saloon has a method that you can add on your connector and request to write logic while a request is being sent. This
boot
method has changed arguments in version two. It used to provide you with an instance of Request
but will now provide you with an instance of PendingRequst.
You should ensure any modifications are made on this PendingRequest instance and not use $this
or modify the connector/request.Version One
Version Two
<?php
class CreateForgeServerRequest extends SaloonRequest
{
// {...}
public function boot(SaloonRequest $request): void
{
$request->addHeader('X-Example', 'Hello');
}
}
<?php
use Saloon\Contracts\PendingRequest;
class CreateForgeServerRequest extends Request
{
// {...}
public function boot(PendingRequest $pendingRequest): void
{
$pendingRequest->headers()->add('X-Example', 'Hello');
}
}
Estimated Impact: High
Saloon's caching plugin has also had a full overhaul to work with Saloon v2. It's recommended that you follow the steps for configuring the new caching plugin in the documentation here.
Estimated Impact: High
Previously, Saloon provided data transfer objects through a
CastsToDto
trait. This trait could be added to the connector or request and would allow you to define a castToDto
method. From Saloon v2, DTO casting is a built-in feature for every connector and request and the CastsToDto
trait has been removed. All you need to do is change the protected castToDto
method to a public createDtoFromResponse
method.Version One
Version Two
<?php
use Sammyjo20\Saloon\Traits\Plugins\CastsToDto;
class ForgeConnector extends SaloonConenctor
{
use CastsToDto;
protected function castToDto(SaloonResponse $response): mixed
{
// ...
}
}
<?php
class ForgeConnector extends SaloonConenctor
{
protected function createDtoFromResponse(SaloonResponse $response): mixed
{
// ...
}
}
Estimated Impact: Medium
Saloon’s
Response
class has changed to be a more generic, PSR-compatible response. If you are extending the existing Response class, you should make sure that it is still working correctly.Estimated Impact: Medium
From version two, Saloon has updated its plugins. You can choose to add plugins to both your connector or your request. Previously, plugins would receive an instance of
SaloonRequest
in the arguments. Now, plugins will receive a PendingRequest
instance. You should update your plugins accordingly.You should also make any changes to the
PendingRequest
instance and not use $this
as it's bad practice to overwrite the connector/request instance.Estimated Impact: Medium
Previously, Saloon allowed you to use the
addHandler
method to use a Guzzle middleware. From version two, Guzzle middleware is still supported with the default GuzzleSender, but you must migrate your handlers to the new API.It's also recommended that you move any Guzzle middleware from requests into your connector class as middleware should only be executed once.
Version One
Version Two
<?php
class Forge extends SaloonConnector
{
//...
public function boot(SaloonRequest $request): void
{
$this->addHandler('customHeaderHandler', function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
$request->withHeader('X-Custom-Header', 'Hello');
return $handler($request, $options);
};
});
}
}
<?php
class Forge extends Connector
{
//...
public function boot(PendingRequest $pendingRequest): void
{
$pendingRequest->sender()->addMiddleware(function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
$request->withHeader('X-Custom-Header', 'Hello');
return $handler($request, $options);
};
}, 'customHandlerMiddleware');
}
}
Estimated Impact: Low
Previously, Saloon had five traits which would throw an exception if a request or connector wasn’t authenticated. The following traits have now been removed:
- RequiresBasicAuth
- RequiresDigestAuth
- RequiresTokenAuth
You should now use the generic
RequiresAuth
trait if you would still like to throw an exception.Estimated Impact: Low
Saloon no longer has Carbon as a dependency, so all dates returned that used to return a
CarbonInterface
now return DateTimeImmutable
- OAuthAuthenticator:
getExpiresAt()
- AccessTokenAuthenticator:
getExpiresAt()
Estimated Impact: Low
The
MockResponse::fromRequest
method has been removed from version two.Last modified 4d ago