Skip to content

Commit be4162f

Browse files
committed
Issue #32: Replaced annotations with attributes.
Signed-off-by: alexmerlin <alex.merlin.1985@gmail.com>
1 parent 1de7ba3 commit be4162f

27 files changed

Lines changed: 587 additions & 678 deletions

README.md

Lines changed: 24 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ Run the following command in your project directory
2525
composer require dotkernel/dot-annotated-services
2626

2727

28-
After installing, add the `ConfigProvider` class to your configuration aggregate.
28+
After installing, add the `ConfigProvider` class to your configuration aggregate, usually: `config/config.php`
2929

3030
## Usage
3131

3232
### Using the AnnotatedServiceFactory
3333

34-
You can register services in the service manager using the `AnnotatedServiceFactory` as below
34+
You can register services in the service manager using `AnnotatedServiceFactory` as below:
3535
```php
3636
return [
3737
'factories' => [
@@ -43,17 +43,15 @@ return [
4343
### NOTE
4444
> You can use only the fully qualified class name as the service key
4545
46-
The next step is to annotate the service constructor or setters with the service names to inject
46+
The next step is to add the `#[Inject]` attribute to the service constructor with the service FQCNs to inject:
4747
```php
48-
use Dot\AnnotatedServices\Annotation\Inject;
49-
50-
/**
51-
* @Inject({
52-
* Dependency1::class,
53-
* Dependency2::class,
54-
* "config"
55-
* })
56-
*/
48+
use Dot\AnnotatedServices\Attribute\Inject;
49+
50+
#[Inject(
51+
Dependency1::class,
52+
Dependency2::class,
53+
"config",
54+
)]
5755
public function __construct(
5856
protected Dependency1 $dep1,
5957
protected Dependency2 $dep2,
@@ -62,105 +60,46 @@ public function __construct(
6260
}
6361
```
6462

65-
The annotation `@Inject` is telling the factory to inject the services between curly braces.
63+
The `#[Inject]` attribute is telling `AnnotatedServiceFactory` to inject the services specified as parameters.
6664
Valid service names should be provided, as registered in the service manager.
6765

6866
To inject an array value from the service manager, you can use dot notation as below
6967
```php
70-
use Dot\AnnotatedServices\Annotation\Inject;
68+
use Dot\AnnotatedServices\Attribute\Inject;
7169

72-
/**
73-
* @Inject({"config.debug"})
74-
*/
70+
#[Inject(
71+
"config.debug",
72+
)]
7573
```
74+
which will inject `$container->get('config')['debug'];`.
7675

77-
which will inject `$container->get('config')['debug'];`
7876

7977
### NOTE
80-
> Even if using dot annotation, the annotated factory will check first if a service name exists with that name
78+
> Even if using dot notation, `AnnotatedServiceFactory` will check first if a service name exists with that name.
8179
82-
You can use the inject annotation on setters too, they will be called at creation time and injected with the configured dependencies.
8380

84-
### Using the AnnotatedRepositoryFactory
85-
You can register doctrine repositories and inject them using the AnnotatedRepositoryFactory as below:
81+
### Using the AttributedRepositoryFactory
82+
You can register doctrine repositories and inject them using the `AttributedRepositoryFactory` as below:
8683
```php
8784
return [
8885
'factories' => [
89-
ExampleRepository::class => AnnotatedRepositoryFactory::class,
86+
ExampleRepository::class => AttributedRepositoryFactory::class,
9087
],
9188
];
9289
```
9390

94-
The next step is to add the `@Entity` annotation in the repository class.
91+
The next step is to add the `#[Entity]` annotation in the repository class.
9592

9693
The `name` field has to be the fully qualified class name.
9794

