|
| 1 | +# Upgrade to 3.0 |
| 2 | + |
| 3 | +Version 3.0 is a full architecture refresh. This is not a step-by-step migration guide because most SDKs should be reshaped around the new authoring model instead of mechanically replacing old calls. |
| 4 | + |
| 5 | +Use this document as a short summary of what changed and where to look when updating an SDK. |
| 6 | + |
| 7 | +## Resources Use Endpoint Builders |
| 8 | + |
| 9 | +Request helpers now live behind `endpoint()` inside resources. |
| 10 | + |
| 11 | +```php |
| 12 | +return $this |
| 13 | + ->endpoint() |
| 14 | + ->get('/users/{id}', ['id' => $id]) |
| 15 | + ->entity(User::class); |
| 16 | +``` |
| 17 | + |
| 18 | +Use endpoint modifiers for request-local state: |
| 19 | + |
| 20 | +```php |
| 21 | +return $this |
| 22 | + ->endpoint() |
| 23 | + ->query('active', true) |
| 24 | + ->header('X-Tenant', $tenant) |
| 25 | + ->get('/users') |
| 26 | + ->collection(User::class, key: 'data'); |
| 27 | +``` |
| 28 | + |
| 29 | +See [Resource Authoring: Endpoint Requests](docs/04-resource-authoring.md#endpoint-requests), [Resource Authoring: Query And Headers](docs/04-resource-authoring.md#query-and-headers), and [Resources: Endpoint HTTP Methods](docs/05-resources.md#endpoint-http-methods) for details. |
| 30 | + |
| 31 | +## Responses Are First-Class |
| 32 | + |
| 33 | +Entities must implement `EntityInterface`: |
| 34 | + |
| 35 | +```php |
| 36 | +public static function fromArray(array $data, ?Context $context = null): static; |
| 37 | +``` |
| 38 | + |
| 39 | +Use response mapping helpers: |
| 40 | + |
| 41 | +```php |
| 42 | +$response->entity(User::class); |
| 43 | +$response->collection(User::class, key: 'data'); |
| 44 | +$response->envelope(UserResponse::class); |
| 45 | +``` |
| 46 | + |
| 47 | +Response envelopes must implement `ResponseEnvelopeInterface`. |
| 48 | + |
| 49 | +See [Responses: EntityInterface](docs/06-responses.md#entityinterface) and [Responses: ResponseEnvelopeInterface](docs/06-responses.md#responseenvelopeinterface) for details. |
| 50 | + |
| 51 | +## Config Replaces Ad Hoc Options |
| 52 | + |
| 53 | +SDK options should use `config()`: |
| 54 | + |
| 55 | +```php |
| 56 | +$this->config($options, defaults: [ |
| 57 | + 'timezone' => 'UTC', |
| 58 | +]); |
| 59 | +``` |
| 60 | + |
| 61 | +The same config is available to entities, response envelopes, and hooks through context objects. |
| 62 | + |
| 63 | +See [API](docs/03-api.md) and [Responses: Context](docs/06-responses.md#context) for details. |
| 64 | + |
| 65 | +## Decoding And Errors Are First-Class |
| 66 | + |
| 67 | +Response decoding is configured with `responses()`: |
| 68 | + |
| 69 | +```php |
| 70 | +$this->responses()->json(); |
| 71 | +$this->responses()->xml(); |
| 72 | +$this->responses()->custom($decoder); |
| 73 | +``` |
| 74 | + |
| 75 | +HTTP errors do not throw by default. Configure error handling explicitly: |
| 76 | + |
| 77 | +```php |
| 78 | +$this->errors()->status(404, NotFoundException::class); |
| 79 | +$this->errors()->when(fn (ErrorContext $context) => null); |
| 80 | +``` |
| 81 | + |
| 82 | +See [API](docs/03-api.md) and [Responses](docs/06-responses.md) for details. |
| 83 | + |
| 84 | +## Infrastructure Uses Builders |
| 85 | + |
| 86 | +PSR-18 clients, PSR-17 factories, PSR-6 cache, PSR-3 logging, HTTPlug authentication, plugins, and hooks are still supported. In v3, they are configured through grouped builders instead of scattered low-level methods. |
| 87 | + |
| 88 | +```php |
| 89 | +$this->auth()->bearer($token); |
| 90 | +$this->cache($pool)->defaultTtl(3600); |
| 91 | +$this->logger($logger); |
| 92 | +$this->plugins()->add($plugin); |
| 93 | +$this->hooks()->beforeRequest($hook); |
| 94 | +$this->client($client)->requestFactory($requestFactory); |
| 95 | +``` |
| 96 | + |
| 97 | +`plugins()` remains the right place for transport-level behavior. `hooks()` remains available for request and response lifecycle customization, but response decoding and error handling now have dedicated builders. |
| 98 | + |
| 99 | +Authentication is replaced by each `auth()` call unless you explicitly use `chain()`: |
| 100 | + |
| 101 | +```php |
| 102 | +use Http\Message\Authentication\Bearer; |
| 103 | +use Http\Message\Authentication\QueryParam; |
| 104 | + |
| 105 | +$this->auth()->chain( |
| 106 | + new Bearer($token), |
| 107 | + new QueryParam(['api_key' => $apiKey]), |
| 108 | +); |
| 109 | +``` |
| 110 | + |
| 111 | +See [Authentication](docs/07-authentication.md), [HTTP Client](docs/08-http-client.md), [Cache](docs/09-cache.md), [Logging](docs/10-logging.md), [Plugins](docs/11-plugins.md), and [Hooks](docs/12-hooks.md) for details. |
| 112 | + |
| 113 | +## Defaults And Endpoint Overrides |
| 114 | + |
| 115 | +SDK authors can still configure request defaults: |
| 116 | + |
| 117 | +```php |
| 118 | +$this->defaultHeaders(['Accept' => 'application/json']); |
| 119 | +$this->defaultQueries($this->config()->only(['units', 'locale'])); |
| 120 | +``` |
| 121 | + |
| 122 | +SDK authors can configure endpoint-specific cache defaults inside the endpoint chain: |
| 123 | + |
| 124 | +```php |
| 125 | +use ProgrammatorDev\Api\Builder\CacheBuilder; |
| 126 | + |
| 127 | +return $this |
| 128 | + ->endpoint() |
| 129 | + ->cache(fn (CacheBuilder $cache) => $cache->defaultTtl(60)) |
| 130 | + ->get('/live') |
| 131 | + ->collection(Event::class, key: 'data'); |
| 132 | +``` |
| 133 | + |
| 134 | +SDK users can override that cache behavior for one resource chain with `withCache()`: |
| 135 | + |
| 136 | +```php |
| 137 | +$events = $api |
| 138 | + ->events() |
| 139 | + ->withCache(fn (CacheBuilder $cache) => $cache->defaultTtl(30)) |
| 140 | + ->live(); |
| 141 | +``` |
| 142 | + |
| 143 | +Cache precedence is: |
| 144 | + |
| 145 | +```text |
| 146 | +API cache config < endpoint cache defaults < resource withCache override |
| 147 | +``` |
| 148 | + |
| 149 | +The base package provides the generic override mechanism. API-specific fluent helpers, such as `withIncludes()` or `withStatus()`, should live in the concrete SDK. |
| 150 | + |
| 151 | +See [Resource Authoring: API-Specific Resource Chains](docs/04-resource-authoring.md#api-specific-resource-chains), [Resources: Resource Cache Overrides](docs/05-resources.md#resource-cache-overrides), [Cache: Endpoint Defaults](docs/09-cache.md#endpoint-defaults), and [Cache: Resource Overrides](docs/09-cache.md#resource-overrides) for details. |
| 152 | + |
| 153 | +## Setup Is The Escape Hatch |
| 154 | + |
| 155 | +Most SDK-user customization now goes through `setup()`: |
| 156 | + |
| 157 | +```php |
| 158 | +$api->setup()->client($client); |
| 159 | +$api->setup()->plugins()->add($plugin); |
| 160 | +$api->setup()->auth()->bearer($token); |
| 161 | +``` |
| 162 | + |
| 163 | +SDK authors still configure defaults from the `Api` subclass with protected helpers such as `baseUrl()`, `defaultQueries()`, `auth()`, `responses()`, `errors()`, `cache()`, `logger()`, `plugins()`, and `hooks()`. |
| 164 | + |
| 165 | +See [API](docs/03-api.md) and [Design Approach: Escape Hatch](docs/02-design-approach.md#escape-hatch) for details. |
| 166 | + |
| 167 | +## Send Is Public |
| 168 | + |
| 169 | +`send()` is public as an advanced escape hatch. SDK users can call endpoints that are not modeled by the concrete SDK while still using the SDK's configured base URL, authentication, cache, plugins, hooks, decoding, and error handling. |
| 170 | + |
| 171 | +```php |
| 172 | +$response = $api->send('GET', '/unmodeled-endpoint', queries: [ |
| 173 | + 'page' => 1, |
| 174 | +]); |
| 175 | +``` |
| 176 | + |
| 177 | +See [API](docs/03-api.md) for details. |
| 178 | + |
| 179 | +## HTTP Client Discovery |
| 180 | + |
| 181 | +The package uses PHP-HTTP discovery for PSR-18 clients and PSR-17 factories. When the `php-http/discovery` Composer plugin is enabled, missing implementations can be installed automatically from the supported virtual packages. |
| 182 | + |
| 183 | +SDK authors may still require or suggest concrete implementations when they want control over the default HTTP stack. |
| 184 | + |
| 185 | +See [HTTP Client: SDK Author Defaults](docs/08-http-client.md#sdk-author-defaults) and [HTTP Client: SDK User Overrides](docs/08-http-client.md#sdk-user-overrides) for details. |
| 186 | + |
| 187 | +## API-Specific Behavior Belongs In SDKs |
| 188 | + |
| 189 | +API-specific options such as includes, filters, selects, or pagination should be implemented in concrete SDK resources, not in the base package. |
| 190 | + |
| 191 | +```php |
| 192 | +$users = $api |
| 193 | + ->users() |
| 194 | + ->withStatus('active') |
| 195 | + ->all(); |
| 196 | +``` |
| 197 | + |
| 198 | +See [Resource Authoring: API-Specific Resource Chains](docs/04-resource-authoring.md#api-specific-resource-chains) for details. |
| 199 | + |
| 200 | +## Test Utilities Are Support Code |
| 201 | + |
| 202 | +The v3 test helpers are intended to support this package and SDK author tests. Concrete SDKs should prefer focused tests around their own resources, entities, response envelopes, fake clients, and API-specific fluent helpers. |
0 commit comments