Download the PHP package nsrosenqvist/php-api-toolkit without Composer
On this page you can find all versions of the php package nsrosenqvist/php-api-toolkit. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download nsrosenqvist/php-api-toolkit
More information about nsrosenqvist/php-api-toolkit
Files in nsrosenqvist/php-api-toolkit
Package php-api-toolkit
Short Description API Toolkit is a PHP library for working with REST APIs.
License MIT
Homepage https://github.com/nsrosenqvist/php-api-toolkit
Informations about the package php-api-toolkit
PHP Api Toolkit
This toolkit is a wrapper around Guzzle 7 that allow you to work with dedicated clients for a particular remote API. It automatically applies configuration in a seamless manner and keeps code modular and neatly organized. The goal of this library is to remove the need for API specific SDKs and instead provide most functionality you need out of the box, and this includes a comprehensive mocking middleware.
Installation
The library requires PHP 7.4+ and can be installed using composer:
Usage
The core concept is that each remote API and its associated configuration and authorization is contained within a single class which inherits NSRosenqvist\ApiToolkit\ADK
. The ADK class contains the core functionality which the library is utilizing, but a more featured base class comes bundled that provides the functionality that one would commonly need. Therefore, one would most often base one's drivers on NSRosenqvist\ApiToolkit\StandardApi
instead, and any required customizations can easily be performed by overloading methods.
A simple driver only needs basic client configuration and the means of authorization:
The first parameter to the parent ADK class is an array
defining the Guzzle client options, the second one define the default request options. All the default middleware are configured through request options.
Now one can make requests using this configuration by invoking the regular Guzzle methods on the driver class.
Inheritance
No methods are private, since the intention is that child-classes should be able to overload and modify functionality of the base library as needed. The documentation touches on the most common use cases, but please refer to the source code for a comprehensive overview.
Handlers
Most often, only two methods need to be overloaded by the driver. The first is resultHandler
which processes the resulting response, both for synchronous and asynchronous requests. It needs to return a \Psr\Http\Message\ResponseInterface
, and the example below makes use of the built-in \NSRosenqvist\ApiToolkit\Result
structure that implements the interface while also providing some additional useful features.
The error handler gets invoked whenever the request fails for some reason. Here you can take any required action, such as logging, and then either return the exception or rethrow it.
Please note that if http_errors
are set to false (as in the example), then the error handler won't process automatically but must instead be manually called from the result handler. Either one could handle successful requests and errors both in the result handler, or just create a \GuzzleHttp\Exception\RequestException
and pass it on to the error handler. The built-in recorder middleware makes sure that the original request is accessible through the response.
Manager
A manager class comes built-in, which is meant to be used as a singleton. Use this to easily access APIs from different places in your codebase, preferably through dependency injection or a facade (see the included LaravelApiProvider
service provider).
If you register the APIs by their FQN as strings and use an autoloader, then they won't be loaded into memory before you actually make use of them.
Chains
One of the big additions of this library is the concept of request chains. If a non-existant property is accessed on the driver, a new request chain is created. These are simple object-oriented representations of a request, suitable for when integrating towards RESTful APIs. All usual Guzzle magic methods are supported, and the only difference is that they don't accept the URI in the method call, instead it gets dynamically resolved from the chain.
The chain gets resolved by the initating driver, so to customize how it should be resolved one would overload the resolve
method.
Chains can easily be initated with custom options, if one would like to provide a simple convenience method for defining the target API version, like in the example above, one could create a custom method on the driver returning a new request chain.
Then one could simply call a specific version of the API by initiating the chain using the method version
:
Mocking
It's easy to test APIs built using this toolkit, either include the mock middleware in your handler stack or base the driver on \NSRosenqvist\ApiToolkit\StandardApi
to have it included by default. To simply make all requests return 200 (by default), and never be sent away to a remote server, just enable mocking using the request option mock
or by toggling it for subsequent requests through the method mocking
.
Queue
A better method is to predefine what responses should be returned using the queue system. When responses are queued, the mocking middleware will be enabled automatically and doesn't need to be disabled afterwards.
Manifest
Mock manifests are basically router files that define what responses should be given to different requests. It's a quite flexible syntax that is designed to help you write as little configuration as possible. Only PHP and JSON files are supported out of the box, but you can easily enable JSONC or Yaml support by requiring either adhocore/json-comment
or symfony/yaml
in your composer.json
file.
The basic syntax is as follows:
content
can either be a simple string, or a path to directory containing files defining response bodies (set the default request parameter stubs
). Absolute paths will work as well.
Variable matching
One can create multiple response definitions for the same route by wrapping them in an array and using a match statement. In the example below, a request to foo/bar/lorem
would yield a 200 response, while a request to foo/bar/ipsum
would yield a 202.
The variable names "query" and "method" are reserved, since they are used for defining conditions for method and query matching.
Wildcard patterns
You can even mix and match named variables with glob wildcards:
The routes will be matched according to specificity, so named variables will be prioritized before wildcards. Under the hood the wildcard matching uses fnmatch
and therefore one could use more advanced patterns, but they are not officially supported.
Method matching
The method key in the match definition allows one to specify different responses for different methods.
Query conditions
In addition to variable matching, one can also test the query parameters (these will also be prioritized in order of specificity).
Advanced query matching
In addition to direct comparisons, one can instead set any of these special comparison operators:
__isset__
: Tests whether the parameter exist.__missing__
: Tests whether the parameter does not exist.__true__
: Tests whether the parameter is truthy (this includes, "yes", "y", 1, etc.).__false__
: Tests whether the parameter is falsey (this includes, "no", "n", 0, etc.).__bool__
: Tests whether the parameter is booly.__string__
: Tests whether the parameter is a string.__numeric__
: Tests whether the parameter is a numeric.__int__
: Tests whether the parameter is an int.__float__
: Tests whether the parameter is a float.__array__
: Tests whether the parameter is an array.
Alternative syntaxes
In order to minimize required configuration, some alternative syntaxes are also supported. These will be normalized upon import.
Short syntax
REST syntax
The REST syntax allows one to define responses according to HTTP method (the method will be expanded into match->method
, like a regular method match). This syntax also supports short syntax definitions.
Structures
The library comes with a couple of built-in general data structures that are meant to remove the need for custom data structures. However, this comes with no type validation, but that could easily be implemented in the result handler using something like JSON Schema, if desired.
ObjectData
The NSRosenqvist\ApiToolkit\Structures\ObjectData
class is a general purpose object that provides both property and array access to its members. This means that the following means of using it are equivalent and the code sample will output "true":
It also implements Illuminate\Contracts\Support\Arrayable
and Illuminate\Contracts\Support\Jsonable
which allows it to be easily converted into an array (toArray
) or JSON (toJson
).
ListData
The NSRosenqvist\ApiToolkit\Structures\ListData
class is a general purpose list data structure. It supports array access, and like NSRosenqvist\ApiToolkit\Structures\ObjectData
, it can also be easily converted to an array or JSON.
Macros
Both NSRosenqvist\ApiToolkit\Structures\ObjectData
and NSRosenqvist\ApiToolkit\Structures\ListData
supports macros. You can define custom methods that will be available on all instances of the classes (or on a child-class if you want to keep macros separate per API driver).
Result
The NSRosenqvist\ApiToolkit\Structures\Result
class is an implementation of \Psr\Http\Message\ResponseInterface
that provides direct access to the underlying response body data. It defines a couple of convenience methods, like success
and failure
, but mostly it serves as a wrapper around the provided data. If the data is a NSRosenqvist\ApiToolkit\Structures\ListData
, it can be iterated upon directly, and if NSRosenqvist\ApiToolkit\Structures\ObjectData
, then it can be accessed directly.
Included Middleware
\NSRosenqvist\ApiToolkit\StandardApi
includes a couple of default middleware that are meant to provide common API SDK functionality.
CacheMiddleware
The included caching mechanism is a very simple implementation that only makes sure that the same request isn't executed more than once per PHP request process. It only does this for GET requests. The middleware can be toggled on and off by using the option flag cache
.
\NSRosenqvist\ApiToolkit\StandardApi
implements a helper method, named cache
, that toggles the setting for current request chain.
MockMiddleware
The functionality of the mocking middleware is described under the section on mocking. It is configured for each request using request options, but this is handled automatically in \NSRosenqvist\ApiToolkit\StandardApi
. The options it accepts are:
mock
: Enable or disable the middleware.manifest
: An object or path to the manifest for mock routing.stubs
: The directory containing files that the manifest can return as content.response
: A directly defined response that will be returned (used by StandardApi's queue functionality).
RecorderMiddleware
The recorder middleware simply replaces the response with a \NSRosenqvist\ApiToolkit\RetrospectiveResponse
which also keeps a reference to the current request. This is in order to be able to do request dependent processing in the result handler. If this isn't required you can simply overload the getHandlerStack
method and skip including this middleware.
Similar functionality can be achieved by inspecting the option endpoint
, which gets automatically set on requests relative to the base URI. Absolute requests will instead have the option url
set.
RetryMiddleware
The retry middleware will perform the request again if the remote returned 429, with a maximun number of retries and exponential delay. This middleware is controlled by the option max_retries
. It also supports custom retry-decider callbacks.
License
The library is licensed under MIT and certain middlewares are based on ones included by default in Guzzle 7, which are also under MIT. Some of the data structures are based on ones from the Illuminate libraries, which are also licensed under MIT.
Development
Contributions are very much welcome. If you clone the repo and then run composer install
, certain hooks should automatically be configured that make sure code standards are upheld before any changes can be pushed. We try to follow PSR-12 and maintain compatibity with PHP 7.4 for now. See composer.json for configured commands (e.g. test
, lint
, compat
).
All versions of php-api-toolkit with dependencies
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
guzzlehttp/guzzle Version ^7.5
jrfnl/php-cast-to-type Version ^2.1
illuminate/support Version >=5.5