Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ After installing, register `dot-annotated-services` in your project by adding th

## Usage

### Using the AnnotatedServiceFactory
### Using the AttributedServiceFactory

You can register services in the service manager using `AnnotatedServiceFactory` as seen in the below example:
You can register services in the service manager using `AttributedServiceFactory` as seen in the below example:

```php
return [
'factories' => [
ServiceClass::class => AnnotatedServiceFactory::class,
ServiceClass::class => AttributedServiceFactory::class,
],
];
```
Expand All @@ -54,19 +54,19 @@ The next step is to add the `#[Inject]` attribute to the service constructor wit
use Dot\AnnotatedServices\Attribute\Inject;

#[Inject(
Dependency1::class,
Dependency2::class,
App\Srevice\Dependency1::class,
App\Srevice\Dependency2::class,
"config",
)]
public function __construct(
protected Dependency1 $dep1,
protected Dependency2 $dep2,
protected App\Srevice\Dependency1 $dep1,
protected App\Srevice\Dependency2 $dep2,
protected array $config
) {
}
```

The `#[Inject]` attribute is telling `AnnotatedServiceFactory` to inject the services specified as parameters.
The `#[Inject]` attribute is telling `AttributedServiceFactory` to inject the services specified as parameters.
Valid service names should be provided, as registered in the service manager.

To inject an array value from the service manager, you can use dot notation as below
Expand All @@ -82,7 +82,7 @@ which will inject `$container->get('config')['debug'];`.


### NOTE
> Even if using dot notation, `AnnotatedServiceFactory` will check first if a service name exists with that name.
> Even if using dot notation, `AttributedServiceFactory` will check first if a service name exists with that name.


### Using the AttributedRepositoryFactory
Expand Down
1 change: 1 addition & 0 deletions docs/book/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../../README.md
37 changes: 37 additions & 0 deletions docs/book/v4/cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Caching the annotations

