Инъекция прыщей и динамических конструкторов

У меня вопрос по поводу 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 не будет указывать, как различные объекты должны создаваться с помощью intellisensing. Я также немного сомневаюсь, насколько более тестируемым $this->app['something'] даже сделал мой контроллер.

Контроллеры вообще должны быть тестируемыми? Если да, могу ли я рассмотреть Image объект быть объектом значения?

Какие-нибудь мысли?

1 ответ

Прыщ - это контейнер для хранения ценностей или услуг. Приложение запрашивает 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');

  }
}
Другие вопросы по тегам