Генерация изображений в Wepps Platform: автоматический ресайз и кэширование

Класс Images — это утилита для динамической обработки изображений в Wepps Platform. Он автоматически создает уменьшенные версии изображений в заданных размерах, кэширует результаты и отдает их с оптимальными HTTP-заголовками.

22.01.2026

Введение

Класс Images — это утилита для динамической обработки изображений в Wepps Platform. Он автоматически создает уменьшенные версии изображений в заданных размерах, кэширует результаты и отдает их с оптимальными HTTP-заголовками. Система работает по принципу "on-demand" — изображение обрабатывается только при первом запросе, после чего сохраняется в файловую систему для быстрой отдачи.

Зачем использовать Images?

Проблемы, которые решает утилита

  1. Ручной ресайз изображений - не нужно вручную создавать превью и миниатюры для загруженных файлов
  2. Производительность - автоматическая генерация оптимизированных версий изображений нужных размеров
  3. Кэширование - готовые изображения сохраняются в файловой системе и отдаются с long-term кэшированием
  4. Унификация размеров - все изображения одного типа имеют одинаковые размеры на сайте

Когда использовать

  • Отображение товаров в каталоге (миниатюры, карточки товара)
  • Галереи и слайдеры с изображениями разных размеров
  • Превью новостей и статей
  • Любые случаи, когда нужны изображения фиксированных размеров
  • Когда важна производительность и кэширование статики

Основные концепции

URL-схема генерации

Изображения генерируются через специальный URL-паттерн:

/pic/{PREFIX}/{PATH_TO_FILE}

Где:

  • {PREFIX} — префикс размера (lists, preview, medium, slide и т.д.)
  • {PATH_TO_FILE} — путь к исходному файлу из таблицы s_Files

Пример:

<img src="/pic/medium/lists/Products/image.jpg" alt="Товар">

Принцип работы

  1. При первом запросе /pic/medium/lists/Products/image.jpg:

    • Apache перенаправляет запрос на Images/Request.php через mod_rewrite
    • Класс Images загружает исходный файл из файловой системы
    • Выполняется ресайз/кроп до нужных размеров
    • Изображение сохраняется в pic/medium/lists/Products/image.jpg
    • Изображение отдается браузеру с заголовками кэширования
  2. При повторных запросах:

    • Apache находит готовый файл в pic/medium/ и отдает его напрямую
    • PHP-скрипт не вызывается — максимальная производительность

Доступные размеры изображений

Предустановленные префиксы

Префикс Размер (ширина × высота) Режим Описание
lists 80 × 80 resize Миниатюры для списков
preview 320 × 240 crop Превью изображений
medium 640 × 480 crop Средний размер (горизонтальный)
mediumv 480 × 600 crop Средний размер (вертикальный)
mediumsq 600 × 600 resize Средний размер (квадратный)
full 1280 (по большей стороне) resize Полноразмерное изображение
slide 1280 (по большей стороне) resize Для слайдеров (десктоп)
slidem 600 (по большей стороне) resize Для слайдеров (мобильные)
a4 500 × 705 crop Пропорции A4 (вертикальный формат)

Режимы обработки

Resize (proportional) — изображение вписывается в заданный прямоугольник с сохранением пропорций:

Исходное: 1920×1080 → Medium (640×480)
Результат: 640×360 (с белыми полями по вертикали)

Crop (fill) — изображение заполняет весь прямоугольник, обрезая лишнее:

Исходное: 1920×1080 → Preview (320×240)
Результат: 320×240 (центральная часть, края обрезаны)

Использование в шаблонах

Базовое использование

{* Миниатюра в списке товаров *}
<img src="/pic/lists{$item.Image_FileUrl}" alt="{$item.Name}">

{* Средний размер в карточке товара *}
<img src="/pic/medium{$product.Images.0}" alt="{$product.Name}">

{* Вертикальный формат для новостей *}
<img src="/pic/mediumv{$news.Images.0}" alt="{$news.Title}">

{* Полноразмерное изображение *}
<a href="/pic/full{$gallery.Image_FileUrl}">
    <img src="/pic/preview{$gallery.Image_FileUrl}" alt="Просмотр">
