I have a question regarding Pimple and dynamic constructor injection.
Say I have an MVC framework and I want to do something like image uploading. The semi-DI way of doing it would be like this:
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');
}
}
Basically Image
is a simple container for the properties of the image I want to create and save. JPEGImageSaver
makes use of imagecreatefromjpeg()
, imagecopyresized()
, and imagejpeg()
and the properties of the Image
object as well as the properties from the uploaded temp image to save a new safe version of the uploaded image. ImageUploader
interfaces with the JPEGImageSaver
to safely store the uploaded image.
The problem is I have three tightly coupled classes with the controller, and the way I've attempted to avoid that is by using Pimple, and then passing Pimple into the controller.
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');
}
}
But as you can see, using Pimple to inject dependencies into my controller has made using them MORE complicated than before. The main issue is that I don't see a way in Pimple to set constructor values for objects during request, thus needing a bunch of setters for the Image
object.
Is there a common solution to this problem? I've thought about wrapping Pimple in a resolving container that lets me pass in constructor arguments, but the problem with that is my IDE won't indicate how the various objects should be constructed through intellisensing. I'm also a bit dubious about how much more testable $this->app['something']
has even made my controller.
Do controllers even need to be testable? If so, can I consider the Image
object to be a value object?
Any thoughts?
Pimple is a container to store values or services. The application asks Pimple to retrieve a service such as session object.
If the image class is used throughout your application with exact definition,
then you can ask Pimple to store this definition.
If you have different image sizes in your application, you can do something like:
You can go even further and store the parameters of Image class and re-use them.
Currently in Pimple you can't pass parameters while retrieving a service:
You will need to extend Pimple to implement this feature.
However, you can create a factory method in your controller class that will modify the image parameters stored in Pimple, then call the image service to create the image object with your specific parameters, and then revert the stored parameters to the original values.