9895
Every repository should extend `Doctrine\ORM\EntityRepository`.
9996
```php
97+
use Api\App\Entity\Example;
10098
use Doctrine\ORM\EntityRepository;
101-
use Dot\AnnotatedServices\Annotation\Entity;
99+
use Dot\AnnotatedServices\Attribute\Entity;
102100

103-
/**
104-
* @Entity(name="App\Entity\Example")
105-
*/
101+
#[Entity(name: Example::class)]
106102
class ExampleRepository extends EntityRepository
107103
{
108-
109-
}
110-
```
111-
112-
113-
### Using the abstract factory
114-
115-
Using this approach, no service manager configuration is required. It uses the registered abstract factory to create annotated services.
116-
117-
In order to tell the abstract factory which services are to be created, you need to annotate the service class with the `@Service` annotation.
118-
```php
119-
use Dot\AnnotatedServices\Annotation\Service;
120-
121-
/*
122-
* @Service
123-
*/
124-
class ServiceClass
125-
{
126-
// configure injections as described in the previous section
127-
}
128-
```
129-
130-
And that's it, you don't need to configure the service manager with this class, creation will happen automatically.
131-
132-
133-
## Cache annotations
134-
135-
This package is built on top of `doctrine/annotation` and `doctrine/cache`.
136-
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/master/lib/Doctrine/Common/Cache) for available implementations offered by doctrine.
137-
138-
Below, we give an example, as defined in our frontend and admin starter applications
139-
```php
140-
return [
141-
'annotations_cache_dir' => __DIR__ . '/../../data/cache/annotations',
142-
'dependencies' => [
143-
'factories' => [
144-
// used by dot-annotated-services to cache annotations
145-
// needs to return a cache instance from Doctrine\Common\Cache
146-
AbstractAnnotatedFactory::CACHE_SERVICE => AnnotationsCacheFactory::class,
147-
]
148-
],
149-
];
150-
```
151-
152-
```php
153-
namespace Frontend\App\Factory;
154-
155-
use Doctrine\Common\Cache\FilesystemCache;
156-
use Psr\Container\ContainerInterface;
157-
158-
class AnnotationsCacheFactory
159-
{
160-
public function __invoke(ContainerInterface $container)
161-
{
162-
//change this to suite your caching needs
163-
return new FilesystemCache($container->get('config')['annotations_cache_dir']);
164-
}
165104
}
166105
```

composer.json

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "dotkernel/dot-annotated-services",
33
"type": "library",
4-
"description": "DotKernel service creation component through laminas-servicemanager and annotations",
4+
"description": "DotKernel dependency injection component using class attributes.",
55
"license": "MIT",
66
"homepage": "https://github.com/dotkernel/dot-annotated-services",
77
"authors": [
@@ -11,23 +11,20 @@
1111
}
1212
],
1313
"keywords": [
14-
"annotations",
15-
"services",
16-
"factories",
14+
"attribute",
1715
"container",
18-
"laminas",
19-
"mezzio",
20-
"service-manager"
16+
"dependency",
17+
"di",
18+
"factory",
19+
"inject",
20+
"service"
2121
],
2222
"require": {
2323
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
24-
"laminas/laminas-servicemanager": "^3.22.1",
25-
"doctrine/annotations": "^1.14.3",
26-
"doctrine/cache": "^1.12.1 || ^2.1.1",
27-
"doctrine/orm" : "^2.17.3"
24+
"doctrine/orm": "^2.0 || ^3.0"
2825
},
2926
"require-dev": {
30-
"phpunit/phpunit": "^10.5.9",
27+
"phpunit/phpunit": "^10.5",
3128
"vimeo/psalm": "^5.20",
3229
"laminas/laminas-coding-standard": "^2.5"
3330
},

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<testsuites>
44
<testsuite name="dot-annotated-services Test Suite">
55
<directory>./test</directory>
6+
<exclude>./test/TestData</exclude>
67
</testsuite>
78
</testsuites>
89
<coverage/>

psalm-baseline.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
3+
<file src="test/Factory/AttributedRepositoryFactoryTest.php">
4+
<MissingTemplateParam>
5+
<code>class ($entityManager, $metadata) extends EntityRepository {</code>
6+
</MissingTemplateParam>
7+
</file>
8+
</files>

psalm.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
88
xmlns="https://getpsalm.org/schema/config"
99
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
10+
errorBaseline="psalm-baseline.xml"
1011
>
1112
<projectFiles>
1213
<directory name="src" />
14+
<directory name="test" />
1315
<ignoreFiles>
1416
<directory name="vendor" />
1517
</ignoreFiles>

src/Annotation/Entity.php

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/Annotation/Inject.php

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Annotation/Service.php

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/Attribute/Entity.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dot\AnnotatedServices\Attribute;
6+
7+
use Attribute;
8+
9+
#[Attribute]
10+
class Entity
11+
{
12+
private string $name;
13+
14+
public function __construct(string $name)
15+
{
16+
$this->name = $name;
17+
}
18+
19+
public function getName(): string
20+
{
21+
return $this->name;
22+
}
23+
}

src/Attribute/Inject.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dot\AnnotatedServices\Attribute;
6+
7+
use Attribute;
8+
9+
#[Attribute]
10+
class Inject
11+
{
12+
protected array $services = [];
13+
14+
public function __construct(string ...$services)
15+
{
16+
$this->services = $services;
17+
}
18+
19+
public function getServices(): array
20+
{
21+
return $this->services;
22+
}
23+
}

0 commit comments

Comments
 (0)