Service Proxy
, (*1)
Service Proxy is a library that provides functionality to manage technical code over a class:
- Transactional context
- Security access
- Cache management
- Events
- Logs (not implemented yet), (*2)
Installation
The easiest way to install ServiceProxy is via composer., (*3)
Create the following composer.json
file and run the php composer.phar install
command to install it., (*4)
{
"require": {
"openclassrooms/service-proxy": "*"
}
}
```php
<?php
require 'vendor/autoload.php';, (*5)
use OpenClassrooms\ServiceProxy\ServiceProxy;, (*6)
//do things, (*7)
## Concepts
### Interceptors
Interceptors are used as decorators to react to the method execution.
for example using `@Cache` annotation, is a condition to enable the cache interceptor.
There is two types of interceptors:
#### Prefix interceptors :
Interceptors that are called before the method execution, they must implement `OpenClassrooms\ServiceProxy\Interceptor\Contract\PrefixInterceptor`
Three methods are called:
- `prefix` : called before the method execution. Should return instance of `OpenClassrooms\ServiceProxy\Interceptor\Response\Response`.
- `supportsPrefix` : called to know if the interceptor should be called, for example in the case of the cache interceptor, it will check that the method has the `@Cache` annotation.
- `getPrefixPriority` : called to know the priority of the interceptor, the higher the priority, the earlier the interceptor will be called.
#### Suffix interceptors :
Interceptors that are called after the method execution, even if an exception is thrown, they must implement `OpenClassrooms\ServiceProxy\Interceptor\Contract\SuffixInterceptor`
Three methods are called:
- `suffix` : called after the method execution even if an exception is thrown. should return instance of `OpenClassrooms\ServiceProxy\Interceptor\Response\Response`.
- `supportsSuffix` : called to know if the interceptor should be called, for example in the case of the cache
interceptor, it will check that the method has the `@Cache` annotation.
- `getSuffixPriority` : called to know the priority of the interceptor, the higher the priority, the earlier the interceptor will be called.
#### Handling exceptions
If you want to react to an exception thrown by the method, you can check for the exception in the suffix interceptor.
- To check `$instance->method()->threwException()`
- To get the exception (null if no exception was thrown) `$instance->method()->getException()`
- To get the return value (null in case of an exception) `$instance->method()->getReturnValue()`
#### Early return
- If a prefix interceptor returns a response with early return parameter set to `true` ex: `Response($data, true)`, the method won't be executed and the suffix interceptors won't be called.
- If a suffix interceptor returns a response with early return parameter set to `true`, the exception won't be thrown, in the case of a method that throws an exception.
You can create your own interceptors, or use the built-in ones:
### Handlers
Handlers are used by interceptors to manage the infrastructure code.
To be able to use built-in interceptors, you need to implement the built-in handlers contracts.
- All handles need to implement `OpenClassrooms\ServiceProxy\Handler\Contract\AnnotationHandler`.
- Each handler must have a unique name, you can use the `getName` method to return it.
- Each handler must return true if it's the default handler or false if not, you can use the `isDefault` method to return it.
- You can't have two handlers with the same name by annotation.
- You can have only one default handler, by annotation.
- If you have only one handler by annotation, it will be the default one.
**example:**
```php
use OpenClassrooms\ServiceProxy\Annotation\Cache;
/**
* @Cache(handler="in_memory")
* to select the in_memory handler
*/
```
## Usage
### Instantiation
#### Symfony
Check out the [ServiceProxyBundle](http://github.com/openclassrooms/ServiceProxyBundle).
The bundle provides an easy configuration option for this library.
#### Manual
##### Example
First implement the handlers
```php
use OpenClassrooms\ServiceProxy\Handler\Contract\CacheHandler;
class InMemoryCacheHandler implements CacheHandler
{
public function getName(): string
{
return 'in_memory';
}
...
}
class RedisCacheHandler implements CacheHandler
{
public function getName(): string
{
return 'redis';
}
...
}
Then you can inject the handlers into the interceptors:, (*8)
$cacheInterceptor = new CacheInterceptor([new ArrayCacheHandler(), new RedisCacheHandler()]);
$prefixInterceptors = [
$cacheInterceptor,
new EventInterceptor([/* event handlers */]),
new TransactionInterceptor([/* transaction handlers */]),
new SecurityInterceptor([/* security handlers */]),
];
$suffixInterceptors = [
$cacheInterceptor,
new EventInterceptor(),
new TransactionInterceptor(),
];
$serviceProxyFactory = new ProxyFactory(
new Configuration(), //if no proxies directory is provided, the system tmp dir is used
$prefixInterceptors,
$SecurityInterceptor,
);
$proxy = $serviceProxyFactory->createProxy(new Class());
Built-in interceptors
Acknowledgments
This library is based on Ocramius\ProxyManager., (*9)