4

我有一个关于 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的属性以及上传的临时图像的属性来保存上传图像的新安全版本。ImageUploader接口JPEGImageSaver以安全地存储上传的图像。

问题是我有三个与控制器紧密耦合的类,我试图避免这种情况的方法是使用 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对象的设置器。

这个问题有一个通用的解决方案吗?我曾考虑将 Pimple 包装在一个解析容器中,让我传入构造函数参数,但问题是我的 IDE 不会指示应如何通过智能感知构造各种对象。$this->app['something']我也有点怀疑我的控制器有多少可测试性。

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

有什么想法吗?

4

1 回答 1

1

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');

  }
}
于 2015-01-21T02:03:36.747 回答