Pimple和动态构造函数注入


Pimple and dynamic constructor injection

我有一个关于Pimple和动态构造函数注入的问题。

假设我有一个MVC框架,我想做一些像图像上传之类的事情。半DI的方法是这样的:

class ImageUploadController
{
    public function upload()
    {
         $targetImage = new Image(1920, 1080, 75, 'jpg', 'save/path');
         $imageSaver = new JPEGImageSaver($targetImage);
         $imageUploader = new ImageUploader($imageSaver);
         $imageUploader->upload('myUploadfield');
    }
}

基本上,Image是一个简单的容器,用于我要创建和保存的图像的属性。JPEGImageSaver利用imagecreatefromjpeg()imagecopyresized()imagejpeg()以及Image对象的属性以及来自上传的临时图像的属性来保存上传图像的新的安全版本。CCD_ 7与CCD_ 8接口以安全地存储上传的图像。

问题是我有三个与控制器紧密耦合的类,我试图避免这种情况的方法是使用Pimple,然后将Pimple传递到控制器中。

class ImageUploadController
{
    public function upload()
    {
         $targetImage = $this->app['Image'];
         $targetImage->setWidth(1920);
         $targetImage->setHeight(1080);
         $targetImage->setQuality(75);
         $targetImage->setExtension('jpg');
         $targetImage->setSavePath('save/path');

         $imageSaver = $this->app['JPEGImageSaver'];
         $imageSaver->setTargetImage($targetImage);
         $imageUploader = $this->app['ImageUploader'];
         $imageUploader->setImageSaver($imageSaver);
         $imageUploader->upload('myUploadField');
    }
}

但正如您所看到的,使用Pimple将依赖项注入到我的控制器中使使用它们比以前更加复杂。主要问题是,我在Pimple中看不到在请求期间为对象设置构造函数值的方法,因此需要为Image对象设置一堆setter。

这个问题有共同的解决方案吗?我曾想过将Pimple封装在一个解析容器中,这样我就可以传递构造函数参数,但问题是我的IDE不会指示应该如何通过智能感知来构建各种对象。我也有点怀疑$this->app['something']在多大程度上提高了我的控制器的可测试性。

控制器甚至需要可测试吗?如果是,我可以认为Image对象是一个值对象吗?

有什么想法吗?

Pimple是一个存储值或服务的容器。应用程序要求Pimple检索会话对象等服务。

如果图像类在整个应用程序中使用,并且具有精确的定义,

<?php
$targetImage = new Image(1920, 1080, 75, 'jpg', 'save/path');

那么你可以要求Pimple存储这个定义。

<?php
// define image service
$container['image'] = function ($c) {
    return new Image(1920, 1080, 75, 'jpg', 'save/path');
};

如果您的应用程序中有不同的图像大小,您可以执行以下操作:

<?php
// define image service
$container['bigImage'] = function ($c) {
    return new Image(1920, 1080, 75, 'jpg', 'save/path');
};
$container['smallImage'] = function ($c) {
    return new Image(200, 200, 75, 'jpg', 'save/path');
};

您可以更进一步,存储Image类的参数并重复使用它们。

<?php
$container['imageParams'] = [
   'width' => 1920,
   'height' => 1080,
   'type' => 'jpg',
   'quality' => 75
];
// define image service
$container['image'] = function ($c) {
    $image = $c['imageParams'];
    return new Image($image['width'],
                     $image['height'],
                     $image['quality'],
                     $image['type'],
                     'save/path'
    );
};

目前在Pimple,您无法在检索服务时传递参数:

<?php
$this->app['image'](1920, 1080, 75, 'jpg', 'save/path');

您将需要扩展Pimple来实现此功能。

但是,您可以在控制器类中创建一个工厂方法,该方法将修改存储在Pimple中的图像参数,然后调用图像服务来创建具有特定参数的图像对象,然后将存储的参数恢复为原始值。

<?php
class ImageUploadController {
  protected function imageFactory($width, $height, $type, $quality) {
     // Store original parameters
     $origin = $this->app['imageParams'];
     // Override the original parameters
     $this->app['imageParams']['width'] = $width;
     $this->app['imageParams']['height'] = $height;
     $this->app['imageParams']['quality'] = $quality;
     $this->app['imageParams']['type'] = $type;
     // Get image class
     $image = $this->app['image'];
     // Rest image parameters
     $this->app['imageParams'] = $origin;
     return $image;
  }
  public function upload()
  {
     $targetImage = $this->imageFactory(1920, 1080, 75, 'jpg');
  }
}