https://github.com/firehed/api
A PHP API toolkit
https://github.com/firehed/api
api framework php php-framework
Last synced: 7 months ago
JSON representation
A PHP API toolkit
- Host: GitHub
- URL: https://github.com/firehed/api
- Owner: Firehed
- Created: 2015-09-14T23:48:25.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2023-04-20T13:58:31.000Z (almost 3 years ago)
- Last Synced: 2025-02-13T22:27:00.196Z (about 1 year ago)
- Topics: api, framework, php, php-framework
- Language: PHP
- Size: 264 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 20
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# API Framework
[](https://github.com/Firehed/api/actions?query=workflow%3ATest+branch%3Amaster)
[](https://codecov.io/gh/Firehed/api)
## Installation
API is available via composer:
`composer require firehed/api`
## Usage
Set up an `.apiconfig` file, which contains JSON-formatted settings for the framework.
You may run `vendor/bin/api generate:config` to do this.
See configuration below for additional information.
Generate a default front-controller:
`vendor/bin/api generate:frontController`
After creating, modifying, or deleting endpoints, run the compiler:
`vendor/bin/api compile:all`
This step is _not_ optional: the framework depends on the generated files, rather than ever attempting to perform the same step at runtime.
It is expected that you will rebuild the files on every build/deployment with the above command.
See the section on best practices below.
## Testing
For convenience, a trait is included that includes tests for the description methods of your endpoints.
In your test case class (which typically extends `PHPUnit\Framework\TestCase`, use the trait:
`\Firehed\API\Traits\EndpointTestCases`
And add a `getEndpoint` method that returns an instance of the endpoint under test.
### Example
```php
getHeaderLine('Authorization'), 2);
// Find a user, app, etc. from the token string
return new Container([
App::class => $app,
User::class => $user,
// ...
'oauth_scopes' => $scopes,
]);
}
public function authorize(AuthenticatedEndpointInterface $endpoint, ContainerInterface $container): Ok
{
$scopes = $container->get('oauth_scopes');
if (!$endpoint instanceof YourInternalScopeInterface) {
throw new \LogicException('Endpoint is invalid');
}
// This is a method in YourInternalScopeInterface
$neededScopes = $endpoint->getRequiredScopes();
foreach ($neededScopes as $scope) {
if (!in_array($scope, $scopes)) {
throw new AuthException(sprintf('Missing scope %s', $scope));
}
}
return new Ok();
}
}
```
## Error Handling
It is strongly discouraged to handle most exceptions that are thrown in an Endpoint's `execute()` method.
Instead, prefer to write services that fail loudly by throwing exceptions and endpoints that expect the success case.
This is not an absolute rule, but helps avoid deeply-nested `try`/`catch` blocks and other complexity around error handling.
The API framework is responsible for catching all exceptions thrown during an Endpoint's `execute()` method, and will provide them to dedicated exception handlers.
It is highly recommended to create and provide a default error handler, `Firehed\API\Errors\HandlerInterface`, via the container (see table above).
All unhandled exceptions will be sent to that handler, along with the request (so that responses can be formatted according to `Accept` headers, etc).
All endpoints that implement `Firehed\API\Interfaces\HandlesOwnErrorsInterface` (which is a part of `EndpointInterface` prior to v4.0.0) will have their `handleException()` method called with the thrown exception.
This handler will be called _before_ the default error handler.
This method _may_ choose to ignore certain exception classes (by rethrowing them), but must return a PSR `ResponseInterface` when opting to handle an exception.
Finally, a global fallback handler is configured by default, which will log the exception and return a generic 500 error.
## Best Practices
### Source Control
Use source control, of course.
The following patterns should be added to your source control's ignored files, to exclude generated files:
- `__*__.*`
### Build Automation
It is highly recommended (for any modern PHP application) to use automated builds.
This framework relies on compilation in order to improve performance.
You **must** run the compilation process prior to deployment, and **should** do so during your automated build:
`vendor/bin/api compile:all`.
### Docker
There are no special requirements to run in Docker, beyond what is noted in the above build automation section.
This means you should have the following line in your Dockerfile at any point after installing dependencies with Composer:
```Dockerfile
RUN vendor/bin/api compile:all
```
You **should** also add all of the source control ignore files to your `.dockerignore`.
## Compatibility
This framework tries to strictly follow the rules of Semantic Versioning.
In summary, this means that given a release named `X.Y.Z`:
- Breaking changes will only be introduced when `X` is incremented
- New features will only be introduced either when `Y` is incremented or when `X` is incremented and `Y` is reset to `0`
- Bugfixes may be introduced in any version increment
The term "breaking changes" should be interpreted to mean:
- Additional required parameters being added to methods
- Additional methods being added to interfaces
- Tightening the typehints of a method or function parameter
- Loosening the return type of a method or function
- Deletion of any public method (except on classes marked as internal)
- Additional system requirements (PHP version, extensions, etc.)
- Substantial, non-optional behavior changes
- Required modifications to documented build steps (e.g. `vendor/bin/api compile:all`)
Breaking changes DO NOT include:
- Removal of a dependency (if you are implicitly relying on a dependency of this framework, you should explicitly add it into your own `composer.json`)
- Removal of a class or method that is clearly marked internal
- Format or content changes to any files that are intended to be generated during the compilation process, including adding or removing files entirely
Whenever possible, deprecated functionality will be marked as such by `trigger_error(string, E_USER_DEPRECATED)` (in addition to release notes).
Note that depending on your PHP settings, this may result in an `ErrorException` being thrown.
Since that is a configurable behavior, it is NOT considered to be a BC break.
Additionally, the entire `Firehed\API` namespace should be considered reserved for the purposes of PSR-11 Container auto-detection.
That is to say, if you use a key starting with `Firehed\API` in your container, you should expect that key may be retrieved and used without explicitly opting-in to the behavior it provides.