我有一个关于Pimple和动态构造函数注入的问题。
假设我有一个MVC框架,我想做一些像上传图片这样的事情。半依赖注入的方式是这样的:
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对象是一个值对象吗?
有什么想法吗?
发布于 2015-01-21 10:03:37
Pimple是一个用于存储值或服务的容器。应用程序要求Pimple检索一个服务,如会话对象。
如果在整个应用程序中都以精确的清晰度使用image类,
<?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');
}
}https://stackoverflow.com/questions/20309760
复制相似问题