uiarts/proxy-image

Proxy images

Maintainers

Package info

github.com/UI-Arts/proxy-image

pkg:composer/uiarts/proxy-image

Statistics

Installs: 116

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.3.1 2026-05-04 09:04 UTC

This package is auto-updated.

Last update: 2026-05-13 20:20:55 UTC


README

Пакет для проксування та обробки зображень (resize, crop, optimize) через підписані URL.

Встановлення

1. Додати пакет через Composer

composer require uiarts/proxy-image

2. Опублікувати конфіг

php artisan vendor:publish --tag=proxy-image-config

3. Опублікувати entrypoint (images.php)

php artisan vendor:publish --tag=proxy-image-public

Після цього файл буде доступний:

public/images.php

Налаштування

В .env додай:

IMAGES_HMAC_SECRET=your-secret-key
IMAGES_DEFAULT_DISK=your_disk
IMAGES_LOCAL_DISK=your_disk
IMAGES_LOCAL_PREFIX=
IMAGES_S3_DISK=s3
IMAGES_S3_PREFIX=
IMAGES_PICTURE_PLACEHOLDER_MODE=false
IMAGES_RENDERER=gd
IMAGES_LIBVIPS_BINARY=vipsthumbnail
IMAGES_LIBVIPS_MODE=vipsthumbnail

Або відредагуй config/proxy-image.php.

Renderer

  • IMAGES_RENDERER=gd — поточний дефолтний рендерер через GD.
  • IMAGES_RENDERER=libvips — рендерер через libvips CLI.
  • IMAGES_LIBVIPS_MODE=vipsthumbnail|thumbnail_source — режим роботи libvips.
  • IMAGES_LIBVIPS_BINARY — шлях/назва бінарника для обраного режиму:
    • vipsthumbnail для IMAGES_LIBVIPS_MODE=vipsthumbnail
    • vips для IMAGES_LIBVIPS_MODE=thumbnail_source

Placeholder mode (picsum)

Коли IMAGES_PICTURE_PLACEHOLDER_MODE=true, методи ProxyImage::picture(...) і ProxyImage::singleUrl(...) віддають лінки на https://picsum.photos/{width}/{height}. Розміри беруться з sizes для кожного брейкпоінта. Якщо висота a, використовується width / 2. Це зменшує навантаження на локальну машину під час розробки.

Налаштування Nginx

Додай у конфіг:

location ^~ /i/ {
    include fastcgi_params;

    fastcgi_pass php-fpm:9000;

    fastcgi_param SCRIPT_FILENAME $document_root/images.php;
    fastcgi_param SCRIPT_NAME /images.php;
    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
    add_header X-Images-Entrypoint 1 always;
}

if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
}

Формат URL

/i/{signature}/{ops}/{encoded}.{ext}

Приклад URL

https://example.com/i/{signature}/w:800/dXBsb2Fkcy90ZXN0LmpwZw.jpg

Приклад Використання

{!! 
\UIArts\ProxyImage\Facades\ProxyImage::picture(
    pictures: 'uploads/image.jpg',
    sizes: [
        'mobile' => [300, 'a'], // [(int)width, (int|string)height] height - може бути або int або стрінг, але тільки "a", що означає auto
        'tablet' => [300, 'a'],
        'desktop' => [800, 'a'],
    ],
    class: 'picture-wrap', // class для <picture>
    attributes: [
        'mode' => 'fit', // fit, fill
        'quality' => 85,
        'densities' => [1, 2],
        'alt' => 'Some alt',
        'title' => 'Some title',
        'class' => 'img-fluid', // class для <img>
        'data-zoom' => 'uploads/image.jpg',
        'data-error-src' => 'uploads/image.jpg',
        'loading' => 'lazy',
        'fetchPriority' => 'high', // high, low, auto
    ],
)
!!}

Headless JSON (picture data)

Структуровані дані для <picture> можна отримати без HTML:

\UIArts\ProxyImage\Facades\ProxyImage::pictureData(
    pictures: 'uploads/image.jpg',
    sizes: [
        'mobile' => [300, 'a'],
        'tablet' => [300, 'a'],
        'desktop' => [800, 'a'],
    ],
    attributes: [
        'mode' => 'fit',
        'quality' => 85,
        'densities' => [1, 2],
        'formats' => ['avif', 'jpg'],
        'alt' => 'Some alt',
    ],
);

Формат відповіді:

[
    'mode' => 'proxy', // proxy|bypass|placeholder
    'img' => [
        'src' => '/i/...',
        'srcset' => '/i/... 1x, /i/... 2x',
        'alt' => 'Some alt',
        'title' => 'Some title',
        'width' => 800,
        'height' => 'auto',
    ],
    'sources' => [
        [
            'type' => 'image/avif',
            'media' => '(min-width: 1200px)',
            'srcset' => '/i/... 1x, /i/... 2x',
        ],
    ],
]

Приклад для Vue:

<template>
  <picture v-if="data?.img?.src">
    <source
      v-for="(source, i) in (data?.sources || [])"
      :key="i"
      :type="source.type || undefined"
      :media="source.media || undefined"
      :srcset="source.srcset || ''"
    />
    <img
      :src="data.img.src"
      :srcset="data.img.srcset || undefined"
      :alt="data.img.alt || ''"
      :title="data.img.title || undefined"
      :width="data.img.width || undefined"
      :height="data.img.height !== 'auto' ? data.img.height : undefined"
    >
  </picture>
</template>

<script setup>
defineProps({
  data: { type: Object, required: true }
});
</script>