yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.24k stars 6.91k forks source link

[Enh] Yii::createObject() #15092

Closed lav45 closed 6 years ago

lav45 commented 6 years ago

Invite I need to connect the component

class CDN extends \yii\base\Component
{
    /** @var array */
    public $options;
    /** @var StorageInterface */
    private $storage;

    public function __construct(StorageInterface $storage)
    {
        $this->storage = $storage;
    }
}

class Storage implements StorageInterface
{
    /** @var string */
    public $basePath;
    /** @var TransportInterface */
    private $transport;

    public function __construct(TransportInterface $transport)
    {
        $this->transport = $transport;
    }
}

The first problem that will face is that you cannot pass the required parameters to the constructor when the component description.

return [
    'componenets' => [
        'cdn' => [
            'class' => CDN::class,
            'options' => [],
            'storage' => [
                'class' => Storage::class,
                'basePath' => '/var/data',
                'transport' => Transport::class,
            ],
        ]
    ]
];

To this option is earned, you will implement a recursive nested classes. This functionality is already implemented in the https://github.com/lav45/yii2-flysystem https://github.com/lav45/yii2-flysystem/blob/master/src/MountManager.php#L48

vtvz commented 6 years ago

PR #15061 solves this problem like this:

[
        'cdn' => [
            'class' => CDN::class,
            'options' => [],
            'storage' => Instance::of([
                'class' => Storage::class,
                'basePath' => '/var/data',
                'transport' => Transport::class,
            ]),
        ]
    ]
lav45 commented 6 years ago

@vtvz you have a very interesting project but it won't work if the parameters should be passed in the constructor @see

my implementation allows you to add classes as a component of third-party developers (not yii2 projects) https://github.com/lav45/yii2-flysystem#configuring

return [
    'componenets' => [
        'flysystem' => [
            'class' => 'airani\flysystem\MountManager',
            's3' => [ // https://flysystem.thephpleague.com/adapter/aws-s3-v3/
                'class' => 'League\Flysystem\AwsS3v3\AwsS3Adapter',
                'client' => [
                    'class' => 'Aws\S3\S3Client',
                    'args' => [
                        'credentials' => [
                            'key' => 'chvw2NSdzDV2aKbsJg8ypX',
                            'secret' => 'a4aeZBK5ZRTsDTCqBVFGZpL9MEeBMYjDHS3Cx55YazDD'
                        ],
                        'endpoint' => 'https://hb.bizmrg.com',
                        'version' => 'latest',
                        'region' => 'ru-msk',
                    ]
                ],
                'bucket' => 'public',
            ]
        ]
    ]
]
SilverFire commented 6 years ago

Why not define StorageInterface and TransportInterface in your DI container configuration to make it auto-resolvable?

return [
    'componenets' => [
        'cdn' => [
            'class' => CDN::class,
            'options' => []
        ]
    ],
    'container' => [
        'definitions' => [
            StorageInterface::class => Storage::class,
            TransportInterface::class => AwsS3Transport::class
        ]
    ]
];
lav45 commented 6 years ago

@SilverFire I love the components for the fact that you can reuse the same component with different settings. In this case Aws\S3\S3Client when you connect can use a different username and password.

samdark commented 6 years ago

Seems to be resolved by #15347.

lav45 commented 6 years ago

@samdark больше всего интересовал механизм передачи параметров в конструктор

class Storage implements StorageInterface
{
    /** @var string */
    public $basePath;
    /** @var TransportInterface */
    private $transport;

    public function __construct(TransportInterface $transport)
    {
        $this->transport = $transport;
    }
}
samdark commented 6 years ago

Will be resolved in 2.1 DI component. Won't solve it in 2.0.