</a>

Примеры с проверкой наличия

{* С fallback на placeholder *}
<img src="{if $item.Images.0}/pic/medium{$item.Images.0}{else}/ext/Template/files/noimage.png{/if}" 
     alt="{$item.Name}">

{* Несколько изображений *}
{foreach $product.Images as $image}
    <div class="gallery-item">
        <a href="/pic/full{$image}" data-lightbox="product">
            <img src="/pic/preview{$image}" alt="">
        </a>
    </div>
{/foreach}

{* Адаптивные изображения для слайдера *}
<picture>
    <source media="(max-width: 768px)" srcset="/pic/slidem{$slide.ImageMobile_FileUrl}">
    <img src="/pic/slide{$slide.Image_FileUrl}" alt="{$slide.Title}">
</picture>

Конфигурация .htaccess

Правило перенаправления в корне проекта

# Если файл не существует в файловой системе
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

# Перенаправить на генератор изображений
RewriteRule ^pic/([a-zA-Z0-9]+)/(.+)$ packages/WeppsExtensions/Addons/Images/Request.php?fileUrl=$2&pref=$1 [L]

Как это работает:

  1. Запрос /pic/medium/lists/Products/test.jpg
  2. Apache проверяет, существует ли файл pic/medium/lists/Products/test.jpg
  3. Если нет — перенаправляет на Images/Request.php?fileUrl=lists/Products/test.jpg&pref=medium
  4. PHP генерирует изображение и сохраняет его в pic/medium/lists/Products/test.jpg
  5. При следующем запросе файл уже существует и отдается напрямую

Заголовки кэширования

<FilesMatch ".(?i:flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf|woff)$">
    Header set Cache-Control "max-age=2592000"
</FilesMatch>

Статические файлы (включая изображения) кэшируются на 30 дней.

Практические примеры

1. Список товаров с миниатюрами

{* Products/Products.tpl *}
<div class="products-grid">
    {foreach $products as $item}
        <div class="product-card">
            <a href="{$item.Url}">
                <img src="/pic/lists{$item.Images.0}" 
                     alt="{$item.Name}" 
                     loading="lazy">
            </a>
            <h3>{$item.Name}</h3>
            <p class="price">{$item.Price} ₽</p>
        </div>
    {/foreach}
</div>

2. Карточка товара с зумом

{* Products/ProductsItem.tpl *}
<div class="product-gallery">
    {* Основное изображение *}
    <div class="main-image">
        <a href="/pic/full{$product.Images.0}" data-lightbox="product">
            <img src="/pic/medium{$product.Images.0}" 
                 alt="{$product.Name}"
                 id="productMainImage">
        </a>
    </div>

    {* Миниатюры для переключения *}
    <div class="thumbnails">
        {foreach $product.Images as $index => $image}
            <img src="/pic/lists{$image}" 
                 alt="" 
                 class="thumbnail {if $index == 0}active{/if}"
                 onclick="changeMainImage('/pic/medium{$image}', '/pic/full{$image}')">
        {/foreach}
    </div>
</div>

<script>
function changeMainImage(mediumSrc, fullSrc) {
    const mainImg = document.getElementById('productMainImage');
    mainImg.src = mediumSrc;
    mainImg.parentElement.href = fullSrc;
}
</script>

3. Адаптивный слайдер

{* Template/Swiper/Swiper.tpl *}
<div class="swiper">
    <div class="swiper-wrapper">
        {foreach $slides as $item}
            <div class="swiper-slide">
                <picture>
                    {* Мобильная версия *}
                    <source media="(max-width: 768px)" 
                            srcset="/pic/slidem{$item.ImageMobile_FileUrl}">

                    {* Десктопная версия *}
                    <img src="/pic/slide{$item.Image_FileUrl}" 
                         alt="{$item.Title}"
                         class="slide-image">
                </picture>

                <div class="slide-content">
                    <h2>{$item.Title}</h2>
                    <p>{$item.Description}</p>
                </div>
            </div>
        {/foreach}
    </div>
</div>

4. Галерея с lazy loading

{* Gallery/Gallery.tpl *}
<div class="gallery-grid">
    {foreach $gallery as $item}
        <div class="gallery-item">
            <a href="/pic/full{$item.Image_FileUrl}" 
               data-lightbox="gallery" 
               data-title="{$item.Name}">
                <img src="/pic/preview{$item.Image_FileUrl}" 
                     alt="{$item.Name}"
                     loading="lazy"
                     class="gallery-thumbnail">
            </a>
        </div>
    {/foreach}
</div>

5. Список новостей с превью

{* News/News.tpl *}
<div class="news-list">
    {foreach $news as $item}
        <article class="news-item">
            <div class="news-image">
                <a href="{$item.Url}">
                    <img src="/pic/mediumv{$item.Images.0}" 
                         alt="{$item.Title}">
                </a>
            </div>
            <div class="news-content">
                <time>{$item.DateCreate|date_format:"%d.%m.%Y"}</time>
                <h3><a href="{$item.Url}">{$item.Title}</a></h3>
                <p>{$item.Anons}</p>
            </div>
        </article>
    {/foreach}
</div>

6. Корзина с миниатюрами

{* Cart/CartDefault.tpl *}
<div class="cart-items">
    {foreach $cartItems as $item}
        <div class="cart-item">
            <div class="cart-image">
                <img src="/pic/lists{$item.image}" 
                     alt="{$item.name}">
            </div>
            <div class="cart-info">
                <h4>{$item.name}</h4>
                <p class="price">{$item.price} ₽</p>
                <input type="number" value="{$item.quantity}" min="1">
            </div>
        </div>
    {/foreach}
</div>

Лучшие практики

1. Используйте правильные префиксы для контекста

{* ❌ Плохо: использование полноразмерных изображений в списках *}
<img src="/pic/full{$item.Image_FileUrl}" alt="Товар" style="width: 80px;">

{* ✅ Хорошо: используем подходящий размер *}
<img src="/pic/lists{$item.Image_FileUrl}" alt="Товар">

Почему важно: Браузер загрузит файл 200 КБ вместо 5 КБ, что замедлит загрузку страницы.

2. Добавляйте fallback для отсутствующих изображений

{* ❌ Плохо: сломанное изображение при отсутствии файла *}
<img src="/pic/medium{$item.Images.0}" alt="{$item.Name}">

{* ✅ Хорошо: placeholder при отсутствии изображения *}
<img src="{if $item.Images.0}/pic/medium{$item.Images.0}{else}/ext/Template/files/noimage.png{/if}" 
     alt="{$item.Name}">

3. Используйте lazy loading для изображений вне viewport

{* ❌ Плохо: все изображения загружаются сразу *}
{foreach $products as $item}
    <img src="/pic/medium{$item.Images.0}" alt="">
{/foreach}

{* ✅ Хорошо: отложенная загрузка *}
{foreach $products as $item}
    <img src="/pic/medium{$item.Images.0}" 
         alt="{$item.Name}" 
         loading="lazy">
{/foreach}

4. Оптимизируйте для адаптивности

{* ✅ Правильная структура с адаптивными изображениями *}
<picture>
    {* Мобильные устройства - меньшее изображение *}
    <source media="(max-width: 480px)" 
            srcset="/pic/preview{$item.Image_FileUrl}">

    {* Планшеты *}
    <source media="(max-width: 768px)" 
            srcset="/pic/medium{$item.Image_FileUrl}">

    {* Десктоп *}
    <img src="/pic/full{$item.Image_FileUrl}" 
         alt="{$item.Name}">
</picture>

5. Проверяйте наличие изображений перед использованием

{* ✅ Безопасная проверка массива изображений *}
{if !empty($product.Images) && isset($product.Images.0)}
    <img src="/pic/medium{$product.Images.0}" alt="{$product.Name}">
{else}
    <img src="/ext/Template/files/noimage.png" alt="Нет изображения">
{/if}

Архитектура и внутреннее устройство

Класс Images

Расположение: packages/WeppsExtensions/Addons/Images/Images.php

<?php
namespace WeppsExtensions\Addons\Images;

class Images
{
    // Конструктор принимает $_GET параметры
    function __construct($get)
    {
        // 1. Валидация fileUrl и pref
        // 2. Загрузка метаданных из s_Files
        // 3. Определение целевых размеров по префиксу
        // 4. Создание GD-ресурса изображения
        // 5. Выполнение resize/crop
    }

    // Сохранение в файловую систему
    public function save() { ... }

    // Вывод в HTTP-ответ
    public function output() { ... }

    // Наложение водяного знака
    public function stamp($x, $y, $gap, $list, $filename) { ... }
}

Request.php — точка входа

<?php
require_once __DIR__ . '/../../../../configloader.php';

use WeppsExtensions\Addons\Images\Images;

// Создание объекта с параметрами из URL
$obj = new Images($_GET);

// Наложение штампа (опционально)
$obj->stamp('center', 'bottom', 0.1, 'News|Gallery');

// Отдача изображения браузеру
$obj->output();

// Сохранение в файловую систему для кэширования
$obj->save();

unset($obj);

Алгоритм работы resize

private function resize(float $width, float $height, float $ratio)
{
    // Вписываем изображение в прямоугольник с сохранением пропорций
    if ($ratio >= 1) { // Горизонтальный формат
        if ($this->ratio >= 1) {
            $this->width = $height * $this->ratio;
            $this->height = $height;
        }
    } else { // Вертикальный формат
        if ($this->ratio >= 1) {
            $this->width = $width;
            $this->height = $width / $this->ratio;
        }
    }
}

Алгоритм работы crop

private function crop(float $width, float $height, float $ratio)
{
    $srcRatio = $this->ratio; // Соотношение исходного изображения
    $dstRatio = $ratio;       // Соотношение целевого прямоугольника

    if ($srcRatio > $dstRatio) {
        // Исходное шире целевого - обрезаем по бокам
        $this->height = $height;
        $this->width = $height * $srcRatio;
    } else {
        // Исходное выше целевого - обрезаем сверху/снизу
        $this->width = $width;
        $this->height = $width / $srcRatio;
    }
}

Добавление водяного знака (штампа)

Метод stamp()

public function stamp(
    string $x = 'right',      // Горизонтальное положение: left|center|right
    string $y = 'bottom',     // Вертикальное положение: top|center|bottom
    float $gap = 0.1,         // Отступ от края (доля от ширины штампа)
    string $list = '',        // Список таблиц БЕЗ штампа (через |)
    string $filename = ''     // Путь к PNG-файлу штампа
)

Пример использования в Request.php

// Наложить штамп в правом нижнем углу с отступом 10%
// НЕ накладывать на изображения из News и Gallery
$obj->stamp('right', 'bottom', 0.1, 'News|Gallery');

// Наложить штамп по центру сверху
$obj->stamp('center', 'top', 0.05, '');

// Использовать кастомный логотип
$obj->stamp('right', 'bottom', 0.1, '', '/path/to/custom-logo.png');

Особенности

  • Штамп автоматически масштабируется до 15% от меньшей стороны изображения
  • Поддерживается прозрачность PNG
  • Можно исключить таблицы из обработки (например, не ставить штамп на логотипы брендов)

Отладка

Проверка генерации изображений

# 1. Проверить, что исходный файл существует
ls -la files/lists/Products/test.jpg

# 2. Проверить запись в s_Files
mysql> SELECT * FROM s_Files WHERE FileUrl LIKE '%test.jpg%';

# 3. Проверить правило .htaccess
curl -I https://site.ru/pic/medium/lists/Products/test.jpg

# 4. Проверить созданные версии
ls -la pic/medium/lists/Products/
ls -la pic/preview/lists/Products/

Визуализация кэша

// Создать страницу для просмотра всех версий изображения
$testImage = '/lists/Products/test.jpg';
$prefixes = ['lists', 'preview', 'medium', 'mediumv', 'mediumsq', 'full', 'slide'];

