L
L
lilwings2020-02-15 05:06:45
Yii
lilwings, 2020-02-15 05:06:45

Did I do it right on yii2 (Code review)?

controller:

public function actionAdd()
{
    $model = new Info();

    if ( $model->load(Yii::$app->request->post()) ) {
        $model->img_preview = UploadedFile::getInstance($model, 'img_preview');
        $model->img_full = UploadedFile::getInstance($model, 'img_full');

        if ( $model->upload() && $model->save(false)) {
            Yii::$app->session->setFlash('message', 'Данные сохранены!');

            return $this->refresh();
        }

        Yii::$app->session->setFlash('message', 'Не правильные данные!');
    }

    return $this->render('add', compact('model'));
}


Model info:

class Info extends ActiveRecord
{
    public static function tableName()
    {
        return '{{info}}';
    }

    public function rules() {
        return [
            ,
            [['title', 'preview', 'description_seo'], 'filter', 'filter' => 'strip_tags'],
            [['title', 'preview', 'description_seo'], 'trim'],
            [['title', 'preview', 'description_seo'], 'required'],
            [['img_preview', 'img_full'], 'safe'],
            ['description', 'safe'],
        ];
    }

    public function upload() {
        if ($this->validate()) {

            $model = new InfoUpload($this);
            $model->upload();

            return true;
        }

        return false;
    }
}


Model InfoUpload:

class InfoUpload extends Model
{
    public $modelInfo;
    public $img_preview;
    public $img_full;

    public function __construct(&$model)
    {
        $this->modelInfo = $model;
        $this->img_preview = $model->img_preview;
        $this->img_full = $model->img_full;
    }

    public function upload() {
        // Создание директории
        $folderName = $this->generateUniqFileName("web/info");
        FileHelper::createDirectory( Yii::getAlias("@frontend/web/img/info/$folderName") );

        // Создание файла
        $imgPreviewName = $folderName . '/' . $this->generateUniqFileName("web/info/$folderName") . '.' . $this->img_preview->extension;
        $this->img_preview->saveAs( Yii::getAlias("@frontend/web/img/info/$imgPreviewName") );

        // Создание Файла
        $imgFullName = $folderName . '/' . $this->generateUniqFileName("web/info/$folderName") . '.' . $this->img_full->extension;
        $this->img_full->saveAs( Yii::getAlias("@frontend/web/img/info/$imgFullName") );

        // Заполнение главной модели
        $this->fillingInfo(['img_preview' => $imgPreviewName, 'img_full' => $imgFullName,]);
    }

    public function fillingInfo($paths) {
        $this->modelInfo->img_preview = $paths['img_preview'];
        $this->modelInfo->img_full = $paths['img_full'];
    }

    public function generateUniqFileName($path) {
        $name = bin2hex(random_bytes(8));

        if ( file_exists( Yii::getAlias("@frontend/$path/$name") ) ) return $this->generateUniqFileName($path);
        else return $name;
    }
}


I created two models( Thanks for that Dmitry ):
1) Info Model - Responsible for validating data and writing it to the database
2) InfoUpload Model - Responsible for saving files and overwriting values ​​in the main Info model.

The entire Info model is passed to InfoUpload by reference, and when files are written, the model with Info data is updated, and instead of files there is a path to them.

Answer the question

In order to leave comments, you need to log in

[[+comments_count]] answer(s)
M
Maxim, 2020-02-15
@lilwings

1. Why did you place the creation of a directory, the creation of a file in the model? This is the responsibility of some service, but not the model (entity).
2. Downloading files can be moved from the controller to the same service.
3. I don’t really understand why there are two models.
From all this I show you the service for loading and deleting images, although in Symfony, but it is not difficult to make it in Yii. Connect in the controller constructor and work with it.

/**
 * Class FileUploader
 * @author Maxim Vorozhtsov <myks1992@mail.ru>
 */
class FileUploader
{
    /**
     * @var string
     */
    private $basUrl;

    /**
     * FileUploader constructor.
     * @param string $basUrl
     */
    public function __construct(string $basUrl)
    {
        $this->basUrl = $basUrl;
    }

    /**
     * @param UploadedFile $file
     * @return File
     * @throws Exception
     */
    public function upload(UploadedFile $file): File
    {
        $path = $this->generateUrl();
        $name = time() . '.' . $file->getExtension();
        $fileName = $path . '/' . $name;
        FileHelper::createDirectory($path);
        $file->saveAs($fileName);
        return new File($path, $name, $file->size);
    }

    /**
     * @return string
     */
    public function generateUrl(): string
    {
        return $this->basUrl;
    }

    /**
     * @param string $name
     */
    public function remove(?string $name): void
    {
        if (is_file($fileName = $this->generateUrl() . '/' . $name)) {
            unlink($fileName);
        }
    }
}

Store and BaseUrl is assigned in the DI container.
'container' => [
        'singletons' => [
            FileUploader::class => static function () {
                return new Myks92\Vmc\Event\Service\Uploader\FileUploader(Yii::getAlias('@staticRoot/origin/images/events'));
            },
        ],
    ],

Controller:
public function actionUploadPoster($id)
    {
        $event = $this->findModel($id);
        $form = new Poster\Upload\Form();
        $handler = Yii::createObject(Poster\Upload\Handler::class);

        if (!$this->checker->allowEdit($event->getId())) {
            throw new ForbiddenHttpException('Вам не разрешено производить данное действие!');
        }

        if ($form->load(Yii::$app->request->post()) && $form->validate()) {
            $uploader = Yii::createObject(FileUploader::class);
            $uploader->remove($event->getPoster());
            $uploaded = $uploader->upload($form->poster);

            $file = new Poster\Upload\File(
                $uploaded->getPath(),
                $uploaded->getName(),
                $uploaded->getSize()
            );

            $handler->handle(new Poster\Upload\Command($event->getId()->getValue(), $file));

            return $this->redirect(['view', 'id' => $event->getId()->getValue()]);
        }

        return $this->render('upload-poster', [
            'model' => $event,
            'posterForm' => $form,
        ]);
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question