### Usage Example: Accessing Pokemon Resources (PHP) Source: https://docs.saloon.dev/digging-deeper/building-sdks Demonstrates how to instantiate a `Pokeapi` connector and then use the `pokemon()` resource method to call the `all()` and `get()` methods for fetching Pokémon data. This highlights the ease of use after resource grouping. ```php pokemon()->all(page: 1); $giratina = $pokeapi->pokemon()->get(id: 'giratina'); ``` -------------------------------- ### Define Spotify API Rate Limits and Redis Store Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This example demonstrates how to configure rate limits for the Spotify API connector using the Saloon Rate Limit Plugin. It defines limits for requests per minute, day, and month, and specifies Redis as the storage mechanism for tracking these limits. Ensure you have Redis installed and accessible. ```php everyMinute(), Limit::allow(1000)->everyDay(), Limit::allow(5000)->everyMonth(), ]; } protected function resolveRateLimitStore(): RateLimitStore { $redis = new Redis; $redis->connect('127.0.0.1'); return new RedisStore($redis); } } ``` -------------------------------- ### Install Saloon Laravel Plugin Source: https://docs.saloon.dev/installable-plugins/laravel-integration Installs the Saloon Laravel plugin using Composer. Requires saloonphp/saloon as a dependency. ```bash composer require saloonphp/laravel-plugin "^3.0" ``` -------------------------------- ### Install Saloon Cache Plugin (Bash) Source: https://docs.saloon.dev/installable-plugins/caching-responses Install the Saloon cache plugin using Composer. This command adds the necessary package to your project dependencies. ```bash composer require saloonphp/cache-plugin "^3.0" ``` -------------------------------- ### XML Structure Example Source: https://docs.saloon.dev/installable-plugins/xml-wrangler An example of an XML structure representing a breakfast menu. This XML demonstrates nested elements, attributes, and provides sample data for food items including their name, price, description, and calorie count. ```xml Belgian Waffles $5.95 Two of our famous Belgian Waffles with plenty of real maple syrup 650 Strawberry Belgian Waffles $7.95 Light Belgian waffles covered with strawberries and whipped cream 900 Berry-Berry Belgian Waffles $8.95 Light Belgian waffles covered with an assortment of fresh berries and whipped cream 900 ``` -------------------------------- ### Setup Global Mock Client for PHPUnit Source: https://docs.saloon.dev/the-basics/testing Destroys the global mock client before each test when using PHPUnit. This setup should be placed within the `setUp` method of your test class or TestCase to ensure test isolation. ```php use Saloon\Http\Faking\MockClient; class RequestTest extends TestCase { protected function setUp(): void { MockClient::destroyGlobal(); } } ``` -------------------------------- ### Controller Example for API Data Sync Source: https://docs.saloon.dev/the-basics/testing An example controller method that fetches server data from the Laravel Forge API using Saloon and stores it in the database. This code is intended to be tested using the mocked API responses. ```php send(new GetServersRequest)->array('data'); foreach($servers as $server) { DB::table('servers')->insert([ 'name' => $server['name'], 'ip' => $server['ip'], ]); } return response('Synced servers', 200); } } ``` -------------------------------- ### Install Saloon Pagination Plugin Source: https://docs.saloon.dev/installable-plugins/pagination Install the Saloon pagination plugin using Composer. This package provides the necessary classes and interfaces to implement pagination in your Saloon connectors. ```sh composer require saloonphp/pagination-plugin "^2.0" ``` -------------------------------- ### Install Symfony Var Dumper for Debugging Source: https://docs.saloon.dev/the-basics/debugging This command installs Symfony's Var Dumper library, which Saloon uses by default for its debugging driver. This is a prerequisite if you are not using Laravel, as it is already included in the framework. ```bash composer require symfony/var-dumper ``` -------------------------------- ### Install Saloon Laravel HTTP Sender (Laravel 11+) Source: https://docs.saloon.dev/installable-plugins/laravel-integration Installs the Saloon HTTP sender library for Laravel 11 and above using Composer, enabling requests to be handled by Laravel's HTTP client. ```bash composer require saloonphp/laravel-http-sender "^3.0" ``` -------------------------------- ### PHP: Spotify Connector Authorization Code Flow Example Source: https://docs.saloon.dev/digging-deeper/oauth2-authentication/oauth2-authentication This example illustrates the complete Authorization Code grant flow using a Saloon Spotify connector. It covers redirecting the user, handling the callback, creating an access token, authenticating the connector, sending requests, and refreshing access tokens. ```php $connector = new SpotifyConnector; // 1. Redirect the user to the authorization URL... $authorizationUrl = $connector->getAuthorizationUrl($scopes, $state); // 2. Handle the callback from the API provider and create an access token... $authenticator = $connector->getAccessToken($code, $state); // 3. Authenticate the connector $connector->authenticate($authenticator); // 4. Send your requests $connector->send(new GetTracksRequest); // 5. Refresh your access tokens... $newAuthenticator = $connector->refreshAccessToken($authenticator); ``` -------------------------------- ### Install Saloon Laravel HTTP Sender (Laravel 9-10) Source: https://docs.saloon.dev/installable-plugins/laravel-integration Installs the Saloon HTTP sender library for Laravel 9 and 10 using Composer, enabling requests to be handled by Laravel's HTTP client. ```bash composer require saloonphp/laravel-http-sender "^2.0" ``` -------------------------------- ### Install Lawman PHP Package Source: https://docs.saloon.dev/installable-plugins/lawman This command installs the Lawman plugin as a development dependency using Composer. It ensures that the plugin's autoloading capabilities are leveraged for immediate use after installation. ```bash composer require jonpurvis/lawman --dev ``` -------------------------------- ### Create MockResponse using Fixtures Source: https://docs.saloon.dev/the-basics/testing This example demonstrates creating a mock response using `MockResponse::fixture()`. Saloon will record a real API response the first time the test runs and save it to a file. Subsequent test runs will use this recorded fixture, improving test speed and avoiding repeated API calls or rate limiting. The 'user' argument specifies the name of the fixture file. ```php $mockClient = new MockClient([ GetUserRequest::class => MockResponse::fixture('user'); ]); ``` -------------------------------- ### FlysystemDriver Configuration (PHP) Source: https://docs.saloon.dev/installable-plugins/caching-responses Configure the `FlysystemDriver` for Saloon caching, requiring `league/flysystem` version 3. This example demonstrates using an AWS S3 V3 adapter. ```php use Saloon\CachePlugin\Drivers\FlysystemDriver; public function resolveCacheDriver(): Driver { // This example uses the "AwsS3V3Adapter" driver // that is provided by Flysystem. return new FlysystemDriver( new Filesystem(new AwsS3V3Adapter($s3Client, 'bucket-name')) ); } ``` -------------------------------- ### Implement Default Rate Limits and Memory Store Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This example sets up a Saloon connector with the `HasRateLimits` trait, an empty array for limits (meaning no specific limits are enforced by default), and uses the `MemoryStore` for tracking. The `MemoryStore` is suitable for testing or simple use cases as it persists only within the connector's lifetime. ```php use Saloon\Http\Connector; use Saloon\RateLimitPlugin\Contracts\RateLimitStore; use Saloon\RateLimitPlugin\Stores\MemoryStore; use Saloon\RateLimitPlugin\Traits\HasRateLimits; class SpotifyConnector extends Connector { use HasRateLimits; protected function resolveLimits(): array { return []; } protected function resolveRateLimitStore(): RateLimitStore { return new MemoryStore; } } ``` -------------------------------- ### Basic Request Definition Source: https://docs.saloon.dev/the-basics/requests Defines a basic GET request to the '/servers' endpoint by extending the `Request` abstract class and implementing the `resolveEndpoint` method. ```APIDOC ## GET /servers ### Description This endpoint retrieves a list of servers. ### Method GET ### Endpoint /servers ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php MockResponse::make(body: '', status: 200), 'forge.laravel.com/*' => MockResponse::make(body: '', status: 200), ]); ``` -------------------------------- ### Configure Saloon Rate Limiter with Redis Store Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This example demonstrates configuring the Saloon Rate Limit Plugin to use the `RedisStore`. It requires an active Redis connection, specified by host and port. The `RedisStore` leverages a Redis database for storing and retrieving rate limit information, offering a robust and scalable solution. ```php use Redis; use Saloon\RateLimitPlugin\Contracts\RateLimitStore; use Saloon\RateLimitPlugin\Stores\RedisStore; protected function resolveRateLimitStore(): RateLimitStore { $client = new Redis; $client->connect('127.0.0.1'); return new RedisStore($client); } ``` -------------------------------- ### Use Local MockClient with Connector in PHP Source: https://docs.saloon.dev/the-basics/testing This example demonstrates how to create and use a local `MockClient` instance with a Saloon connector using the `withMockClient()` method. This allows for isolated testing of individual requests and connectors without affecting the global mock client. It requires `MockClient` and `MockResponse` from Saloon. ```php MockResponse::make('Server Created', 200), ]); $connector = new ForgeConnector; $connector->withMockClient($mockClient); $connector->send(new CreateServerRequest($name, $ip)); $mockClient->assertSent(function (Request $request) { return $request->body()->all() === ['name' => $name, 'ip' => $ip]; }); }); ``` -------------------------------- ### Set Custom Thresholds for Rate Limits Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This example configures a rate limit with a custom threshold percentage. The limit will trigger an action when a specified percentage (e.g., 80%) of the limit is reached, allowing for proactive management of API usage. ```php use Saloon\RateLimitPlugin\Limit; protected function resolveLimits(): array { return [ Limit::allow(60, threshold: 0.8)->everyMinute(), // Will fail when at 80% capacity ]; } ``` -------------------------------- ### Setup Global Mock Client for PEST Source: https://docs.saloon.dev/the-basics/testing Ensures the global mock client is destroyed before each test to prevent state leakage between tests when using PEST. This is crucial for maintaining isolated test environments. ```php use Saloon\Http\Faking\MockClient; uses() ->beforeEach(fn () => MockClient::destroyGlobal()) ->in(__DIR__); ``` -------------------------------- ### Define API Rate Limits with Intervals Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This example defines multiple rate limits for an API using the Limit class. It sets a per-minute limit of 60 requests and a daily limit of 1000 requests, demonstrating flexible interval configuration. ```php use Saloon\RateLimitPlugin\Limit; protected function resolveLimits(): array { return [ Limit::allow(60)->everyMinute(), Limit::allow(1000)->everyDay(), ]; } ``` -------------------------------- ### LaravelCacheDriver Configuration (PHP) Source: https://docs.saloon.dev/installable-plugins/caching-responses Configure the `LaravelCacheDriver` for Saloon caching, which integrates with Laravel's cache system. This example uses Laravel's Redis cache store. ```php use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; public function resolveCacheDriver(): Driver { // This example uses Redis cache store that // Laravel provides. return new LaravelCacheDriver(Cache::store('redis')); } ``` -------------------------------- ### Update Saloon Packages via Composer Source: https://docs.saloon.dev/upgrade/upgrading-from-v2 This command updates all Saloon-related packages to their latest compatible versions for the new major release. Ensure you have Composer installed and configured. ```bash composer update "saloonphp/*" ``` -------------------------------- ### Define CursorPaginator Class in PHP Source: https://docs.saloon.dev/installable-plugins/pagination/cursor-pagination Example of defining a custom CursorPaginator class by extending Saloon's base class. This requires passing the connector and request to the constructor. It sets up the structure for custom pagination logic. ```php everyMinute()->name('spotify-limit-user-' . $this->userId), ]; } ``` -------------------------------- ### Request with Constructor Arguments - PHP Source: https://docs.saloon.dev/the-basics/requests Defines a request class that accepts constructor arguments to dynamically set request properties. This example shows how to pass a resource ID to the constructor to construct a specific endpoint URL. ```php class GetServerRequest extends Request { protected Method $method = Method::GET; public function __construct(protected readonly string $id) { // } public function resolveEndpoint(): string { return '/servers/' . $this->id; } } ``` ```php $request = new GetServerRequest('5664b05b-8b32-4523-a0d5-837f5080417a'); ``` -------------------------------- ### Initialize MockClient with a Closure for Advanced Mocking Source: https://docs.saloon.dev/the-basics/testing This example demonstrates using a closure to define mock responses within the MockClient. This approach offers advanced control, allowing the mock response to be dynamically generated based on the `PendingRequest` object. It's suitable for complex mocking scenarios where the response depends on request details. ```php $mockClient = new MockClient([ GetServersRequest::class => function (PendingRequest $pendingRequest) { return MockResponse::make(...); }, ]); ``` -------------------------------- ### Integrate XML Wrangler with Saloon Responses in PHP Source: https://docs.saloon.dev/installable-plugins/xml-wrangler Shows how to obtain an `XmlReader` instance from a Saloon HTTP response object. This allows you to leverage XML Wrangler's reading and querying capabilities directly on XML data returned by an API. Assumes Saloon and XML Wrangler are installed. ```php $response = $connector->send($request); $reader = $response->xmlReader(); // $reader->values(); // etc... ``` -------------------------------- ### Test Saloon Connector Authentication with Lawman Source: https://docs.saloon.dev/installable-plugins/lawman Shows how to test a Saloon Connector's authentication methods using Lawman. This example verifies the presence of both certificate and token authentication, demonstrating support for multi-authentication configurations. ```php test('connector') ->expect('App\Http\Integrations\Integration\Connector') ->toBeSaloonConnector() ->toUseCertificateAuthentication() ->toUseTokenAuthentication(); ``` -------------------------------- ### Prevent Fixture Recording in Tests (PHPUnit) Source: https://docs.saloon.dev/the-basics/testing Add MockConfig::throwOnMissingFixtures() to the setUp() method in your TestCase.php file to prevent Saloon from recording fixtures during PHPUnit tests. This is crucial for ensuring fixture integrity. ```php use Saloon\nMockConfig; class TestCase extends BaseTestCase { protected function setUp(): void { MockConfig::throwOnMissingFixtures(); } } ``` -------------------------------- ### Prevent Stray Requests in Tests (PHPUnit) Source: https://docs.saloon.dev/the-basics/testing Integrate Config::preventStrayRequests() within the setUp() method of your TestCase.php file to prevent real API calls during PHPUnit tests. This ensures a controlled testing environment. ```php use Saloon\nConfig; class TestCase extends BaseTestCase { protected function setUp(): void { parent::setUp(); Config::preventStrayRequests(); } } ``` -------------------------------- ### Implement HasBody for JSON Requests in PHP Source: https://docs.saloon.dev/the-basics/request-body-data/json-body To send a JSON body with a Saloon request, you must implement the `HasBody` interface and set the request method to POST, PUT, or PATCH. This example demonstrates the basic setup for a `CreateServerRequest`. ```php filePath) ]; } } ``` -------------------------------- ### Instantiate Saloon SDK Connector Source: https://docs.saloon.dev/digging-deeper/building-sdks Shows how to create an instance of a Saloon SDK connector. This involves passing necessary authentication details, like an API token, during instantiation, preparing the SDK for making requests. ```php headers()->add('X-Current-Time', new DateTime); } } ``` -------------------------------- ### Usage Example: Update Server with DTO in PHP Source: https://docs.saloon.dev/digging-deeper/data-transfer-objects This PHP snippet demonstrates the usage of the `UpdateServerRequest` by first fetching a `Server` DTO using `GetServerRequest`. It then modifies a property of the retrieved `Server` object (`$server->name`) and subsequently uses this modified DTO to create and send an `UpdateServerRequest` via a `ForgeConnector`. ```php send(new GetServerRequest(id: 12345)); $server = $response->dto(); // Modify the server $server->name = 'YEE-HAW-2'; // Update the server request $response = $connector->send(new UpdateServerRequest($server)); ``` -------------------------------- ### Handle Asynchronous Responses with Promises in PHP Source: https://docs.saloon.dev/the-basics/responses This example illustrates how to handle asynchronous requests in Saloon using Guzzle Promises. It shows how to send an async request and use `.then()` for successful responses and `.otherwise()` for handling exceptions. The `wait()` method is used to force promise resolution. It requires the `SaloonHttpResponse` and `Exception` classes. ```php sendAsync(new GetServersRequest); $promise ->then(function (Response $response) { // Handle successful response }) ->otherwise(function (Exception $exception) { // Handle failed request }); $promise->wait(); // Force the promise to be resolved ``` -------------------------------- ### Connect to Redis using PredisStore Source: https://docs.saloon.dev/installable-plugins/handling-rate-limits This snippet demonstrates how to configure the PredisStore to connect to a Redis server using the predis/predis PHP library. It requires the predis/predis package and sets up a client connection to a specified host and port. ```php use Saloon\RateLimitPlugin\Contracts\RateLimitStore; use Saloon\RateLimitPlugin\Stores\PredisStore; protected function resolveRateLimitStore(): RateLimitStore { $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => '10.0.0.1', 'port' => 6379, ]); return new PredisStore($client); } ``` -------------------------------- ### Publish Saloon Configuration Source: https://docs.saloon.dev/installable-plugins/laravel-integration Publishes the Saloon configuration file using an Artisan command for customization. ```bash php artisan vendor:publish --tag=saloon-config ``` -------------------------------- ### Integrate PokemonResource with Connector (PHP) Source: https://docs.saloon.dev/digging-deeper/building-sdks Shows how to define a method on a Saloon `Connector` class that instantiates and returns the custom `PokemonResource`. This makes the resource accessible through the connector instance, allowing users to easily access grouped requests. ```php class Pokeapi extends Connector { // ... public function pokemon(): PokemonResource { return new PokemonResource($this); } } ``` -------------------------------- ### PsrCacheDriver Configuration (PHP) Source: https://docs.saloon.dev/installable-plugins/caching-responses Configure the `PsrCacheDriver` for Saloon caching, which supports PSR-16 cache implementations. This example uses `PhpArrayAdapter` from the `symfony/cache` library. ```php use Saloon\CachePlugin\Drivers\PsrCacheDriver; public function resolveCacheDriver(): Driver { // This example uses the PhpArrayAdapter from // the symfony/cache library. return new PsrCacheDriver(new PhpArrayAdapter); } ``` -------------------------------- ### Initialize MockClient with Request Class Mapping Source: https://docs.saloon.dev/the-basics/testing This snippet demonstrates how to initialize Saloon's MockClient by mapping a request class to a mocked response. It's useful for setting up specific responses for known requests, ensuring predictable behavior during testing without actual API calls. Dependencies include Saloon's MockClient and MockResponse classes. ```php use Saloon\Http\Faking\MockClient; test('my test', function () { $mockClient = new MockClient([ GetServersRequest::class => MockResponse::make(body: '', status: 200), ]); $connector = new ForgeConnector; $connector->withMockClient($mockClient); }); ``` -------------------------------- ### Namespace Fixtures Using Folders in PHP Source: https://docs.saloon.dev/the-basics/testing This snippet illustrates how to organize fixtures into subdirectories by including a path in the fixture name. This helps manage fixtures when dealing with multiple API integrations. The `MockClient::global()` method accepts fixture names with directory separators like '/'. ```php MockClient::global([ GetServersRequest::class => MockResponse::fixture('forge/servers'), ]); ``` -------------------------------- ### Customize Cacheable HTTP Methods (PHP) Source: https://docs.saloon.dev/installable-plugins/caching-responses By default, only GET and OPTIONS requests are cached. You can customize which HTTP methods are considered cacheable by overriding the `getCacheableMethods` method. ```php send($request); ``` -------------------------------- ### Use Saloon Paginator with Laravel LazyCollection Source: https://docs.saloon.dev/installable-plugins/pagination Utilizes the `collect()` method to get a Laravel LazyCollection from the paginator, enabling efficient, memory-conscious processing of paginated API data. Requires `illuminate/collections` if not using Laravel. ```bash composer require illuminate/collections ``` ```php paginate(new GetLikedSongsRequest); $collection = $paginator->collect(); $results = $collection ->filter(function (array $song) { return count($song['artists']) > 1; }) ->map(function (array $song) { return $song['name']; }) ->sort(); foreach($results as $song) { // $song: "When It Rains It Pours" } ``` -------------------------------- ### Initialize and Authenticate with Client Credentials Grant Source: https://docs.saloon.dev/digging-deeper/oauth2-authentication/client-credentials-grant Demonstrates the basic flow of using the Client Credentials Grant with a Saloon connector. It shows how to obtain an access token and authenticate the connector for sending requests. ```php getAccessToken($scopes); // 2. Authenticate the connector $connector->authenticate($authenticator); // 3. Send your requests $connector->send(new GetInventoryRequest); ``` -------------------------------- ### Refreshing Expired Access Tokens (PHP) Source: https://docs.saloon.dev/digging-deeper/oauth2-authentication/oauth2-authentication This example shows how to check if an authenticator's access token has expired and how to refresh it using the `refreshAccessToken` method. It covers retrieving, checking, and updating the authenticator. ```php getCachedAuthenticator(); $connector = new SpotifyConnector; if ($authenticator->hasExpired()) { // We'll refresh the access token which will return a new authenticator // which we can store against our user in our application. $authenticator = $connector->refreshAccessToken($authenticator); $user->updateAuthenticator($authenticator); } // Authenticate our connector and send the request $connector->authenticate($authenticator); $response = $connector->send(new GetTracksRequest); ``` -------------------------------- ### Customizing Request Failure Detection in Connector Source: https://docs.saloon.dev/the-basics/handling-failures Provides an example of how to override the `hasRequestFailed` method on a Saloon connector to define custom logic for determining if a request has failed, even if the HTTP status code indicates success. ```php body(), 'Server Error'); } } ``` -------------------------------- ### Modifying the PSR-7 Request Before Sending in Saloon Source: https://docs.saloon.dev/digging-deeper/psr-support This example shows how to intercept and modify the PSR-7 request before it is sent to the HTTP client using the `handlePsrRequest` hook on a Saloon connector. This allows for custom headers or other request modifications. ```php withHeader('X-API-Key', 'Howdy!'); return $request; } } ``` -------------------------------- ### Connector Constructor Arguments - PHP Source: https://docs.saloon.dev/the-basics/connectors Illustrates how to use constructor arguments to inject dynamic properties, such as the base URL, into a Saloon connector. This allows for flexible connector instantiation based on runtime values. ```php class ForgeConnector extends Connector { public function __construct(protected readonly string $baseUrl) { // } public function resolveBaseUrl(): string { return $this->baseUrl; } } ``` ```php $connector = new ForgeConnector('https://forge.laravel.com/api/v1'); ``` -------------------------------- ### Access Authenticator Properties Source: https://docs.saloon.dev/digging-deeper/oauth2-authentication/client-credentials-grant Provides methods to retrieve the access token, check its expiration status, and get the expiry date from an `AccessTokenAuthenticator` instance. This is crucial for managing token validity and refreshing them. ```php getAccessToken(); $authenticator->getExpiresAt(); $authenticator->hasExpired(); $authenticator->hasNotExpired(); ``` -------------------------------- ### Request Headers Source: https://docs.saloon.dev/the-basics/requests Demonstrates how to define default headers for a request using the `defaultHeaders` method and how to add headers dynamically to a request instance. ```APIDOC ## Request Headers ### Description Allows setting default or dynamic headers for API requests. ### Method GET (example) ### Endpoint /servers (example) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php 'application/json', 'Accept' => 'application/json', ]; } } // Dynamically adding headers $request = new GetServersRequest; $request->headers()->add('X-Custom-Header', 'SomeValue'); ``` ### Response #### Success Response (200) (Response structure depends on the specific endpoint) #### Response Example (Response structure depends on the specific endpoint) ``` -------------------------------- ### Basic MockClient Assertions in PHP Source: https://docs.saloon.dev/the-basics/testing This code demonstrates basic assertions using a `MockClient` instance in PHP. It shows how to assert that a specific request was sent using `assertSent()` and how to check the number of times a request was sent with `assertSentCount()`. These methods are part of Saloon's testing utilities. ```php MockResponse::make(...), ]); // Your application code... $mockClient->assertSent(GetServersRequest::class); $mockClient->assertSentCount(1); }); ``` -------------------------------- ### Automated Per-Request Authentication with Saloon Connector Boot Method Source: https://docs.saloon.dev/conclusion/how-to-guides/per-request-authentication Refactors the authentication process by utilizing the `boot` method within a Saloon connector. This method runs before each request, allowing for automatic token retrieval and attachment, while also including logic to prevent infinite loops for the authentication request itself. ```php getRequest() instanceof GetAccessTokenRequest) { return; } // Now let's make our authentication request. Since we are in the // context of the connector, we can just simply call $this and // make another request! $authResponse = $this->send(new GetAccessTokenRequest($this->username, $this->password)); // Now we'll take the token from the auth response and then pass it // into the $pendingRequest which is the original GetSongsByArtistRequest. $pendingRequest->authenticate(new TokenAuthenticator($authResponse->json()['token'])); } } ``` -------------------------------- ### Create Saloon SDK Connector Class Source: https://docs.saloon.dev/digging-deeper/building-sdks Defines a Saloon connector for an SDK, setting the base URL, default headers, and authentication method. This serves as the root class for the SDK, encapsulating API configuration. ```php 'application/json', 'Content-Type' => 'application/json', ]; } protected function defaultAuth(): TokenAuthenticator { return new TokenAuthenticator($this->token); } } ``` -------------------------------- ### Implement HasBody Interface for POST Requests Source: https://docs.saloon.dev/the-basics/request-body-data/multipart-form-body To send a request body, your Saloon request class must implement the `HasBody` interface. This example shows a basic `UploadProfilePictureRequest` class configured for a POST method. ```php 'name', // ?sort=name 'filter[active]' => 'true', // ?filter[active]=true ]; } } // Dynamically adding query parameters $request = new GetServersRequest; $request->query()->add('provider', 'aws'); ``` ### Response #### Success Response (200) (Response structure depends on the specific endpoint) #### Response Response Example (Response structure depends on the specific endpoint) ``` -------------------------------- ### Instantiate Paginator with Connector Source: https://docs.saloon.dev/installable-plugins/pagination After implementing the `paginate` method, you can instantiate the paginator by passing the connector to your request object. This prepares the custom pagination process for the request. ```php paginate($spotifyConnector); ``` -------------------------------- ### Accessing Underlying Guzzle Client and Handler Stack Source: https://docs.saloon.dev/digging-deeper/middleware Provides code examples for retrieving the underlying Guzzle client instance and its handler stack from a Saloon connector. This allows for direct modification of Guzzle components. ```php sender()->getGuzzleClient(); $handlerStack = $this->sender()->getHandlerStack(); } } ``` -------------------------------- ### Instantiate Saloon Paginator Source: https://docs.saloon.dev/installable-plugins/pagination Instantiates a paginator for a given request. No API requests are made at this stage; requests are only triggered during iteration. This is the first step before consuming paginated data. ```php paginate(new GetLikedSongsRequest); ``` -------------------------------- ### Add HasFormBody Trait for Form Data Source: https://docs.saloon.dev/the-basics/request-body-data/form-body-url-encoded The `HasFormBody` trait implements the `body()` method required by `HasBody` and provides a `defaultBody()` method for setting default form parameters. This example adds the trait to the `CreateServerRequest`. ```php send(new GetSongsByArtistRequest('Luke Combs')); // 200 body: [{name: 'When it rains, it pours'}] ``` -------------------------------- ### Manipulate Form Request Body at Runtime Source: https://docs.saloon.dev/the-basics/request-body-data/form-body-url-encoded Saloon provides methods to dynamically add, remove, merge, or set form body parameters on a per-request basis. This example shows how to use `add`, `merge`, and `all` methods. ```php body()->add('ubuntu_version', '22.04'); $request->body()->merge([ 'type' => 'app', 'provider' => 'ocean2', ]); $body = $request->body()->all(); // array: [ // 'ubuntu_version' => '22.04', // 'type' => 'app', // 'provider' => 'ocean2', // ] ``` -------------------------------- ### Define SDK Method for Sending Request Source: https://docs.saloon.dev/digging-deeper/building-sdks Illustrates adding a custom method to the Saloon connector class to simplify sending specific API requests. This method encapsulates the request creation and sending logic, providing a cleaner interface for SDK users. ```php class Pokeapi extends Connector { // ... public function allPokemon(int $page): Response { return $this->send(new GetAllPokemon($page)); } } ``` -------------------------------- ### Use Fixture for Mocking Responses in PHP Source: https://docs.saloon.dev/the-basics/testing This snippet demonstrates how to use `MockResponse::fixture()` to mock API responses using predefined fixture files. It's useful for simulating API behavior during testing without making actual HTTP requests. Dependencies include Saloon's mocking components. ```php MockResponse::fixture('servers'), ]); $this->assertDatabaseCount('servers', 0); // Call our controller which will invoke the Saloon request $this ->getJson('/api/servers/sync') ->assertOk(); // Assert our database has created servers! $this->assertDatabaseCount('servers', 2); $this->assertDatabaseHas('servers', [ 'name' => 'REAL-SERVER-1', 'ip' => '192.168.0.1', ]); $this->assertDatabaseHas('servers', [ 'name' => 'REAL-SERVER-2', 'ip' => '192.168.0.2', ]); }); ``` -------------------------------- ### Define Default Form Body with Constructor Arguments Source: https://docs.saloon.dev/the-basics/request-body-data/form-body-url-encoded This example demonstrates how to set a default form body for a Saloon request by defining constructor arguments and using the `defaultBody()` method. It allows for standardized requests with required parameters. ```php $this->ubuntuVersion, 'type' => $this->type, 'provider' => $this->provider, ]; } } ``` -------------------------------- ### Update sendAndRetry Handler Signature (PHP) Source: https://docs.saloon.dev/upgrade/upgrading-from-v2 The `handleRetry` argument in `sendAndRetry` now expects a `Request` class instead of a `PendingRequest`. This change affects how retry logic is handled, ensuring that the correct request context is passed to the closure. The example demonstrates the updated signature. ```php $connector->sendAndRetry( request: $request, tries: 5, interval: 0, handleRetry: static function (Throwable $exception, Request $request) { // $request->headers()->add(); }, ); ``` -------------------------------- ### Request with Constructor Arguments Source: https://docs.saloon.dev/the-basics/requests Illustrates how to use constructor arguments to pass dynamic data, such as resource IDs, into a request class, enabling requests for specific resources. ```APIDOC ## GET /servers/{id} ### Description Retrieves a specific server by its ID. The ID is passed via the request constructor. ### Method GET ### Endpoint /servers/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the server. #### Query Parameters None #### Request Body None ### Request Example ```php id; } } // Creating an instance of the request with a specific ID $request = new GetServerRequest('5664b05b-8b32-4523-a0d5-837f5080417a'); ``` ### Response #### Success Response (200) - **server** (object) - The server object with the specified ID. #### Response Example ```json { "server": { "id": "5664b05b-8b32-4523-a0d5-837f5080417a", "name": "Specific Server" } } ``` ``` -------------------------------- ### Add HasMultipartBody Trait for Multipart Requests Source: https://docs.saloon.dev/the-basics/request-body-data/multipart-form-body The `HasMultipartBody` trait simplifies handling multipart/form-data. It implements the required `body()` method from `HasBody` and provides a `defaultBody()` method for setting up the request's body. This example adds the trait to the `UploadProfilePictureRequest` class. ```php 'text/plain', ]; } } ```