echo '<table border="1"><tr>';
foreach ($prefixes as $pref) {
    echo '<th>' . $pref . '</th>';
}
echo '</tr><tr>';
foreach ($prefixes as $pref) {
    echo '<td><img src="/pic/' . $pref . $testImage . '" style="max-width:200px;"></td>';
}
echo '</tr></table>';

Частые проблемы

1. Изображение не генерируется (404 ошибка)

# Проверить, что mod_rewrite включен
apache2ctl -M | grep rewrite

# Проверить права на директорию pic/
chmod -R 755 pic/

# Проверить правило в .htaccess
tail -20 .htaccess | grep "RewriteRule.*pic"

2. Изображение генерируется, но не кэшируется

# Проверить, создается ли файл в pic/
ls -la pic/medium/lists/Products/

# Проверить права на запись
ls -ld pic/medium/

# Проверить логи Apache
tail -f /var/log/apache2/error.log

3. Старая версия изображения не обновляется

# Удалить закэшированные версии
rm -f pic/*/lists/Products/test.jpg

# При следующем запросе они сгенерируются заново

Производительность

Первичная генерация vs кэш

Первый запрос (генерация):
- Время: ~200-500ms
- CPU: высокое (обработка GD)
- I/O: чтение исходника + запись результата

Повторные запросы (кэш):
- Время: ~5-20ms
- CPU: минимальное (отдача статики)
- I/O: только чтение готового файла

Оптимизация производительности

// ❌ Неоптимально: генерировать все размеры при загрузке
foreach ($products as $item) {
    echo '<img src="/pic/lists' . $item->Images[0] . '">';
    echo '<img src="/pic/medium' . $item->Images[0] . '">';
    echo '<img src="/pic/full' . $item->Images[0] . '">';
}

// ✅ Оптимально: использовать только нужные размеры
foreach ($products as $item) {
    // В списке - только миниатюры
    echo '<img src="/pic/lists' . $item->Images[0] . '">';
}
// На странице товара - средний размер
echo '<img src="/pic/medium' . $product->Images[0] . '">';

Прогрев кэша

Если нужно заранее сгенерировать изображения (например, после массовой загрузки):

<?php
// warm-cache.php
require_once 'configloader.php';

use WeppsCore\Connect;

// Получить все изображения
$files = Connect::$instance->fetchAll("
    SELECT FileUrl 
    FROM s_Files 
    WHERE FileType LIKE 'image/%'
");

$prefixes = ['lists', 'preview', 'medium', 'full'];

foreach ($files as $file) {
    foreach ($prefixes as $pref) {
        $url = "https://site.ru/pic/{$pref}{$file['FileUrl']}";

        // Запросить URL для генерации
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_exec($ch);
        curl_close($ch);

        echo "Generated: {$url}\n";
    }
}

Очистка кэша изображений

Системный метод очистки (рекомендуется)

Платформа предоставляет встроенный инструмент для безопасной очистки неиспользуемых файлов:

Через админку:

  1. Перейти в раздел Настройки → Обработка → Задачи
  2. Нажать кнопку "Очистка файлов"
  3. Система удалит все файлы из /files/lists/* и /pic/*, которые не записаны в таблице s_Files

Через CLI:

# Из корня проекта
cd packages/WeppsAdmin/ConfigExtensions/Processing

# Выполнить очистку
php Request.php action=removefiles

Как это работает:

Метод ProcessingTasks::removeFiles() выполняет следующие действия:

  1. Удаляет из s_Files записи для несуществующих таблиц
  2. Удаляет из s_Files осиротевшие записи (когда запись в основной таблице удалена)
  3. Сканирует директории /files/lists/ и /pic/
  4. Сравнивает найденные файлы с записями в s_Files
  5. Удаляет файлы, которых нет в базе данных
// Пример из ProcessingTasks.php
public function removeFiles(): void
{
    // Очистка базы данных от устаревших записей
    self::removeDatabaseRows();

    // Поиск всех файлов
    $dirs = [
        $this->root . '/files/lists/',
        $this->root . '/pic/'
    ];
    $files = self::findFiles($dirs);

    // Получение списка из s_Files
    $res = Connect::$instance->fetch("SELECT FileUrl FROM s_Files");

    // Удаление файлов, не записанных в s_Files
    $diff = array_diff($filesFromDisk, $filesFromDatabase);
    foreach ($diff as $file) {
        unlink($file);
    }
}

Преимущества системного метода:

  • ✅ Безопасно — удаляет только неиспользуемые файлы
  • ✅ Очищает как исходники (/files/), так и кэш (/pic/)
  • ✅ Удаляет устаревшие записи из базы данных
  • ✅ Работает из админки и через CLI
  • ✅ Выводит количество удаленных файлов

Ручная очистка через терминал

Если нужно очистить кэш вручную без проверки базы данных:

# Очистить все кэшированные изображения
rm -rf pic/lists/* pic/preview/* pic/medium/* pic/full/* pic/slide/* pic/slidem/*

# Очистить кэш конкретного размера
rm -rf pic/medium/*

# Очистить кэш для конкретной таблицы
rm -rf pic/*/lists/Products/*

# Очистить конкретное изображение во всех размерах
find pic/ -name "test.jpg" -type f -delete

⚠️ Внимание: Ручная очистка удаляет все файлы, включая используемые. Они будут регенерированы при следующем запросе.

Автоматическое обновление при замене файла

При замене изображения через админку старый кэш автоматически становится неактуальным, так как платформа использует уникальные имена файлов с временной меткой:

// При загрузке файла в Lists.php
$prefix = sprintf("%06d", $id) . "_{$field}_" . date("U") . "_";
$destination = $prefix . $translit;

// Пример результата:
// /files/lists/Products/000123_Image_1738502400_product.jpg
//                                    ^^^^^^^^^^
//                              Unix timestamp (временная метка)

Как это работает:

  1. Загружается новый файл → создается с новой временной меткой
  2. Запись в s_Files обновляется с новым FileUrl
  3. Шаблоны получают новый URL из базы данных
  4. Кэш генерируется для нового файла
  5. Старый кэш остается, но не используется (будет удален при системной очистке)

Преимущества:

  • ✅ Нет проблем с кэшированием в браузере
  • ✅ Старая и новая версия не конфликтуют
  • ✅ Можно откатить изменения в базе данных
  • ✅ Не нужно вручную чистить кэш

Автоматическая очистка при удалении записи

<?php
// В расширении при удалении товара/новости
class Products extends Extension
{
    public function delete($id)
    {
        // Получить изображения
        $images = $this->getImages($id);

        // Удалить запись
        Connect::$instance->query("DELETE FROM Products WHERE Id = ?", [$id]);

        // Очистить кэш изображений
        foreach ($images as $imageUrl) {
            $this->clearImageCache($imageUrl);
        }
    }

    private function clearImageCache($fileUrl)
    {
        $prefixes = ['lists', 'preview', 'medium', 'full', 'slide'];

        foreach ($prefixes as $pref) {
            $cachedFile = Connect::$projectDev['root'] . "/pic/{$pref}{$fileUrl}";
            if (file_exists($cachedFile)) {
                @unlink($cachedFile);
            }
        }
    }
}

Скрипт периодической очистки старых файлов

#!/bin/bash
# clean-old-images.sh

# Удалить файлы старше 90 дней (если исходник был удален)
find /var/www/site/pic/lists -type f -mtime +90 -delete
find /var/www/site/pic/preview -type f -mtime +90 -delete
find /var/www/site/pic/medium -type f -mtime +90 -delete

# Удалить пустые директории
find /var/www/site/pic -type d -empty -delete

echo "Старые изображения очищены"

Добавить в cron для автоматического запуска:

# Каждый день в 3:00 утра
0 3 * * * /var/www/site/clean-old-images.sh >> /var/log/clean-images.log 2>&1

Мониторинг размера кэша

# Проверить общий размер кэшированных изображений
du -sh pic/*

# Вывод:
# 245M    pic/lists
# 1.2G    pic/medium
# 3.5G    pic/full
# 890M    pic/preview
# 2.1G    pic/slide

# Количество файлов в кэше
find pic/ -type f | wc -l

# Топ-10 самых больших файлов
find pic/ -type f -exec du -h {} + | sort -rh | head -10

Безопасность

Защита от path traversal

// ✅ В классе Images есть валидация пути
$filename = (isset($this->get['fileUrl'])) ? $this->get['fileUrl'] : '';
$rootfilename = $root . "" . $filename;

if (!is_file($rootfilename)) {
    Exception::error(404);
}

// ✅ Проверка существования записи в s_Files
$res = Connect::$instance->fetch("
    SELECT * FROM s_Files 
    WHERE FileType LIKE 'image/%' 
    AND FileUrl='/{$filename}'
");

if (count($res) == 0) {
    Exception::error(404);
}

Защита: Изображение будет сгенерировано только если:

  1. Файл физически существует
  2. Есть запись в таблице s_Files
  3. Тип файла — изображение

Ограничение максимального размера

// В конструкторе Images.php
$side = (is_numeric($side) && $side > 0) ? $side : 100;
$side = ($side > 1920) ? 1920 : $side; // Максимум 1920px

Защита от создания огромных изображений, которые могут перегрузить сервер.

Защита от несанкционированного доступа к s_Files

# В .htaccess запрещен доступ к файлам таблицы s_Files напрямую
<FilesMatch "^(config|install)\.php$">
    Order Deny,Allow
    Deny from All
</FilesMatch>

Расширение функционала

Добавление нового размера изображений

// В Images.php в конструкторе добавить новый case
switch ($action) {
    // ... существующие размеры ...

    case "custom":
        $this->widthDst = 800;
        $this->heightDst = 600;
        $crop = 0; // 0 = resize, 1 = crop
        break;
}

Использование в шаблоне

<img src="/pic/custom{$item.Image_FileUrl}" alt="">

Заключение

Класс Images в Wepps Platform предоставляет:

  • ✅ Автоматическую генерацию изображений нужных размеров
  • ✅ Эффективное кэширование в файловой системе
  • ✅ Оптимальные HTTP-заголовки для long-term кэширования
  • ✅ Поддержку множества предустановленных размеров
  • ✅ Возможность наложения водяных знаков
  • ✅ Защиту от несанкционированного доступа
  • ✅ Простую интеграцию в Smarty-шаблоны

Используйте правильные префиксы размеров для оптимизации производительности, добавляйте lazy loading для изображений вне viewport, и не забывайте периодически очищать устаревший кэш.


Файлы:

  • packages/WeppsExtensions/Addons/Images/Images.php — основной класс обработки
  • packages/WeppsExtensions/Addons/Images/Request.php — точка входа
  • .htaccess — правила перенаправления
  • pic/ — директория кэша изображений

Как фреймворк: Гибкость разработки

Полный контроль над кодом, архитектурой и расширениями для сложных проектов

wapps framework

Как CMS: Простота управления

Интуитивная админ-панель для редакторов контента без программирования

wapps cms

Как платформа: Готовые решения

Быстрый старт проектов с возможностью глубокой кастомизации под любые задачи

wapps platform
E
Работа с Excel-файлами в Wepps Platform: класс Excel для импорта и экспорта данных

Класс `Excel` предоставляет удобный интерфейс для работы с Excel-файлами в платформе Wepps. Позволяет создавать форматированные Excel-файлы из массивов данных, а также читать данные из существующих файлов с поддержкой многолистовых документов.

20.01.2026
P
Генерация PDF-документов в Wepps: От шаблона до готового файла

Нужно автоматически формировать счета, накладные или договоры? Раньше это требовало сложных библиотек, мучительной вёрстки в коде и головной боли с кириллицей. С платформой Wepps вы создаёте PDF так же просто, как обычную HTML-страницу.

17.01.2026
Создание системного расширения в Wepps: расширяем возможности админки

Можно ли создать отдельный модуль в админке со своей навигацией, несколькими страницами и полным контролем над PHP-кодом? Именно для этого существуют системные расширения — мощный инструмент для добавления произвольного функционала в административную панель.

15.01.2026

☝️ Будьте в курсе: полезные статьи, новости проекта и практические советы по работе с платформой Wepps.