Skip to content

Add HasApiVersion trait for API versioning - #564

Merged
Sammyjo20 merged 6 commits into
saloonphp:v4from
JonPurvis:api-versioning
Oct 3, 2026
Merged

Sammyjo20 merged 6 commits into
saloonphp:v4from
JonPurvis:api-versioning

Conversation

@JonPurvis

@JonPurvis JonPurvis commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Why

Lots of APIs version their surface in different ways:

  • Headers (Stripe-Version: 2026-08-26.dahlia, Stripe-style version strings)
  • Query params (?api-version=2026-10)
  • Path segments (/v1beta/...)
  • Subdomains (https://v2.api.provider.com)

This PR adds a small opt-in plugin so versioning is declarative on the connector/request instead of hand-rolled in boot() / middleware. It also makes it easy to override the default: set a version on the connector, then call setApiVersion() on a specific request when one endpoint needs a different version.

Summary

  • New Saloon\Traits\Plugins\HasApiVersion plugin with setApiVersion() / getApiVersion()
  • New Saloon\Enums\VersionMode: Header, QueryParam, Subdomain, UrlPath
  • Configurable key via $versionKey (default api-version)
  • {version} placeholder replacement for path/subdomain modes
  • No-op when $apiVersion is null
  • Pest coverage for all modes, connector/request overrides, and the null guard

Usage

Header

class StripeConnector extends Connector
{
    use HasApiVersion;

    protected ?string $apiVersion = '2026-08-26.dahlia';
    protected VersionMode $versionMode = VersionMode::Header;
    protected string $versionKey = 'Stripe-Version';

    public function resolveBaseUrl(): string
    {
        return 'https://api.stripe.com';
    }
}

Sends Stripe-Version: 2026-08-26.dahlia.

Query param

protected VersionMode $versionMode = VersionMode::QueryParam;
protected ?string $apiVersion = '2026-10';

Sends ?api-version=2026-10.

URL path

protected VersionMode $versionMode = VersionMode::UrlPath;
protected ?string $apiVersion = 'v1beta';

public function resolveBaseUrl(): string
{
    return 'https://generativelanguage.googleapis.com/{version}';
}

Becomes https://generativelanguage.googleapis.com/v1beta.

Subdomain

protected VersionMode $versionMode = VersionMode::Subdomain;
protected ?string $apiVersion = 'v2';

public function resolveBaseUrl(): string
{
    return 'https://{version}.api.provider.com';
}

Becomes https://v2.api.provider.com.

Runtime override

Useful when most of an API shares one version, but a single endpoint still needs an older (or newer) one — e.g. a beta route, a deprecated migration path, or a vendor that versioned only part of their surface.

$connector->setApiVersion('override-version');
// or
$request->setApiVersion('override-version');

Prefer the request override when only that one call should differ. Prefer the connector override when you want the new version applied to all requests sent through that connector.

@JonPurvis JonPurvis changed the title Api versioning Add HasApiVersion trait for API versioning Sep 29, 2026
@JonPurvis
JonPurvis marked this pull request as ready for review September 29, 2026 14:35

@Sammyjo20 Sammyjo20 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this idea.

Comment thread src/Traits/Plugins/HasApiVersion.php Outdated

@JonPurvis JonPurvis left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!!

I can't approve my own PR, BUT, here's a 👍

@Sammyjo20
Sammyjo20 merged commit 2f45e52 into saloonphp:v4 Oct 3, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants