【问题标题】:How do inject array of implementations into constructor in PHP如何将实现数组注入PHP中的构造函数
【发布时间】:2020-02-04 01:39:42
【问题描述】:

如何通过构造函数将实现数组注入到类中。我正在分享 C# 的链接。我想在 php 中实现同样的效果。

如何在 php 中实现相同的功能。

public interface IFoo { }
public class FooA : IFoo {}
public class FooB : IFoo {}

public class Bar
{
    //array injected will contain [ FooA, FooB ] 
    public Bar(IFoo[] foos) { }
}

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<IFoo>().To<FooA>();
        Bind<IFoo>().To<FooB>();
        //etc..
    }
}

https://stackoverflow.com/a/13383476/1844634

提前致谢。

【问题讨论】:

    标签: php laravel inversion-of-control lumen laravel-ioc


    【解决方案1】:

    由于运行时性能困难,PHP 不支持泛型。 因此,无法通过承包商的定义来解释您期望所有接口。所以你必须手动配置 DI 容器。明确告诉你的类需要所有支持某种接口的类。

    用于配置的 Laravel 使用 ServiceProvider 进行各种配置: 在\App\Providers\AppServiceProvider 类中,您可以配置类的创建。

    
        public function register(): void
        {
            // to configure implementation for an interface or abstract class
            // you can only configure one implementation for interface
            $this->app->bind(\App\IFoo::class, \App\FooA::class);
    
            // or 'tag' several implementation for one string tag.
            $this->app->tag([\App\FooA::class, \App\FooB::class], \App\IFoo::class);
    
            $this->app->bind(\App\Bar::class, function(\Illuminate\Contracts\Foundation\Application $container){
                // get all tagged implementations
                $foos = $container->tagged(\App\IFoo::class);
    
                return new \App\Bar($foos);
            });
        }
    
    

    【讨论】:

    • 我该怎么做?有参考吗?
    • @user1844634 确定。我将描述如何配置 DI 容器。
    • 这里不需要接口吗?我们直接处理具体的类。如何将接口绑定到具体类?
    • @user1844634 这很像我的答案。
    • 请以我在问题中提到的上述示例并写下您的答案,这将对我有很大帮助。提前致谢。
    【解决方案2】:

    您可能需要使用Tagging。例如, 也许您正在构建一个接收数组的报告聚合器 许多不同的报告接口实现。注册后 报告实现,您可以使用标签为其分配标签 方法:

    $this->app->bind('App\Reports\MemoryReportInterface', 'App\Reports\MemoryReportImplementation');       
    $this->app->bind('App\Reports\SpeedReportInterface', 'App\Reports\SpeedReportImplementation');  
    
    $this->app->tag(['App\Reports\MemoryReportInterface', 'App\Reports\MemoryReportInterface'], 'reports'); 
    

    标记服务后,您可以轻松解决所有问题 通过标记方法:

    $this->app->bind('ReportAggregator', function ($app) {
        return new ReportAggregator($app->tagged('reports'));
    });
    

    用法

    <?php 
    
    namespace ...;
    
    /**
     * 
     */
    class ReportAggregator
    {
        private $reports;
    
        function __construct($reports)
        {
            $this->reports = $reports;
        }
    
        public function getReports() {
            return $this->reports;
        }
        //...
    }
    

    【讨论】:

    • 我希望我的类依赖于抽象。而不是具体的实现。我怎么能在这里实现?
    • 如果我没记错应该是同一个界面。由两个具体类实现的相同接口。它应该是 MemoryReportInterface 或 SpeedReportInterface
    • 请查看我在问题中提到的示例并更新答案。提前致谢。
    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多