-
-
Notifications
You must be signed in to change notification settings - Fork 324
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
Use wildcards in definitions #156
Comments
Hi, thanks for suggesting this. Yes I see what you mean, I have the same "problem" (rather inconvenience). Scanning a directory could be a solution, however there are cons:
However it still is a good feature to implement. Maybe there could be other solutions, for example: $container->set('Application\Service\I*Service', \DI\object('Application\Service\Impl\*Service')); By the way, unrelated, but if you use PHP 5.5 you can simplify your definitions a bit: $container -> set(IAuthorAccountService::class, \DI\object(AuthorAccountService::class)); |
Hi Matthieu and thanks for your response, the solution you propose would be good to declare a directory / namespace scanning. You're right about the limitations, in Java the scanning is performed only one time when the Web server or application server starts so their is no problem after when HTTP requests are performed. Perhaps the "solution" would be to say that in PHP-DI the pattern An application which is designed carefully should never have lots of files in the same directory so this could be a good solution. To limit problems in applications which have a bad design (too much classes in the same directory) we could have a scanner which logs a warning message when the scanning takes too much time. In my opinion having a cache in development like the one you described would be a lot of work but if it works it would be a killing feature. In our application we have clear responsabilities in the source code and it would be easy to configure 4 or 5 scanning configurations to declare nearly 80% of our components in the DI container. I never had a look inside the source code of PHP-DI but after some reflection automatic scanning is perhaps a little trickier than I though first. Each time a class with a Perhaps this would be problematic for performances ?
Yes, sadly we cannot upgrade our code to PHP 5.5 because its to risky for us and we do not have the time to do it for now. But we'll probably use a new PHP version in one of our next projet 😃 |
Please take into consideration the following pattern Using "I" in front is an old type hinting approach. In modern IDEs, when you look at your code you don't want to see IService all over. |
@daniphp What's suggested isn't limited by any naming convention. You just place the $container->set('Foo*', \DI\object('Bar*')); Then |
Ok, that sounds great. |
@daniphp I'm working on the 4.2, which for now contains only #162. I could give it a shot, I think it shouldn't be too hard. I'll give it a try this week. If it's indeed feasible, can you help me up and do the documentation (https://github.com/mnapoli/PHP-DI/blob/master/doc/definition.md)? |
I think a simple example in PHP configuration could be enough, if you On Mon, Jun 2, 2014 at 10:40 AM, Matthieu Napoli notifications@github.com
|
Yep it should be enough! Great I'll let you know. |
Good news, I've managed to implement it (see #165). It allows to use any number of wildcards, so you can match:
but also:
You can also use the wildcard for definitions that are not about classes, e.g.: return [
'foo*' => 'bar', // value definition
'factory*' => DI\factory(function () { /* ... */ }), // factory definition
]; (but I don't think this will be very useful) As you can see it's pretty flexible, I think it covers most use cases. @daniphp & @bgaillard please review and tell me if that's fine with you :) Also @daniphp a PR for the doc is welcome (on the |
Also I forgot to add: I think it hurts a little the performances, because if a class name is not found in the definitions, then it will do a However given definitions are cached, it will not be a problem in production. So I think it's OK. |
What do you think if conflicting definitions would throw an exception. For example: For a class "foor", the clients might expect "baz" but would get "bar". This might be tricky to debug on large configurations. |
Right. Right now the first one to match is considered (except if an exact match is found, in that case the exact match prevails). I would say it's a feature that shouldn't be abused, else there will always be problems I'm afraid. |
👍 Hi @mnapoli & @daniphp, happy to see you've implemented this useful feature. I do not have the time to test it for now but will do it with one of our project when the 4.2 release will be out. I think conflict definitions detection could be a great feature, but if its too complicated or not a priority for now a warning in the docs could prevent problems.
In my opinion few lines about best practices using the wildcards could also be useful in the docs. For example this could be simple advices like (those are general software design best practices in fact) :
I see their are already good advices on the page http://php-di.org/doc/best-practices.html, perhaps this page could be completed. Finally, as @daniphp indicates in a previous post :
All developers are not using the same conventions, perhaps my conventions (principaly taken from Java & Spring) are not yours and needs more discussions. |
Detecting conflict would be (I think) a bit complex and add some overhead. I'm not really against it, but I'll keep it simple for now. It's open for suggestions and pull requests. I'll expand the documentation to add warnings. Thanks |
One last thing: the wildcard currently matches any character. That means that it will match sub-namespaces too, i.e. Do you think that's OK? Of course if you map Do you think it's better to restrict |
Hi @mnapoli,
In my opinion it would be very hard to predict what mappings would be performed by the framework if we allow the Also, because I consider (I hope I'm right) that placing all the business service interfaces and implementations in clear dedicated and flat directories to be a best practice I would prefer to not match the Thanks Matthieu, we're sure the next release will help us produce better code and speed up our devs even more 😃 ! |
Thanks, I agree with you it's best to restrict it so that it doesn't match cross-namespaces, I'll update the code :) |
@mnapoli Great work on this DI container. Very excited to start using it in our project. In your example above, you show: return [
'foo*' => 'bar', // value definition
'factory*' => DI\factory(function () { /* ... */ }), // factory definition
]; Did you provide a way for the factory to get the value matched by *? That would be immensely useful to us |
@ewinslow Sorry for the delay. Thanks :) To answer your question: no, currently there is no way, could you elaborate on why you would need this feature? |
Sure, we have a template system where templates are named based on their The alternative would be to read the entire filesystem and register each On Mon, Jul 28, 2014, 12:46 PM Matthieu Napoli notifications@github.com
|
@ewinslow sorry I completely missed something obvious! $definition = $container->getDefinitionManager()->getDefinition('foo*bar');
echo $definition->getName(); That should give you the name of the definition that matched :) |
Thanks @mnapoli! I will try that and let you know whether it works for me. |
How I map a same interface for various classes?
|
Hi, we are currently integrating PHP-DI 4 in one of our project.
Because its a good practice to have interfaces for our business services we have to define a lot of PHP-DI interface => implementation mappings.
For exemple (this sample can also be configured using a PHP-DI configuration array) :
This is correctly working but at the end we will have a lot of mappings even if we have only one instance of our business services in the DI container.
I think a really good improvement for future releases of PHP-DI would be to have an auto-scanning feature to scan classes with the
@Injectable
annotation. This is exactly what the Spring Framework does.For example in Spring we can do the following to automatically scan classes using the
@Component
annotation and create an instance of each component in the DI container at starting :For this reason interface mappgins is not necessary in Spring, each time a
@Component
annotation is found on a class Spring instanciate this class and injects the associated object inside its DI Container. Then when a@Resource
annotation is found on a class attribute Spring look inside its DI container to find one object which implements the specified interface. If multiple objects implementing the interface are present inside the container Spring fails or forces you to define the name of the object to inject.In PHP-DI it would be great to have something similar, for example :
This would prevent developers to define lots of interface => implementation mappings in PHP-DI.
Any thoughts about this feature ?
Thanks,
Baptiste
The text was updated successfully, but these errors were encountered: