定制 besnovatyj/yii2-cms-upload 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

besnovatyj/yii2-cms-upload

Composer 安装命令:

composer require besnovatyj/yii2-cms-upload

包简介

Функционал загрузок для Yii2 CMS

README 文档

README

Обзор

Переработанная система загрузки файлов и изображений для Yii2 ActiveRecord. Один behavior для файлов и изображений. Чёткое разделение ответственностей.

Структура

upload/
├── UploadBehavior.php          — единый behavior, lifecycle-хуки модели
├── PathResolver.php            — резолвинг шаблонов путей
├── NameGenerator.php           — генерация и санитизация имён файлов
├── ThumbnailProfile.php        — value object профиля превью
├── ThumbnailMode.php           — enum режимов превью (crop/resize)
├── ThumbnailGenerator.php      — генерация превью изображений
├── FileUploadException.php     — исключение загрузки
├── UrlDownloader.php           — скачивание файлов по URL
├── DownloadResult.php          — value object результата скачивания
└── Storage/
    ├── StorageInterface.php    — контракт хранилища
    ├── StorageException.php    — исключение хранилища
    └── LocalStorage.php        — локальная файловая система

Интеграция в проект

1. Регистрация компонента хранилища

Через DIC, смотри \Besnovatyj\Upload\Bootstrap

2. Обновление модели Profile

Было:

use common\components\upload\behaviors\ImageUploadBehavior;

public function behaviors(): array
{
    return [
        [
            'class' => ImageUploadBehavior::class,
            'attribute' => 'photo',
            'filePath' => '@static/origin/users/[[attribute_user_id]]/[[id]].[[extension]]',
            'fileUrl' => '@staticHostName/origin/users/[[attribute_user_id]]/[[id]].[[extension]]',
            'thumbPath' => '@static/cache/users/[[attribute_user_id]]/[[profile]]_[[id]].[[extension]]',
            'thumbUrl' => '@staticHostName/cache/users/[[attribute_user_id]]/[[profile]]_[[id]].[[extension]]',
            'thumbs' => [
                'admin' => ['width' => 100, 'height' => 70],
                'thumb' => ['width' => 370, 'height' => 370],
            ],
        ],
        ...parent::behaviors(),
    ];
}

Стало:

use Besnovatyj\Upload\heap\UploadBehavior;
use Besnovatyj\Upload\heap\ThumbnailProfile;

public function behaviors(): array
{
    return [
        'photoUpload' => [
            'class' => UploadBehavior::class,
            'attribute' => 'photo',
            'pathTemplate' => 'origin/users/{attr.user_id}/{pk}.{extension}',
            'thumbnails' => [
                new ThumbnailProfile('admin', width: 100, height: 70),
                new ThumbnailProfile('thumb', width: 370, height: 370),
            ],
            'thumbPathTemplate' => 'cache/users/{attr.user_id}/{profile}_{pk}.{extension}',
        ],
        ...parent::behaviors(),
    ];
}

3. Обновление view-файлов и сервисов

Методы получения URL:

// Было:
$model->getImageFileUrl('photo');
$model->getThumbFileUrl('photo', 'admin');
$model->getUploadedFileUrl('photo');
$model->getUploadedFilePath('photo');

// Стало:
$model->getUploadUrl('photo');
$model->getThumbUrl('photo', 'admin');
$model->getUploadPath('photo');
$model->getThumbPath('photo', 'admin');

Все методы поддерживают fallback URL:

$model->getUploadUrl('photo', '/images/no-photo.png');
$model->getThumbUrl('photo', 'admin', '/images/no-photo-sm.png');

4. Удаление старых файлов

После миграции удалить:

  • app/common/components/upload/behaviors/FileUploadBehavior.php
  • app/common/components/upload/behaviors/ImageUploadBehavior.php
  • app/common/components/upload/behaviors/FileUploadException.php
  • app/common/components/upload/behaviors/TODO.MD
  • app/common/components/upload/behaviors/ (директория)
  • app/common/components/upload/UploadFromUrl.php
  • app/common/components/upload/UploadFileFromUrl.php

5. Поиск всех использований в проекте

Найти и обновить все файлы, ссылающиеся на старые классы:

grep -r "common\\\\components\\\\upload\\\\behaviors" app/ --include="*.php"
grep -r "ImageUploadBehavior\|FileUploadBehavior" app/ --include="*.php"
grep -r "getImageFileUrl\|getThumbFileUrl\|getUploadedFileUrl\|getUploadedFilePath" app/ --include="*.php"

Шаблоны путей

Пути — относительные, без Yii-алиасов. Хранилище само добавляет basePath и baseUrl.

Плейсхолдеры

Плейсхолдер Описание Пример значения
{pk} Primary key модели 42
{model} Имя класса (lcfirst) profile
{attribute} Имя атрибута photo
{extension} Расширение файла jpg
{filename} Имя без расширения my-photo
{basename} Полное имя файла my-photo.jpg
{profile} Профиль превью admin
{attr.xxx} Значение атрибута модели {attr.user_id}5
{md5.xxx} MD5 от атрибута модели {md5.email}ab12...

Примеры

// Файл документа
'pathTemplate' => 'documents/{attr.user_id}/{pk}.{extension}'
// → documents/5/42.pdf

// Изображение с превью
'pathTemplate' => 'origin/gallery/{attr.gallery_id}/{pk}.{extension}'
'thumbPathTemplate' => 'cache/gallery/{attr.gallery_id}/{profile}_{pk}.{extension}'
// → origin/gallery/10/42.jpg
// → cache/gallery/10/admin_42.jpg

Примеры конфигураций

Простая загрузка файла (без превью)

[
    'class' => UploadBehavior::class,
    'attribute' => 'document',
    'pathTemplate' => 'documents/{attr.user_id}/{pk}.{extension}',
]

Изображение с превью

use Besnovatyj\Upload\heap\ThumbnailProfile;
use Besnovatyj\Upload\heap\ThumbnailMode;

[
    'class' => UploadBehavior::class,
    'attribute' => 'photo',
    'pathTemplate' => 'origin/users/{attr.user_id}/{pk}.{extension}',
    'generateName' => true, // уникальные имена
    'thumbnails' => [
        new ThumbnailProfile('small', width: 100, height: 100, mode: ThumbnailMode::Crop),
        new ThumbnailProfile('medium', width: 400, height: 300),
        new ThumbnailProfile('large', width: 800, height: 600, quality: 90),
    ],
    'thumbPathTemplate' => 'cache/users/{attr.user_id}/{profile}_{pk}.{extension}',
]

Превью в webp/avif (параметр format)

Формат превью задаётся per-профильно и не зависит от формата оригинала:

'thumbnails' => [
    // формат оригинала (как раньше)
    new ThumbnailProfile('admin', width: 100, height: 70),
    // современный формат отдачи: энкодер + {extension} в пути превью станут webp
    new ThumbnailProfile('thumb', width: 370, height: 370, format: 'webp'),
    new ThumbnailProfile('hero', width: 1600, height: 900, format: 'avif', quality: 60),
],

Принципы:

  • Оригинал не перекодируетсяformat касается только превью (оригинал остаётся источником для регенерации и скачивания).
  • format определяет энкодер imagine/Imagick и подставляется в {extension} шаблона thumbPathTemplategetThumbUrl() автоматически вернёт URL с новым расширением (cache/users/5/thumb_1.webp).
  • Поддерживаемые значения зависят от сборки Imagick: проверить — php -r "print_r(Imagick::queryFormats('WEBP')); print_r(Imagick::queryFormats('AVIF'));".
  • null (дефолт) — прежнее поведение: формат оригинала.
  • Рекомендация: webp — безопасный дефолт для превью (поддержка браузерами ~98%); avif — точечно для тяжёлых изображений (энкодинг заметно дороже, поддержка ~95%).

Кастомная генерация имени

[
    'class' => UploadBehavior::class,
    'attribute' => 'avatar',
    'pathTemplate' => 'avatars/{pk}.{extension}',
    'generateName' => fn(\yii\web\UploadedFile $file) => 'avatar_' . time(),
    'deleteOnEmpty' => true, // удалять файл если атрибут очищен
]

Загрузка файла по URL

use Besnovatyj\Upload\heap\UrlDownloader;

$downloader = new UrlDownloader(timeout: 60);
$result = $downloader->download(
    url: 'https://example.com/photo.jpg',
    allowedExtensions: ['jpg', 'png', 'webp'],
    maxSize: 5 * 1024 * 1024, // 5 MB
);

// Использование результата в модели
$model->photo = /* создать UploadedFile из $result->tempPath */;
$model->save();
$result->cleanup(); // удалить временный файл

Разница со старой системой

Аспект Было Стало
Классы behavior 2 (наследование) 1 (final, без наследования)
Файловые операции Разбросаны по behavior-ам Изолированы в LocalStorage
Резолвинг путей 30-строчный regex callback PathResolver с strtr()
Конфигурация превью Сырые массивы ThumbnailProfile (typed VO)
Формат превью Только формат оригинала Per-профильный format (webp/avif/…)
Режим превью Магическая строка 'thumbsType' ThumbnailMode enum
Драйвер изображений Хардкод IMAGICK каждый вызов Настраивается в конструкторе
Обработка ошибок превью Нет (crash) try/catch на каждый профиль
Скачивание по URL 2 дублирующихся класса 1 класс UrlDownloader
Пути в модели @static/..., @staticHostName/... Относительные, storage добавляет базу
Конфиг в модели filePath + fileUrl + thumbPath + thumbUrl pathTemplate + thumbPathTemplate

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-06

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固