Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: decorators #110

Closed
xepozz opened this issue Feb 19, 2020 · 4 comments
Closed

Feature: decorators #110

xepozz opened this issue Feb 19, 2020 · 4 comments
Labels
type:feature New feature

Comments

@xepozz
Copy link
Member

xepozz commented Feb 19, 2020

Would be nice allow to decorate already existing services in container.
I see at least 2 variants of usage:

  1. Decorating already existing service that exist in another container (applied only to CompositeContainer)
    // config/common.php
return [
  // ...
  LoggerInterface::class => function() use ($compositeContainer) {
    return new LoggerDecorator($compositeContainer->get(LoggerInterface::class));
  }
  // ...
];

At now it parsed as circle dependency, but we can modernize this syntax. At now it doesn't matter.
2. Decorating already existing services in current container
// config/common.php

return [
  // ...
  LoggerInterface::class => /* ... */,
  
  LoggerDecorator::class => [
      'decorated' => LoggerInterface::class
  ];
  // ...
];

or
// config/common.php

return [
  // ...
  LoggerInterface::class => /* ... */,
  // ...
];

// config/common.dev.php

return [
  // ...
  LoggerInterface::class => function ($container) {
      return new LoggerDecorator($container->get(LoggerInterface::class));
  }
  // ...
];

What is the expected result?

In all cases $container->get(LoggerInterface::class) should return LoggerDecorator

What do you get instead?

In the first case we have CircularReferenceException. In the second case we have LoggerInterface implementation that passed via /* ... */ or CircularReferenceException`.

Additional info

I think we need to think all future features for another cases (I'm not about decorators only).

@xepozz xepozz added the type:feature New feature label Feb 19, 2020
@xepozz
Copy link
Member Author

xepozz commented Feb 19, 2020

I made syntax examples.

LoggerInterface::class => (new ContainerBuilder())
  ->callback(fn () => new Logger())
  ->decorate(fn ($container, $logger) => new LoggerDecorator($logger));
LoggerInterface::class => (new ContainerBuilder())
  ->callback(fn () => new Logger())
  ->decorate(LoggerDecorator::class),
LoggerDecorator::class => fn ($container) => new LoggerDecorator($container->get(LoggerInterface::class)),
$definitions = [
  LoggerInterface::class => fn () => new Logger(),
  LoggerDecorator::class => fn ($container) => new LoggerDecorator($container->get(LoggerInterface::class)),
];
$containerBuilder
  ->decorate(LoggerInterface::class, LoggerDecorator::class)
  ->decorate(ContainerInterface::class, ContainerDecorator::class);

@viktorprogger
Copy link
Contributor

#10

@viktorprogger
Copy link
Contributor

viktorprogger commented Feb 19, 2020

Why do decorators better than nested/contextual containers?

@xepozz
Copy link
Member Author

xepozz commented Feb 19, 2020

Using decorators we can to substitude any dependencies from PSR container, not only Yii container.
It looks more cleaner and flexible.
Nested container is a part of way to use decorators.

Do you have examples with contextual container that solve this problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature New feature
Projects
None yet
Development

No branches or pull requests

2 participants