`dot-annotated-services` reads class annotations using [doctrine/annotations](https://github.com/doctrine/annotations) and caches them using [doctrine/cache](https://github.com/doctrine/cache).


## Configuration

In order to cache annotations, you should register a service factory at key `AbstractAnnotatedFactory::CACHE_SERVICE` that should return a valid `Doctrine\Common\Cache\Cache` cache driver.
See [Cache Drivers](https://github.com/doctrine/cache/tree/1.13.x/lib/Doctrine/Common/Cache) for available implementations offered by doctrine.

See below an example on how you can configure `dot-annotated-services` to cache annotations.
You can add this configuration values to your application's Doctrine config file:

```php
'annotations_cache_dir' => __DIR__ . '/../../data/cache/annotations',
'dependencies' => [
'factories' => [
Dot\AnnotatedServices\Factory\AbstractAnnotatedFactory::CACHE_SERVICE => YourApp\Factory\AnnotationsCacheFactory::class,
],
];
```
where `AnnotationsCacheFactory` is a custom factory that needs to return a [Doctrine Cache Driver](https://github.com/doctrine/cache/tree/1.13.x/lib/Doctrine/Common/Cache):
```php
<?php

declare(strict_types=1);

namespace YourApp\Factory;

class AnnotationsCacheFactory
{
public function __invoke(Psr\Container\ContainerInterface $container)
{
return new Doctrine\Common\Cache\FilesystemCache($container->get('config')['annotations_cache_dir']);
}
}
```
6 changes: 6 additions & 0 deletions docs/book/v4/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Configuration

After installation, register `dot-annotated-services` in your project by adding the below line to your configuration aggregator (usually: `config/config.php`):

Dot\AnnotatedServices\ConfigProvider::class,

69 changes: 69 additions & 0 deletions docs/book/v4/factories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Factories

`dot-annotated-services` is based on 3 reusable factories - `AnnotatedRepositoryFactory`, `AnnotatedServiceFactory` and `AnnotatedServiceAbstractFactory` - able to inject any dependency into a class.

## AttributedRepositoryFactory

Injects entity repositories into a class.


### Exceptions thrown
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not exist
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not extend `Doctrine\ORM\EntityRepository`
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not have `@Entity` annotation
- `Psr\Container\NotFoundExceptionInterface` if `Doctrine\ORM\EntityManagerInterface` does not exist in the service container
- `Psr\Container\ContainerExceptionInterface` if service manager is unable to provide an instance of `Doctrine\ORM\EntityManagerInterface`


## AttributedServiceFactory

Injects class dependencies into classes.

If a dependency is specified using the dot notation, `AttributedServiceFactory` will try to load a service having that specific alias.
If it does not find one, it will try to load the dependency as a config tree, checking each segment if it's available in the service container.

You can use the inject annotation on setters too, they will be called at creation time and injected with the configured dependencies.


### Exceptions thrown
- `Dot\AnnotatedServices\Exception\RuntimeException` if service does not exist
- `Dot\AnnotatedServices\Exception\RuntimeException` if service does not have `@Inject` annotation on it's constructor
- `ReflectionException` on failure of creating a ReflectionClass of the dependency
- `Psr\Container\NotFoundExceptionInterface` if a dependency does not exist in the service container
- `Psr\Container\ContainerExceptionInterface` if service manager is unable to provide an instance of a dependency


## AnnotatedServiceAbstractFactory

Using this approach, no service manager configuration is required. It uses the registered abstract factory to create annotated services.

In order to tell the abstract factory which services are to be created, you need to annotate the service class with the `@Service` annotation.

```php
<?php

declare(strict_types=1);

namespace YourApp\Service;

/**
* @Dot\AnnotatedServices\Annotation\Service
*/
class Example
{
/**
* @Dot\AnnotatedServices\Annotation\Inject({
* YourApp\Repository\Dependency1::class,
* YourApp\Repository\Dependency2::class,
* "config.example"
* })
*/
public function __construct(
protected YourApp\Repository\Dependency1 $dependency1,
protected YourApp\Helper\Dependency2 $dependency2,
protected array $exampleConfig,
) {
}
}
```
And that's it, you don't need to configure the service manager with this class, creation will happen automatically.
59 changes: 59 additions & 0 deletions docs/book/v4/factories/repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Inject entity repositories


## Prepare repository

`dot-annotated-services` determines the entity a repository is related to by looking at the `@Entity` annotation, added to the repository class.

```php
<?php

declare(strict_types=1);

namespace YourApp\Repository;

/**
* @Dot\AnnotatedServices\Annotation\Entity(name="YourApp\Entity\Example")
*/
class ExampleRepository extends Doctrine\ORM\EntityRepository
{
}
```

Each entity repository must extend `Doctrine\ORM\EntityRepository`.


## Register repository

Open the ConfigProvider of the module where your repository resides.

Add a new entry under `factories`, where the key is your repository FQCN and the value is `Dot\AnnotatedServices\Factory\AnnotatedRepositoryFactory::class`.

See below example for a better understanding of the file structure.

```php
<?php

declare(strict_types=1);

namespace YourApp;

class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => $this->getDependencies(),
];
}

public function getDependencies(): array
{
return [
'factories' => [
YourApp\Repository\ExampleRepository::class => Dot\AnnotatedServices\Factory\AnnotatedRepositoryFactory::class,
],
];
}
}
```
86 changes: 86 additions & 0 deletions docs/book/v4/factories/service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Inject class dependencies


## Prepare class

`dot-annotated-services` determines the dependencies by looking at the `@Inject` annotation, added to the constructor of a class.
Dependencies are specified as one parameter, which is an array of FQCNs.

```php
<?php

declare(strict_types=1);

namespace YourApp\Service;

class Example
{
/**
* @Dot\AnnotatedServices\Annotation\Inject({
* YourApp\Repository\Dependency1::class,
* YourApp\Repository\Dependency2::class,
* "config"
* })
*/
public function __construct(
protected YourApp\Repository\Dependency1 $dependency1,
protected YourApp\Helper\Dependency2 $dependency2,
protected array $config
) {
}
}
```

If your class needs the value of a specific configuration key, you can specify the path using dot notation:

```php
/**
* @Dot\AnnotatedServices\Annotation\Inject({
* YourApp\Repository\Dependency1::class,
* YourApp\Repository\Dependency2::class,
* "config.example"
* })
*/
public function __construct(
protected YourApp\Repository\Dependency1 $dependency1,
protected YourApp\Helper\Dependency2 $dependency2,
protected array $exampleConfig,
) {
}
```


## Register class

Open the ConfigProvider of the module where your class resides.

Add a new entry under `factories`, where the key is your class FQCN and the value is `Dot\AnnotatedServices\Factory\AnnotatedServiceFactory::class`.

See below example for a better understanding of the file structure.

```php
<?php

declare(strict_types=1);

namespace YourApp;

class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => $this->getDependencies(),
];
}

public function getDependencies(): array
{
return [
'factories' => [
YourApp\Service\Example::class => Dot\AnnotatedServices\Factory\AnnotatedServiceFactory::class,
],
];
}
}
```
5 changes: 5 additions & 0 deletions docs/book/v4/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Installation

Install `dotkernel/dot-annotated-services` by executing the following Composer command:

composer require dotkernel/dot-annotated-services
5 changes: 5 additions & 0 deletions docs/book/v4/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Overview

`dot-annotated-services` is DotKernel's dependency injection service.

By providing reusable factories for service and repository injection, it reduces code complexity in projects.
7 changes: 7 additions & 0 deletions docs/book/v4/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Usage

Version `4.x` of `dot-annotated-services` is the last version that uses [doctrine/annotations](https://github.com/doctrine/annotations) to parse and inject dependencies.

You can use it to:
- [Inject class dependencies](factories/service.md)
- [Inject entity repositories](factories/repository.md)
6 changes: 6 additions & 0 deletions docs/book/v5/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Configuration

After installation, register `dot-annotated-services` in your project by adding the below line to your configuration aggregator (usually: `config/config.php`):

Dot\AnnotatedServices\ConfigProvider::class,

31 changes: 31 additions & 0 deletions docs/book/v5/factories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Factories

`dot-annotated-services` is based on 2 reusable factories - `AttributedRepositoryFactory` and `AttributedServiceFactory` - able to inject any dependency into a class.

## AttributedRepositoryFactory

Injects entity repositories into a class.


### Exceptions thrown
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not exist
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not extend `Doctrine\ORM\EntityRepository`
- `Dot\AnnotatedServices\Exception\RuntimeException` if repository does not have `#[Entity]` attribute
- `Psr\Container\NotFoundExceptionInterface` if `Doctrine\ORM\EntityManagerInterface` does not exist in the service container
- `Psr\Container\ContainerExceptionInterface` if service manager is unable to provide an instance of `Doctrine\ORM\EntityManagerInterface`


## AttributedServiceFactory

Injects class dependencies into classes.

If a dependency is specified using the dot notation, `AttributedServiceFactory` will try to load a service having that specific alias.
If it does not find one, it will try to load the dependency as a config tree, checking each segment if it's available in the service container.


### Exceptions thrown
- `Dot\AnnotatedServices\Exception\RuntimeException` if service does not exist
- `Dot\AnnotatedServices\Exception\RuntimeException` if service does not have `#[Inject]` attribute on it's constructor
- `Dot\AnnotatedServices\Exception\RuntimeException` if service tries to inject itself recursively
- `Psr\Container\NotFoundExceptionInterface` if a dependency does not exist in the service container
- `Psr\Container\ContainerExceptionInterface` if service manager is unable to provide an instance of a dependency
Loading