Skip to content

Commit

Permalink
Fix #22: Add docs, minor cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
samdark committed Nov 17, 2021
1 parent 348a21c commit 2606b16
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 35 deletions.
77 changes: 58 additions & 19 deletions README.md
Expand Up @@ -6,8 +6,8 @@
<br>
</p>

This package provides abstract object factory allowing create objects by given definition
with dependencies resolved by a PSR-11 container.
This package provides abstract object factory allowing to create objects by given definition
with dependencies resolved by a [PSR-11](https://www.php-fig.org/psr/psr-11/) container.

[![Latest Stable Version](https://poser.pugx.org/yiisoft/factory/v/stable.png)](https://packagist.org/packages/yiisoft/factory)
[![Total Downloads](https://poser.pugx.org/yiisoft/factory/downloads.png)](https://packagist.org/packages/yiisoft/factory)
Expand All @@ -18,23 +18,62 @@ with dependencies resolved by a PSR-11 container.
[![static analysis](https://github.com/yiisoft/factory/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/factory/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/factory/coverage.svg)](https://shepherd.dev/github/yiisoft/factory)

## Installation
## Requirements

- PHP 7.4 or higher.

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
## Installation

Either run
The package could be installed with [composer](http://getcomposer.org/download/):

```shell
composer require yiisoft/definitions --prefer-dist
```
php composer.phar require --prefer-dist yiisoft/factory

## General usage

The factory is useful if you need to create objects using [definition syntax](https://github.com/yiisoft/definitions)
and/or want to configure defaults for objects created.

```php
$container = new PSR11DependencyInjectionContainer();
$factoryConfig = [
EngineInterface::class => [
'class' => EngineMarkOne::class,
'__construct()' => [
'power' => 42,
],
]
];

$factory = new Factory($container, $factoryConfig);

$one = $factory->create(EngineInterface::class);
$two = $factory->create(EngineInterface::class, [
'__construct()' => [
'power' => 146,
],
]);
```

or add
In the code above we define factory config specifying that when we need `EngineInterface`, an instance of `EngineMarkOne`
will be created with `power` constructor argument equals to 42. We also specify that all the dependencies requested by
the object created should be resolved by `PSR11DependencyInjectionContainer`.

```
"yiisoft/factory": "^3.0@dev"
First call to `create()` uses default configuration of `EngineInterface` as is. Second call specifies custom
configuration for `power` constructor argument. In this case, configuration specified is merged with default
configuration overriding its keys when the key name is the same.

### Tuning for production

By default, the factory validates definitions right when they are set. In production environment, it makes sense not
turn it off by passing `false` as a third constructor argument:

```php
$factory = new Factory($container, $factoryConfig, false);
```

to the require section of your `composer.json`.
## Testing

### Unit testing

Expand All @@ -60,21 +99,21 @@ The code is statically analyzed with [Psalm](https://psalm.dev/). To run static
./vendor/bin/psalm
```

### Support the project
## License

The Yii Factory is free software. It is released under the terms of the BSD License.
Please see [`LICENSE`](./LICENSE.md) for more information.

Maintained by [Yii Software](https://www.yiiframework.com/).

## Support the project

[![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft)

### Follow updates
## Follow updates

[![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/)
[![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter&logoColor=1DA1F2&labelColor=555555?style=flat)](https://twitter.com/yiiframework)
[![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en)
[![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk)
[![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack)

## License

The Yii Factory is free software. It is released under the terms of the BSD License.
Please see [`LICENSE`](./LICENSE.md) for more information.

Maintained by [Yii Software](https://www.yiiframework.com/).
10 changes: 9 additions & 1 deletion src/Factory.php
Expand Up @@ -25,18 +25,26 @@
*/
final class Factory
{
/**
* @var ContainerInterface|null Container to use for resolving dependencies. When null, only definitions
* are used.
*/
private ?ContainerInterface $container;
private FactoryContainer $factoryContainer;

/**
* @var bool $validate Validate definitions when set
* @var bool $validate If definitions should be validated when set.
*/
private bool $validate;

/**
* Factory constructor.
*
* @param ContainerInterface|null $container Container to use for resolving dependencies. When null, only definitions
* are used.
* @param array $definitions Definitions to create objects with.
* @psalm-param array<string, mixed> $definitions
* @param bool $validate If definitions should be validated when set.
*
* @throws InvalidConfigException
*/
Expand Down
40 changes: 26 additions & 14 deletions src/FactoryContainer.php
Expand Up @@ -20,44 +20,51 @@
use function is_object;

/**
* Factory's primary container.
*
* @internal
*/
final class FactoryContainer implements ContainerInterface
{
/**
* @var ContainerInterface|null Container to use for resolving dependencies. When null, only definitions
* are used.
*/
private ?ContainerInterface $container;

/**
* @var mixed[] Definitions
* @var array Definitions to create objects with.
* @psalm-var array<string, mixed>
*/
private array $definitions = [];

/**
* @var DefinitionInterface[] object definitions indexed by their types
* @var DefinitionInterface[] Object created from definitions indexed by their types.
* @psalm-var array<string, DefinitionInterface>
*/
private array $definitionInstances = [];

/**
* @var array used to collect IDs instantiated during build to detect circular references
* @var array Used to collect IDs instantiated during build to detect circular references.
*
* @psalm-var array<string,1>
*/
private array $creatingIds = [];

/**
* @param ContainerInterface|null $container Container to use for resolving dependencies. When null, only definitions
* are used.
*/
public function __construct(?ContainerInterface $container)
{
$this->container = $container;
}

/**
* @param string $id
*
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
* @inheritDoc
*
* @param string $id
* @return mixed|object
*
* @psalm-suppress InvalidThrow
*/
public function get($id)
Expand All @@ -69,17 +76,13 @@ public function get($id)
throw new NotInstantiableClassException($id);
}

/**
* @param string $id
*
* @return bool
*/
public function has($id): bool
{
return isset($this->definitions[$id]) || ($this->container !== null && $this->container->has($id)) || class_exists($id);
}

/**
* Get definition by identifier provided.
* @throws InvalidConfigException
*/
public function getDefinition(string $id): DefinitionInterface
Expand All @@ -99,6 +102,12 @@ public function getDefinition(string $id): DefinitionInterface
return $this->definitionInstances[$id];
}

/**
* Check if there is a definition with a given identifier.
*
* @param string $id Identifier to look for.
* @return bool If there is a definition with a given identifier.
*/
public function hasDefinition(string $id): bool
{
if (isset($this->definitions[$id])) {
Expand All @@ -114,7 +123,10 @@ public function hasDefinition(string $id): bool
}

/**
* @param mixed $definition
* Set definition for a given identifier.
*
* @param string $id Identifier to set definition for.
* @param mixed $definition Definition to set.
*/
public function setDefinition(string $id, $definition): void
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/FactoryTest.php
Expand Up @@ -116,7 +116,7 @@ public function testObjectIsCloned(): void
}

/**
* If class name is used as ID, factory must try create given class.
* If class name is used as ID, factory must try to create given class.
*/
public function testCreateClassNotDefinedInConfig(): void
{
Expand Down

0 comments on commit 2606b16

Please sign in to comment.