kupidonkhv / voyager-fork
A Laravel Admin Package for The Control Group to make your life easier and steer your project in the right direction
Requires
- php: ^8.2|^8.3|^8.4
- ext-gd: *
- ext-json: *
- arrilot/laravel-widgets: ^3.14
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- intervention/image: ^3.7|^4.0
- laravel/ui: ^4.0
- league/flysystem: ^3.0
- spatie/laravel-medialibrary: ^11.14
Requires (Dev)
- laravel/browser-kit-testing: ^7.0
- laravel/framework: ^10.0|^11.0|^12.0|^13.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- orchestra/testbench-browser-kit: ^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0|^12.0
Suggests
None
Provides
None
Conflicts
Replaces
None
- 1.7.x-dev
- v1.7.49
- v1.7.48
- v1.7.47
- v1.7.46
- v1.7.45
- v1.7.44
- v1.7.43
- v1.7.42
- v1.7.41
- v1.7.40
- v1.7.39
- v1.7.38
- v1.7.37
- v1.7.36
- v1.7.35
- v1.7.34
- v1.7.33
- 1.7.29
- 1.7.26
- 1.7.25
- 1.7.24
- 1.7.23
- 1.7.22
- 1.7.21
- 1.7.20
- 1.7.19
- 1.7.18
- 1.7.17
- 1.7.16
- 1.7.15
- 1.7.14
- 1.7.13
- 1.7.12
- 1.7.11
- 1.7.10
- 1.7.9
- 1.7.7
- v1.7.6
- v1.7.5
- v1.7.4
- v1.7.3
- v1.7.2
- v1.7.1
- v1.7
- v1.6.0
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.7
- v1.2.6
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.12
- v1.1.11
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.17
- v1.0.16
- v1.0.15
- v1.0.14
- v1.0.13
- v1.0.12
- v1.0.11
- v1.0.10
- v0.11.14
- dev-security/audit-hardening-2026-11
- dev-feature/voyager-activity-log
- dev-docs/readme-ru-complete
This package is auto-updated.
Last update: 2026-11-01 07:34:43 UTC
README
Voyager — это админ-панель и система BREAD (Browse, Read, Edit, Add, Delete) для Laravel. Форк kupidonkhv/voyager-fork поддерживает актуальные версии Laravel и PHP, а также включает готовые Галереи, Капчу, журнал активности и набор расширенных полей BREAD.
- Репозиторий форка: https://github.com/kupidonkhv/voyager
- Оригинальная документация: https://voyager-docs.devdojo.com/
- Демонстрация: https://voyager.devdojo.com/
- Пакет:
kupidonkhv/voyager-fork
Этот README полностью переведён на русский язык и адаптирован под форк 1.7.x. Код, имена классов, ключи конфигурации и JSON-примеры оставлены без изменений. Все страницы оригинальной документации переработаны с учётом поддержки Laravel 10–13, PHP 8.2–8.4, Галерей, Капчи, журнала активности и встроенных расширений.
Содержание
- Что нового в форке
- Введение
- Что такое Voyager
- Требования
- Установка
- Обновление
- Конфигурация
- Галереи
- Капча
- Встроенное расширение
- BREAD
- Связи
- Formfields
- Checkbox, множественные чекбоксы и радиокнопки
- Поле Coordinates
- Дата и время
- Dropdown
- Изображения
- Media Picker
- Number
- TinyMCE
- Маршрутизация
- Медиа-менеджер
- Меню и конструктор меню
- Менеджер базы данных
- Настройки
- Compass
- Роли и разрешения
- Журнал активности
- Helper-методы
- Мультиязычность
- Переопределение файлов
- Переопределение маршрутов
- Дополнительные CSS и JS
- Мягкое удаление
- Дополнительные атрибуты связей
- Свои formfields
- Координаты в модели
- BREAD-аксессоры
- Собственный guard
- Кнопки действий
- Решение проблем
- Разработка и тестирование
Что нового в форке
Поддержка Laravel и PHP
- Laravel 10.x, 11.x, 12.x и 13.x. Версия 1.7.48 проверена на Laravel 13.39.0.
- PHP 8.2, 8.3 и 8.4. Исправлены неявно nullable-параметры, несовместимые с PHP 8.4.
- Intervention Image 3.7+ и 4.x, включая нативный image-менеджер Laravel 13.
- Работа со схемой и интроспекцией базы данных без Doctrine DBAL, включая SQLite.
- Форматирование дат через
Voyager::formatDateсовместимо с Carbon 3. - После регистрации маршрутов обновляются name-lookups Laravel, поэтому BREAD-маршруты доступны и при повторной загрузке
routes/web.php. voyager:make:modelсохраняет сигнатуру Voyager на Laravel 13.- Кеширование меню учитывает allow-list классов кеша Laravel.
- Обновлены Artisan-команды, Compass, MakeModel и тесты под Laravel 13 / PHPUnit 12.
- Версия 1.7.46 исправляет упаковку релиза: представления, ресурсы и переводы расширения входят в архив, а правило
.gitignoreбольше не скрываетresources/views/vendor,publishable/assets/vendorиpublishable/lang/vendor.
Для Laravel 8–9 используйте Voyager 1.6.x. Для Laravel 6–7 используйте Voyager 1.5.
Кратко о галереях
Начиная с 1.7.47 в Voyager встроен BREAD-раздел «Галереи»:
- загрузка фотографий, подписи, сортировка перетаскиванием, выбор размера миниатюр;
- автоматическое создание пункта меню админки с учётом
APP_LOCALE(готовые переводы дляenиru, для остальных языков — английский fallback); - вставка галереи в контент через
%gallery="Название галереи"%; - готовые шаблоны вывода
default,photo-carouselиrounded; - отдельная установка и повторная установка командой
php artisan voyager:gallery:install; - хранение изображений через
spatie/laravel-medialibrary.
Подробности — в разделе Галереи.
Кратко о капче
Начиная с 1.7.45 в пакет встроена Капча:
- изображения по адресу
/captcha/{config}; - API-капча по адресу
/captcha/api/{config}; - helper-функции
captcha(),captcha_src(),captcha_img(),captcha_check(),captcha_api_check(); - правила валидации
captchaиcaptcha_api; - конфигурации
default,math,flat,mini,inverse.
Подробности — в разделе Капча.
Кратко о журнале активности
В версии 1.7.48 добавлен встроенный журнал действий администраторов:
- фиксирует, кто, когда и что сделал, над каким объектом и с каким результатом;
- покрывает изменения и удаления записей, файлы, настройки, роли и разрешения;
- хранит только имена изменённых полей, без старых и новых значений;
- разделяет просмотр журнала и просмотр технического контекста;
- поддерживает фильтры, очистку по сроку хранения и собственные события.
Подробности — в разделе Журнал активности.
Кратко о расширении
Начиная с 1.7.45 в пакет встроен kupidonkhv/voyager-extension:
- расширенные BREAD-шаблоны и липкая панель действий;
- клонирование записей;
- поля
adv_image,adv_media_files,adv_inline_set,adv_select_dropdown_tree,adv_fields_group,adv_json,adv_related,adv_page_layout; - генераторы путей и URL для Media Library;
- расширенный конструктор меню.
Отдельные пакеты monstrex/voyager-extension, kupidonkhv/captcha и mews/captcha больше не нужны и несовместимы с этой версией.
Подробности — в разделе Встроенное расширение.
Проверка релиза
composer validate vendor/bin/phpunit
Текущий набор: 148 тестов, 978 утверждений (PHP 8.4). Дополнительно проверена установка в чистом приложении Laravel 13.39.0.
Введение
Добро пожаловать в документацию Voyager для версии 1.7.x. Здесь описано, как установить, настроить и использовать Voyager, чтобы быстрее создавать административные панели и управлять данными приложения.
Перед установкой стоит понять, чем Voyager является, а чем — нет. Об этом следующий раздел.
Что такое Voyager
Прежде чем устанавливать Voyager, важно понять, что это и чем это не является.
Что это
- Интерфейс администратора для вашего Laravel-приложения.
- Простой способ добавлять, редактировать и удалять данные приложения.
- Конструктор меню: меню создаются в Voyager и выводятся в приложении.
- Медиа-менеджер для файлов.
- Генератор CRUD/BREAD. Подробнее: BREAD.
Voyager — это просто админка для Laravel-приложения. Что делать на фронтенде — решаете вы. Voyager помогает добавлять данные, редактировать пользователей, создавать меню и выполнять другие административные задачи.
Чем это не является
- Системой управления контентом (CMS).
- Платформой для блогов.
- WordPress.
Voyager — не CMS и не блог-платформа. На нём можно построить CMS или блог, но «из коробки» он ни тем, ни другим не является. Вы полностью контролируете поведение и функциональность приложения.
С Laravel и Voyager можно создать любое приложение. Это инструменты, которые упрощают разработку.
Требования
Перед установкой убедитесь, что выполнены следующие требования:
- Laravel 10, 11, 12 или 13.
- PHP 8.2, 8.3 или 8.4.
- Расширения PHP
gdиjson. - Composer 2.
- Поддерживаемая Laravel база данных: MySQL, MariaDB, PostgreSQL, SQLite или SQL Server. Работа со схемой без Doctrine DBAL проверена на SQLite.
- Права на запись в
storageиbootstrap/cache. - Возможность создать символическую ссылку
public/storage.
Для старых версий Laravel:
- Laravel 8–9 — Voyager 1.6.x.
- Laravel 6–7 — Voyager 1.5.x.
Установка
Установка Voyager состоит из нескольких шагов.
1. Подключите пакет
Создайте новое Laravel-приложение и добавьте пакет:
composer require kupidonkhv/voyager-fork:^1.7.48
Если в проекте уже установлены старые отдельные пакеты, сначала удалите их:
composer remove monstrex/voyager-extension kupidonkhv/captcha mews/captcha composer require kupidonkhv/voyager-fork:^1.7.48
Если Packagist ещё не проиндексировал новый релиз, подождите несколько минут или установите ветку разработки:
composer require kupidonkhv/voyager-fork:dev-1.7
2. Настройте базу данных и APP_URL
Создайте базу данных и добавьте учётные данные в .env:
DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret
Также задайте адрес приложения:
APP_URL=http://localhost:8000
3. Запустите установщик
Voyager можно установить с демо-данными или без них. Демо-данные включают одного администратора (если в базе ещё нет пользователей), одну демонстрационную страницу, четыре демонстрационных поста, две категории и семь настроек.
Установка без демо-данных:
php artisan voyager:install
Установка с демо-данными:
php artisan voyager:install --with-dummy
Установщик публикует ресурсы, выполняет миграции, добавляет маршруты, создаёт сиды, устанавливает BREAD «Галереи» и создаёт символическую ссылку storage.
Если вы видите ошибку Specified key was too long, скорее всего, используется устаревшая версия MySQL. Решение описано в Laravel News.
Запустите локальный сервер:
php artisan serve
И откройте http://localhost:8000/admin.
При установке с демо-данными создаётся пользователь:
email:
admin@admin.compassword:password
Демо-пользователь создаётся только если в базе ещё нет пользователей.
4. Назначьте администратора
Если демо-данные не устанавливались, можно выдать права администратора существующему пользователю:
php artisan voyager:admin your@email.com
Чтобы создать нового администратора, передайте флаг --create:
php artisan voyager:admin your@email.com --create
Команда запросит имя и пароль пользователя.
Публикация конфигурации и ресурсов
Публикация выполняется по тегам:
php artisan vendor:publish --tag=voyager-extension-config php artisan vendor:publish --tag=captcha-config php artisan vendor:publish --tag=voyager-extension-assets
Дополнительно можно опубликовать представления и переводы расширения:
php artisan vendor:publish --tag=voyager-extension-views php artisan vendor:publish --tag=voyager-extension-lang
Расширение включено по умолчанию. Отключить его можно в .env:
VOYAGER_EXTENSION_ENABLED=false
Ручная установка в существующее приложение
Этот раздел для случаев, когда Voyager ставится в уже существующее Laravel-приложение или нужна ручная установка.
Опубликуйте ресурсы пакета:
php artisan vendor:publish --provider="TCG\Voyager\VoyagerServiceProvider"
Выполните миграции:
php artisan migrate
Если нужно изменить миграции, например использовать другую таблицу пользователей, не запускайте миграции сразу. Скопируйте миграции Voyager в
database/migrations, внесите изменения, отключите опциюdatabase.autoload_migrationsи только затем выполните миграции.
Укажите, что модель User наследует модель Voyager. Обычно это app/User.php или app/Models/User.php:
<?php class User extends \TCG\Voyager\Models\User { // ... }
Добавьте маршруты Voyager в routes/web.php:
<?php Route::group(['prefix' => 'admin'], function () { Voyager::routes(); });
Заполните базу необходимыми данными:
php artisan db:seed --class=VoyagerDatabaseSeeder
Создайте символическую ссылку хранилища:
php artisan storage:link
Установите BREAD «Галереи»:
php artisan voyager:gallery:install
Завершите установку:
composer dump-autoload
Обновление
Обновление до 1.7.48
Обновите версию в composer.json:
"kupidonkhv/voyager-fork": "^1.7.48"
Затем выполните:
composer update
Если ранее использовались отдельные расширения и капча, удалите их:
composer remove monstrex/voyager-extension kupidonkhv/captcha mews/captcha
Опубликуйте обновлённые конфигурации:
php artisan vendor:publish --tag=voyager-extension-config --force php artisan vendor:publish --tag=captcha-config --force php artisan vendor:publish --tag=voyager-activity-config --force php artisan vendor:publish --tag=voyager-extension-assets --force
Выполните миграции, установите Галереи и журнал активности:
php artisan migrate php artisan voyager:gallery:install php artisan voyager:activity:install
Очистите кеши:
php artisan config:clear php artisan cache:clear php artisan view:clear
Если вы переопределяли представления Voyager, сравните их с новой версией: в 1.7.x изменены BREAD-шаблоны, форматирование дат и подключение ресурсов расширения.
Обновление с 1.5 на 1.6
При обновлении старых проектов обновите версию в composer.json:
"tcg/voyager": "1.6.*"
Затем выполните:
composer update
TinyMCE обновлён до версии 6, и многие параметры конфигурации изменились. Если в консоли появляются ошибки и вы настраивали TinyMCE, сверьте параметры с актуальной документацией TinyMCE.
Если возникают проблемы, задайте вопрос в Slack-сообществе Voyager.
Конфигурация
После установки создаётся файл config/voyager.php. В нём собраны настройки Voyager.
Если вы кешируете конфигурацию, после изменений выполняйте
php artisan config:clear.
Ниже разобраны основные параметры.
Пользователи
'user' => [ 'add_default_role_on_register' => true, 'default_role' => 'user', 'default_avatar' => 'users/default.png', 'redirect' => '/admin', ],
- add_default_role_on_register — добавлять ли новому пользователю роль по умолчанию.
- default_role — роль, которая назначается новым пользователям.
- default_avatar — путь к аватару по умолчанию.
- redirect — куда перенаправлять пользователя после входа.
Доступ к админ-панели проверяется по разрешению browse_admin. Оно создаётся при установке и не настраивается отдельным ключом.
Контроллеры
'controllers' => [ 'namespace' => 'TCG\\Voyager\\Http\\Controllers', ],
Здесь задаётся namespace контроллеров Voyager. Если нужно переопределить поведение, скопируйте контроллеры и укажите расположение своих контроллеров.
Переопределение одного контроллера Если нужно заменить только один контроллер, добавьте в метод
registerклассаAppServiceProvider:$this->app->bind(VoyagerBreadController::class, MyBreadController::class);
Модели
'models' => [ //'namespace' => 'App\\Models\\', ],
Namespace моделей, которые создаются из раздела базы данных Voyager. Если параметр не задан, используется namespace приложения по умолчанию. Не забудьте завершающие обратные слеши.
Хранилище
'storage' => [ 'disk' => 'public', ],
По умолчанию Voyager использует локальный диск public. Можно указать любой диск из config/filesystems.php: S3, Google Cloud Storage или другое хранилище.
Скрытые файлы медиа-менеджера
'hidden_files' => false,
Показывать ли в медиа-менеджере скрытые файлы, например .gitignore.
Параметры галерей
'gallery' => [ 'enabled' => env('VOYAGER_GALLERY_ENABLED', true), 'menu_title' => env('VOYAGER_GALLERY_MENU_TITLE'), 'thumb_dimensions' => env('VOYAGER_GALLERY_THUMB_DIMENSIONS', '400x300'), 'max_upload_size' => env('VOYAGER_GALLERY_MAX_UPLOAD_SIZE', 10240), 'accepted_mime_types' => [ 'image/jpeg', 'image/png', 'image/webp', 'image/gif', ], ],
- enabled — включает раздел «Галереи». При
falseкоманда установки пропускает создание BREAD и пункта меню. - menu_title — собственный заголовок пункта меню. Если не задан, используется перевод для текущей локали.
- thumb_dimensions — размер миниатюр по умолчанию в формате
ШИРИНАxВЫСОТА. - max_upload_size — максимальный размер файла в килобайтах. По умолчанию
10240КБ (10 МБ). - accepted_mime_types — разрешённые MIME-типы изображений.
Подробности — в разделе Галереи.
База данных
'database' => [ 'tables' => [ 'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'personal_access_tokens', 'settings'], ], 'autoload_migrations' => true, ],
В tables.hidden перечислены таблицы, скрытые в разделе базы данных Voyager. Параметр autoload_migrations позволяет исключить миграции Voyager при выполнении php artisan migrate.
Параметры мультиязычности
'multilingual' => [ 'enabled' => false, 'default' => 'en', 'locales' => [ 'en', //'pt', ], ],
- enabled — включает поддержку нескольких языков.
- default — язык по умолчанию.
- locales — поддерживаемые локали.
Подробнее: Мультиязычность.
Панель управления
'dashboard' => [ 'navbar_items' => [ 'voyager::generic.profile' => [ 'route' => 'voyager.profile', 'classes' => 'class-full-of-rum', 'icon_class' => 'voyager-person', ], 'voyager::generic.home' => [ 'route' => '/', 'icon_class' => 'voyager-home', 'target_blank' => true, ], 'voyager::generic.logout' => [ 'route' => 'voyager.logout', 'icon_class' => 'voyager-power', ], ], 'widgets' => [ ], ],
- navbar_items — пункты выпадающего меню пользователя. Поддерживаются
route,icon_class,target_blankиclasses. - widgets — классы виджетов на панели управления. Примеры находятся в
src/Widgets.
Автоматические действия BREAD
'bread' => [ 'add_menu_item' => true, 'default_menu' => 'admin', 'add_permission' => true, 'default_role' => 'admin', ],
- add_menu_item — создавать пункт меню при добавлении BREAD.
- default_menu — меню, в которое добавляется пункт.
- add_permission — создавать разрешения для нового BREAD.
- default_role — роль, которой выдаются эти разрешения.
Основной цвет
'primary_color' => '#22A7F0',
Основной цвет админ-панели. По умолчанию — светло-синий.
Подсказки разработчику
'show_dev_tips' => true,
Показывает подсказки о том, как обращаться к значениям Voyager. Отключите параметром false.
Подключение CSS и JS
'additional_css' => [ //'css/custom.css', ], 'additional_js' => [ //'js/custom.js', ],
Файлы подключаются в админ-панели после ресурсов Voyager, поэтому могут переопределять стили и поведение. Путь передаётся в функцию Laravel asset().
Подробнее: Дополнительные CSS и JS.
Google Maps
'googlemaps' => [ 'key' => env('GOOGLE_MAPS_KEY', ''), 'center' => [ 'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'), 'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'), ], 'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11), ],
Настройки для поля Coordinates. Здесь задаются ключ Google Maps, центр карты и масштаб. Значения можно хранить в .env.
Кеш настроек
'settings' => [ 'cache' => false, ],
Включает кеширование настроек между запросами средствами Laravel.
Compass в production
'compass_in_production' => false,
Включает Compass в окружении, отличном от local, например в production.
Параметры медиа-менеджера
'media' => [ 'allowed_mimetypes' => [ 'image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'video/mp4', ], 'path' => '/', 'show_folders' => true, 'allow_upload' => true, 'allow_move' => true, 'allow_delete' => true, 'allow_create_folder' => true, 'allow_rename' => true, ],
- allowed_mimetypes — разрешённые типы файлов. Чтобы разрешить все типы, используйте
'*'. - path — стартовый путь относительно файловой системы.
- show_folders — показывать вложенные папки.
- allow_upload, allow_move, allow_delete, allow_create_folder, allow_rename — разрешения на соответствующие операции.
В этом же разделе можно задать watermark и thumbnails. Их формат описан в разделе Media Picker.
Галереи
Раздел «Галереи» появился в версии 1.7.47. Он позволяет вести фотогалереи в админке и выводить их на сайте. Изображения хранятся через spatie/laravel-medialibrary, поэтому пакет добавляет зависимость spatie/laravel-medialibrary и требует расширение ext-gd.
Установка и повторная установка
При выполнении php artisan voyager:install Галереи устанавливаются автоматически. Отдельная команда нужна для повторной установки, обновления или включения раздела в существующем проекте:
php artisan voyager:gallery:install
Команда:
- при необходимости выполняет миграции Media Library;
- создаёт BREAD
galleries, если его ещё нет; - создаёт поля BREAD и разрешения
browse_galleries,read_galleries,edit_galleries,add_galleries,delete_galleries; - выдаёт эти разрешения роли
admin; - создаёт пункт меню в меню
admin, если оно существует.
Если меню
adminещё не создано, команда предупредит об этом. Создайте меню в конструкторе меню и запустите команду снова.
Если раздел отключён в конфигурации, команда завершится с сообщением, что Галереи отключены:
'gallery' => [ 'enabled' => false, ],
Поля галереи
В BREAD «Галереи» доступны поля:
- title — название галереи. Обязательное поле. Именно по нему галерея находится при вставке в контент.
- dimensions — размер миниатюр. Список готовых вариантов:
400x300,600x450,800x600,1024x768,300x400,450x600,600x800,768x1024,300x300,500x500,800x800,600x400,400x600,900x600,600x900. - description — описание галереи.
- sort_order — порядок сортировки самих галерей.
Размер миниатюр можно задать отдельно для каждой галереи. Если поле не заполнено, используется voyager.gallery.thumb_dimensions.
Работа с фотографиями
Откройте галерею на редактирование. На странице есть область загрузки:
- перетащите изображения в область или нажмите на неё, чтобы выбрать файлы;
- после загрузки можно добавить подпись к каждому фото;
- фотографии можно перетаскивать для изменения порядка;
- фотографию можно удалить.
Сначала сохраните галерею, затем загружайте фотографии на странице редактирования. Для новой записи область загрузки показывает подсказку сохранить галерею.
Ограничения загрузки:
- разрешённые MIME-типы задаются в
voyager.gallery.accepted_mime_types; - максимальный размер файла задаётся в
voyager.gallery.max_upload_sizeв килобайтах; - подпись к фотографии ограничена 500 символами.
Конфигурация
'gallery' => [ 'enabled' => env('VOYAGER_GALLERY_ENABLED', true), 'menu_title' => env('VOYAGER_GALLERY_MENU_TITLE'), 'thumb_dimensions' => env('VOYAGER_GALLERY_THUMB_DIMENSIONS', '400x300'), 'max_upload_size' => env('VOYAGER_GALLERY_MAX_UPLOAD_SIZE', 10240), 'accepted_mime_types' => [ 'image/jpeg', 'image/png', 'image/webp', 'image/gif', ], ],
Переменные окружения:
VOYAGER_GALLERY_ENABLED=true VOYAGER_GALLERY_MENU_TITLE="Галереи" VOYAGER_GALLERY_THUMB_DIMENSIONS=400x300 VOYAGER_GALLERY_MAX_UPLOAD_SIZE=10240
- enabled — включает или отключает раздел.
- menu_title — заголовок пункта меню. Если не задан, используется перевод.
- thumb_dimensions — размер миниатюр по умолчанию.
- max_upload_size — максимальный размер файла в килобайтах.
- accepted_mime_types — список разрешённых MIME-типов.
Язык пункта меню
Пункт меню создаётся на языке, который выбран в APP_LOCALE. Для en и ru в пакете есть готовые переводы. Для остальных локалей используется английский текст. Заголовок можно переопределить через gallery.menu_title или VOYAGER_GALLERY_MENU_TITLE.
Вывод галереи в контенте
Вставьте в контент токен с названием галереи:
%gallery="Название галереи"%
Чтобы выбрать шаблон вывода, укажите form:
%gallery="Название галереи" form="rounded"%
Доступные шаблоны:
default— сетка миниатюр с подписями;photo-carousel— горизонтальная карусель;rounded— сетка с круглыми миниатюрами.
Токен обрабатывается макросом Str::parseGalleries(). Вызовите его там, где выводится контент:
{!! \Illuminate\Support\Str::parseGalleries($page->body) !!}
Если галерея не найдена или в ней нет фотографий, в HTML выводится комментарий вида <!-- Gallery "..." not found or empty -->. Это безопасно и не ломает страницу.
Переопределение шаблонов
Шаблоны лежат в resources/views/gallery. Их можно переопределить в приложении:
resources/views/gallery/default.blade.phpresources/views/gallery/photo-carousel.blade.phpresources/views/gallery/rounded.blade.php
Или в каталоге переопределений Voyager:
resources/views/vendor/voyager/gallery/default.blade.phpresources/views/vendor/voyager/gallery/photo-carousel.blade.phpresources/views/vendor/voyager/gallery/rounded.blade.php
В шаблон передаётся переменная $gallery — модель TCG\Voyager\Models\Gallery.
Работа с моделью
use TCG\Voyager\Models\Gallery; $gallery = Gallery::where('title', 'Название галереи')->first(); foreach ($gallery->images as $media) { echo $media->getUrl(); // оригинал echo $media->getUrl('thumb'); // миниатюра echo $media->getCustomProperty('description', ''); }
Связь images() возвращает медиафайлы коллекции images, отсортированные по order_column.
Капча
Начиная с 1.7.45 в пакет встроена Капча на основе Mews Captcha. Она умеет создавать изображения, работать через API и проверять значения правилами валидации Laravel.
Публикация конфигурации
php artisan vendor:publish --tag=captcha-config
После публикации появится config/captcha.php.
Маршруты
GET /captcha/{config}— изображение капчи. По умолчанию/captcha/default.GET /captcha/api/{config}— JSON с ключом и изображением в data URI.
Маршруты регистрируются с middleware web, если приложение использует веб-группу. При отключённой капче маршруты не создаются.
Конфигурации
Встроенные конфигурации: default, math, flat, mini, inverse.
'default' => [ 'length' => 9, 'width' => 120, 'height' => 36, 'quality' => 90, 'math' => false, 'expire' => 60, 'encrypt' => false, ], 'math' => [ 'length' => 9, 'width' => 120, 'height' => 36, 'quality' => 90, 'math' => true, ],
Основные параметры:
- length — количество символов;
- width, height — размеры изображения;
- quality — качество JPEG;
- math — математическая капча;
- expire — время жизни кода в секундах;
- encrypt — шифрование ключа;
- sensitive — учитывать регистр;
- lines, bgImage, bgColor, fontColors, contrast, angle, sharpen, blur, invert — визуальные настройки.
Отключить капчу можно в .env:
CAPTCHA_DISABLE=true
При отключении правила валидации всегда считаются пройденными, а маршруты не регистрируются.
Helper-функции
captcha(); // изображение (Response) captcha('flat'); // изображение с конфигурацией flat captcha_src(); // URL изображения captcha_src('mini'); // URL для конфигурации mini captcha_img(); // HTML-тег img captcha_img('flat', ['class' => 'form-control', 'alt' => 'Капча']); captcha_check($value); // проверка значения из сессии captcha_api_check($value, $key, 'default');
В Blade:
{!! captcha_img() !!}
Проверка формы
$request->validate([ 'captcha' => 'required|captcha', ]);
Если нужно вывести сообщение об ошибке, используйте стандартные средства Laravel:
@error('captcha') <span class="text-danger">{{ $message }}</span> @enderror
API-капча
Запросите /captcha/api/default и получите JSON:
{
"sensitive": false,
"key": "...",
"img": "data:image/jpeg;base64,..."
}
Покажите img пользователю, сохраните key и проверьте ответ правилом captcha_api:
$request->validate([ 'captcha' => 'required|captcha_api:'.$key.',default', ]);
Или через helper:
if (!captcha_api_check($request->input('captcha'), $key, 'default')) { // неверная капча }
captcha_apiпринимает первым параметром ключ, вторым — имя конфигурации. Если конфигурация не указана, используетсяdefault.
Ограничения
- Код хранится в кеше и живёт
expireсекунд (по умолчанию 60). - После успешной проверки значение удаляется из кеша и сессии.
- Для загрузки изображений и шрифтов нужны права на чтение файлов пакета.
Встроенное расширение
Начиная с 1.7.45 расширение kupidonkhv/voyager-extension входит в пакет. Оно добавляет в BREAD расширенные шаблоны, клонирование записей, дополнительные поля и генераторы Media Library.
Конфигурация
Опубликуйте конфигурацию:
php artisan vendor:publish --tag=voyager-extension-config
Основные параметры config/voyager-extension.php:
'enabled' => env('VOYAGER_EXTENSION_ENABLED', true), 'legacy_browse_bread' => false, 'legacy_edit_add_bread' => false, 'legacy_bread_list' => false, 'sticky_action_panel' => [ 'enabled' => true, 'autohide' => false, ], 'clone_record' => [ 'enabled' => true, 'reset_types' => ['image', 'multiple_images', 'file'], 'suffix_fields' => ['title', 'name', 'slug', 'key'], ], 'use_media_path_generator' => true, 'use_media_url_generator' => true, 'slug_filenames' => true, 'assets_path_prefix' => 'admin',
- enabled — включает расширение. Отключается через
VOYAGER_EXTENSION_ENABLED=false. - legacy_browse_bread, legacy_edit_add_bread, legacy_bread_list — возвращают оригинальные представления Voyager вместо расширенных.
- sticky_action_panel.enabled — включает липкую панель действий. autohide скрывает её, пока курсор не наведён.
- clone_record.enabled — включает кнопку клонирования.
- clone_record.reset_types — типы полей, значения которых очищаются при клонировании.
- clone_record.suffix_fields — поля, к значению которых добавляется суффикс
(clone). - use_media_path_generator, use_media_url_generator — включают генераторы путей и URL Media Library.
- slug_filenames — преобразует имена файлов в slug перед сохранением.
- assets_path_prefix — префикс пути к ресурсам расширения.
Поля BREAD
| Код поля | Название | Назначение |
|---|---|---|
adv_image |
VE Image | Одно изображение через Media Library с атрибутами title и alt |
adv_media_files |
VE Media Files | Несколько медиафайлов с выбором, удалением и сортировкой |
adv_inline_set |
VE Inline Fields Set | Набор вложенных полей, редактируемый прямо в форме |
adv_select_dropdown_tree |
VE Select Dropdown Tree | Выпадающий список с древовидной иерархией |
adv_fields_group |
VE Fields Group | Группа полей |
adv_json |
VE JSON Fields | Редактирование JSON-структуры |
adv_related |
VE Related Model | Связанная модель |
adv_page_layout |
VE Page Layout | Конструктор секций страницы. Требует пакет monstrex/voyager-site |
Выберите нужный код в поле Form Type при настройке BREAD. Для расширенных полей можно использовать те же JSON-опции, что и для стандартных formfields.
Изображения и медиафайлы
adv_image сохраняет изображение в Media Library. В модели получите файл по имени поля:
$image = $post->getFirstMedia('image'); $imageUrl = $image->getFullUrl(); $imageTitle = $image->getCustomProperty('title'); $imageAlt = $image->getCustomProperty('alt');
Для adv_media_files используйте коллекцию Media Library и перебирайте файлы:
foreach ($post->getMedia('files') as $media) { echo $media->getUrl(); }
Имена коллекций зависят от настроек поля. Проверьте их в BREAD и в форме редактирования.
Клонирование записей
При включённом clone_record.enabled в списке записей появляется кнопка «Клонировать». Клон создаётся через маршрут POST {slug}/{id}/clone. Поведение настраивается:
'clone_record' => [ 'enabled' => true, 'reset_types' => ['image', 'multiple_images', 'file'], 'suffix_fields' => ['title', 'name', 'slug', 'key'], ],
- поля из
reset_typesочищаются; - к полям из
suffix_fieldsдобавляется(clone); - остальные значения копируются.
Для клонирования нужно разрешение add на соответствующий BREAD.
Генераторы Media Library
Расширение подменяет генераторы путей и URL Media Library, если включены соответствующие параметры. Это позволяет хранить файлы в предсказуемой структуре и формировать URL с префиксом ресурсов админки.
Конструктор меню
Расширенный конструктор меню добавляет обновление пунктов без перезагрузки страницы, работу с цветом, иконками и параметрами маршрутов. Используются маршруты:
voyager.menu-items.ext-record-update— обновление записи пункта меню;voyager.ext-records-get— получение списка записей.
Helper-функции расширения
str_trans('{{en}}English{{ru}}Русский'); // строка на текущей локали voyager_extension_asset('css/app.css'); // URL ресурса расширения flat_to_tree($items); // плоский массив в дерево json_response_with_success($status, $message, $data); json_response_with_error($status, $error);
str_trans() поддерживает синтаксис {{locale}}текст и [[locale]]текст. Если перевод для текущей локали не найден, возвращается первый вариант.
BREAD
BREAD расшифровывается как Browse, Read, Edit, Add, Delete. Это система управления записями таблицы базы данных.
Введение
При добавлении или редактировании BREAD для таблицы сначала отображается блок сведений:
- отображаемые имена в единственном и множественном числе;
- slug;
- иконка;
Modelи namespace контроллера;- имя Policy;
- создание разрешений для BREAD.
Ниже находится список полей таблицы. Для каждого поля можно выбрать, где оно отображается:
- BROWSE — поле показывается в списке записей;
- READ — поле показывается на странице просмотра записи;
- EDIT — поле доступно для редактирования;
- ADD — поле показывается при создании записи;
- DELETE — не влияет на удаление, флаг можно включать или выключать.
Для каждого поля выбирается тип формы: текстовое поле, текстовая область, чекбокс, изображение и другие. Дополнительные параметры задаются в JSON в блоке Optional Details.
Валидация
В Optional Details можно указать правила валидации. Пример: обязательное поле с максимальной длиной 12 символов.
{
"validation": {
"rule": "required|max:12"
}
}
Свои сообщения об ошибках:
{
"validation": {
"rule": "required|max:12",
"messages": {
"required": "Поле :attribute обязательно.",
"max": "Максимальная длина поля :attribute — :max."
}
}
}
Несколько правил:
{
"validation": {
"rule": [
"required",
"max:12"
]
}
}
Отдельные правила для редактирования и добавления:
{
"validation": {
"rule": "min:3",
"edit": {
"rule": "nullable"
},
"add": {
"rule": "required"
}
}
}
Полный список правил — в документации Laravel.
Тегирование
Тегирование позволяет добавлять новые элементы в связь Belongs-To-Many прямо при редактировании или создании записи.
Включите Tagging в настройках связи. Затем введите свободный текст в поле выбора и нажмите Enter, чтобы сохранить новую связь.
Сохраняется только
display-column. Убедитесь, что остальные поля таблицы допускаютNULLили имеют значение по умолчанию.
Сортировка записей BREAD
Можно задать порядок по умолчанию для списка записей и менять порядок перетаскиванием. Для этого измените настройки BREAD:
- Order column — поле таблицы, в котором хранится целочисленный порядок;
- Order display column — поле, которое показывается в списке перетаскивания;
- Order direction — направление сортировки.
После этого на странице списка появится кнопка Order. Она открывает страницу изменения порядка записей.
Ограничение выборки через Scope
Чтобы фильтровать список записей BREAD, создайте локальный scope в модели. Например, чтобы показывать только посты текущего пользователя:
<?php public function scopeCurrentUser($query) { return $query->where('author_id', Auth::user()->id); }
Затем откройте настройки BREAD для posts, найдите поле Scope и выберите currentUser. После сохранения вы увидите только свои записи.
Связи
Создание связи
Связи между таблицами создаются в конструкторе BREAD. Внизу страницы есть кнопка Create Relationship.
Если BREAD для таблицы ещё не создан, сначала создайте его, затем вернитесь к добавлению связи. Иначе появится уведомление о том, что BREAD отсутствует.
После нажатия Create Relationship откроется окно, в котором нужно:
- выбрать тип связи;
- выбрать таблицу, на которую ссылается связь;
- указать namespace этой таблицы;
- выбрать поле, которое связывает таблицы;
- при необходимости выбрать колонки для выпадающего списка или мультиселекта.
Voyager поддерживает связи belongsTo, belongsToMany, hasOne и hasMany.
Дополнительные параметры
Для belongsToMany после сохранения связи можно указать параметры в поле details:
{
"foreign_pivot_key": "user_id",
"related_pivot_key": "role_id",
"parent_key": "id"
}
Сортировка связей
Результаты связи сортируются через объект sort:
{
"sort": {
"field": "my_field",
"direction": "asc"
}
}
Или по убыванию:
{
"sort": {
"field": "my_field",
"direction": "desc"
}
}
Ограничение вариантов связи
Показываемые варианты можно отфильтровать локальным scope в связанной модели. Например, чтобы показывать только активные записи:
public function scopeActive($query) { return $query->where('active', 1); }
Добавьте в параметры связи:
{
"scope": "active",
}
Значение — имя метода без префикса scope. Для scopeActive() это active, для scopeSomeUsers() — someUsers.
В связи BelongsTo поле внешнего ключа определяет, можно ли сохранить значение при добавлении или редактировании, и к нему применяются правила валидации. Для остальных действий, например отображения в списке и редактирования, используется поле связи.
Formfields
Formfields — основа BREAD-системы Voyager. Каждый formfield представляет поле таблицы базы данных и один элемент ввода или вывода в BREAD. Поведение настраивается JSON-опциями.
Все formfields поддерживают несколько общих параметров.
Описание
Любой тип может содержать описание, которое помогает понять назначение поля. Оно задаётся в Optional Details:
{
"description": "Подсказка для этого поля."
}
Параметры отображения
Ширина поля и пользовательский ID задаются через ключ display:
{
"display": {
"width": "3",
"id": "custom_id"
}
}
Ширина считается по сетке из 12 колонок. Значение 3 занимает 25% ширины.
Ключ id задаёт обёртку вокруг элемента:
<div id="custom_id">
<!-- Your field element -->
</div>
Значение по умолчанию
Большинство formfields поддерживают значение по умолчанию:
{
"default" : "Текст по умолчанию"
}
Значения NULL
Иногда пустую строку нужно сохранить в базу как null. Укажите:
{
"null": ""
}
Тогда пустая строка будет записана как null. Если нужно сохранять и пустую строку, и null, выберите строку-заменитель:
{
"null": "Nothing"
}
Теперь ввод Nothing сохранится как null, а пустая строка останется пустой строкой.
Генерация slug
Чтобы автоматически создавать slug из другого поля, например из title:
{
"slugify": {
"origin": "title",
"forceUpdate": true
}
}
Slug создаётся из значения поля title. Если slug уже существует, он обновится только при forceUpdate: true. По умолчанию обновление отключено.
Пользовательское представление
Для formfield можно указать собственный Blade-шаблон:
{
"view": "my_view"
}
Шаблон my_view загружается из resources/views вместо стандартного представления formfield.
В шаблон передаются:
$view— одно из значенийbrowse,read,edit,add,order;$content— содержимое поля;$dataType— модель DataType;$dataTypeContent— экземпляр модели записи;$row— DataRow;$options— детали DataRow.
Можно задать отдельные представления для действий:
{
"view_browse": "my_browse_view",
"view_read": "my_read_view",
"view_add": "my_add_view",
"view_edit": "my_edit_view",
"view_order": "my_order_view"
}
В них передаются те же переменные.
Разработка собственного formfield? Если вы создаёте свой formfield и хотите переопределить представления, объедините
viewс$optionsв методеcreateContent().
Checkbox, множественные чекбоксы и радиокнопки
Checkbox
{
"on" : "Включено",
"off" : "Выключено",
"checked" : true
}
Checkbox отображается как переключатель. Ключ on содержит значение во включённом состоянии, off — в выключенном. Если checked равно true, переключатель включён по умолчанию.
Multiple Checkbox
{
"checked" : true,
"options": {
"checkbox1": "Текст чекбокса 1",
"checkbox2": "Текст чекбокса 2"
}
}
Количество чекбоксов не ограничено.
Radio Button
{
"default" : "radio1",
"options" : {
"radio1": "Текст радиокнопки 1",
"radio2": "Текст радиокнопки 2"
}
}
Радиокнопки работают так же, как dropdown. В default задаётся значение по умолчанию, в options слева указывается значение, справа — отображаемый текст.
Поле Coordinates
Поле Coordinates позволяет выбрать координаты на карте Google Maps.
Optional Details
showLatLngInput / showAutocompleteInput
Установите false, чтобы скрыть соответствующее поле ввода. По умолчанию оба включены.
{
"showAutocompleteInput": false,
"showLatLngInput": false
}
onChange
{
"onChange": "myFunction"
}
Задаёт callback, который вызывается после изменения любого поля ввода. Callback можно использовать, например, чтобы заполнить другое поле адресом из Autocomplete.
Callback вызывается с задержкой 300 мс. Первый параметр — eventType (mapDragged, latLngChanged или placeChanged). Второй — объект data с полями lat, lng и place.
function myFunction(eventType, data) { console.log('eventType', eventType); console.log('data.lat', data.lat); console.log('data.lng', data.lng); console.log('data.place', data.place); }
Дата и время
{
"format" : "%Y-%m-%d"
}
Поле даты и времени позволяет ввести дату. В format задаётся формат вывода даты в списке и на странице просмотра. В форке форматирование совместимо с Carbon 3 и выполняется через Voyager::formatDate.
Dropdown
{
"default" : "option1",
"options" : {
"option1": "Текст варианта 1",
"option2": "Текст варианта 2"
}
}
В default задаётся значение по умолчанию, если у записи нет значения. В options слева указывается значение, справа — отображаемый текст.
Изображения
{
"resize": {
"width": "1000",
"height": null
},
"quality" : "70%",
"upsize" : true,
"thumbnails": [
{
"name": "medium",
"scale": "50%"
},
{
"name": "small",
"scale": "25%"
},
{
"name": "cropped",
"crop": {
"width": "300",
"height": "250"
}
}
]
}
У поля изображения много параметров. Если ничего не указывать, изображение всё равно загрузится. Дополнительные параметры позволяют изменить размер, качество и создать миниатюры.
- resize — размеры изображения. Если
heightилиwidthравноnull, пропорции сохраняются по заданной стороне. В примере ширина1000пикселей, высота рассчитывается автоматически. - quality — качество сжатия в процентах. Обычно значения от 70 до 100% почти не ухудшают вид, но заметно уменьшают размер файла.
- upsize — работает только вместе с
resize. Если изображение меньше заданного размера, по умолчанию оно не увеличивается. Приupsize: trueизображение увеличивается до указанных размеров. - thumbnails — массив объектов миниатюр. Каждый объект содержит
nameиscale.nameдобавляется к имени файла: дляABC.jpgминиатюраmediumбудет называтьсяABC-medium.jpg.scale— процент от размеровresize, если они заданы. Вместоscaleможно использоватьcrop.
Number
{
"step" : 0.1,
"min" : 0,
"max" : 10,
"default": 1,
}
Стандартные атрибуты числового поля. Если step не задан, используется значение any.
TinyMCE
Чтобы настроить TinyMCE в Voyager, подключите дополнительный JS-файл в конфигурации.
В нём определите функцию:
function tinymce_init_callback(editor) { //... }
Если нужно изменить редактор до инициализации:
function tinymce_setup_callback(editor) { //... }
Дополнительные параметры инициализации TinyMCE можно объединить через JSON в деталях BREAD:
{
"tinymceOptions" : {
"name": "value"
}
}
Чтобы использовать TinyMCE вне стандартного шаблона rich_text_box, инициализируйте его так:
tinymce.init(window.voyagerTinyMCE.getConfig());
Все переменные, функции и параметры конфигурации описаны в документации TinyMCE.
Media Picker
Media Picker позволяет загружать, удалять и выбирать файлы прямо из медиа-менеджера. Поведение настраивается опциями:
{
"max": 10,
"min": 0,
"expanded": true,
"show_folders": true,
"show_toolbar": true,
"allow_upload": true,
"allow_move": true,
"allow_delete": true,
"allow_create_folder": true,
"allow_rename": true,
"allow_crop": true,
"allowed": [],
"hide_thumbnails": false,
"quality": 90,
"watermark": {
"source": "...",
"position": "top-left",
"x": 0,
"y": 0
}
}
| Параметр | Описание | Тип | По умолчанию |
|---|---|---|---|
base_path |
Стартовый путь относительно файловой системы | String | /bread-slug/ |
rename |
Переименовать загруженные файлы по строке или выражению | String | Исходное имя |
delete_files |
Удалять файлы при удалении записи BREAD. Используйте осторожно | bool | false |
show_as_images |
Показывать сохранённые данные как изображения в списке | bool | false |
min |
Минимальное количество выбираемых файлов | int | 0 |
max |
Максимальное количество выбираемых файлов. 0 — без ограничений |
int | 0 |
expanded |
Разворачивать медиа-пикер по умолчанию | bool | true |
show_folders |
Показывать вложенные папки | bool | true |
show_toolbar |
Показывать всю панель инструментов | bool | false |
allow_upload |
Разрешить загрузку файлов | bool | true |
allow_move |
Разрешить перемещение файлов и папок | bool | true |
allow_delete |
Разрешить удаление файлов | bool | true |
allow_create_folder |
Разрешить создание папок | bool | true |
allow_rename |
Разрешить переименование файлов. Используйте осторожно | bool | true |
allow_crop |
Разрешить обрезку изображений | bool | true |
hide_thumbnails |
Скрывать известные миниатюры и показывать их дочерними элементами исходного изображения | bool | true |
quality |
Качество загружаемых изображений и миниатюр | int | 90 |
allowed |
Разрешённые типы файлов. Пустой объект означает все типы. Файлы других типов не отображаются | Object | [] |
Разрешённые типы
Чтобы разрешить только определённые типы, передайте MIME-типы в allowed:
["image", "audio", "video"]
или
["image/jpeg", "image/png", "image/bmp"]
Выражения
В base_path и rename можно использовать подстановки:
{pk}— первичный ключ записи (только дляbase_path);{uid}— ID текущего авторизованного пользователя;{date:format}— текущая дата в форматеformat, например{date:d.m.Y};{random:10}— случайная строка из N символов.
Пример base_path:
{
"base_path": "/my-bread/{pk}/{date:Y}/{date:m}/"
}
Водяной знак
Водяной знак добавляется к загруженным изображениям. Источник задаётся относительно диска хранения Voyager:
{
"watermark": {
"source": "watermark.png",
"position": "bottom-left",
"x": 0,
"y": 0,
"size": 15
}
}
- position — положение водяного знака:
top-left(по умолчанию),top,top-right,left,center,right,bottom-left,bottom,bottom-right; - x — смещение по оси X, по умолчанию
0; - y — смещение по оси Y, по умолчанию
0; - size — размер в процентах от изображения, по умолчанию
15.
Миниатюры
Для каждого загруженного изображения можно создавать миниатюры. Доступны три типа.
Fit
Fit совмещает обрезку и изменение размера, чтобы получить миниатюру нужных размеров. Обязателен width, необязательны height и position.
{
"thumbnails": [
{
"type": "fit",
"name": "fit-500",
"width": 500,
"height": 500,
"position": "center"
}
]
}
Crop
Crop обрезает изображение по заданным размерам и позиции. Обязательны width и height, необязательны x и y.
{
"thumbnails": [
{
"type": "crop",
"name": "crop-500-500",
"width": 500,
"height": 500,
"x": 50,
"y": 50,
}
]
}
Resize
Resize изменяет размер изображения. Нужно передать width и/или height.
{
"thumbnails": [
{
"type": "resize",
"name": "resize-500",
"width": 500,
"upsize": true,
},
{
"type": "resize",
"name": "resize-500-500",
"width": 500,
"height": 500
},
{
"type": "resize",
"name": "resize-500",
"width": null,
"height": 500
}
]
}
Водяной знак можно добавить и к миниатюрам. Задайте параметры watermark у родительского элемента и установите watermark: true для нужных миниатюр.
Маршрутизация
После установки Voyager в routes/web.php появляются маршруты:
Route::group(['prefix' => 'admin'], function () { Voyager::routes(); });
Здесь рендерятся маршруты Voyager. Префикс admin можно изменить или задать другие параметры группы, например middleware или domain.
При создании BREAD и указании slug запись доступна по адресу:
URL/admin/slug-name
Пример: для таблицы products со slug products адрес будет:
URL/admin/products
Если включён параметр
bread.add_menu_item(по умолчаниюtrue), пункт меню для нового BREAD создаётся автоматически. Если ссылки нет, добавьте её вручную через конструктор меню.
Медиа-менеджер
Voyager включает полноценный медиа-менеджер: загрузка, переименование и удаление файлов, создание папок, перемещение файлов и папок. В нём доступны все основные операции файлового менеджера.
Файлы можно перетаскивать на кнопку Upload, чтобы загрузить несколько файлов сразу.
Медиа-менеджер умеет создавать миниатюры и добавлять водяные знаки через конфигурацию. Формат параметров описан в разделе Media Picker.
Размер загружаемых файлов Если при загрузке больших файлов возникает ошибка, проверьте настройки PHP
upload_max_filesizeиpost_max_size.
Меню и конструктор меню
С Voyager можно создавать меню для приложения. Сама админ-панель использует конструктор меню для навигации слева.
Текущие меню доступны в Tools → Menu Builder. Меню можно добавлять, редактировать и удалять. Можно создать отдельные меню для шапки, сайдбара и подвала сайта.
Чтобы добавить пункты, нажмите кнопку конструктора у нужного меню. Откроется страница добавления, редактирования и удаления пунктов.
После настройки меню его можно вывести в приложении. Например, для меню main:
menu('main');
Будет выведен нестилизованный список <ul>. Если используется Bootstrap, передайте второй аргумент:
menu('main', 'bootstrap');
Можно указать собственный Blade-шаблон. Например, файл resources/views/my_menu.blade.php:
<ul>
@foreach($items as $menu_item)
<li><a href="{{ $menu_item->link() }}">{{ $menu_item->title }}</a></li>
@endforeach
</ul>
Вызов:
menu('main', 'my_menu');
Меню как JSON
Если меню нужно не вывести, а получить массив, передайте _json вторым параметром:
menu('main', '_json')
Метод вернёт коллекцию пунктов меню.
Менеджер базы данных
Voyager предоставляет инструменты для просмотра, создания, редактирования и удаления таблиц базы данных. Для любой таблицы можно добавить BREAD-функциональность.
В админ-панели откройте Tools → Database. Вы увидите все таблицы базы данных. Кнопка Create a New Table создаёт новую таблицу. Новые таблицы используют charset, заданный в соединении с базой данных по умолчанию.
Если нажать на имя таблицы, откроется текущая схема. Кнопки View, Edit и Delete выполняют соответствующие действия с таблицей.
Для любой таблицы можно добавить BREAD. Если BREAD уже создан, его можно изменить или удалить.
В форке интроспекция и изменение схемы работают без Doctrine DBAL, включая SQLite.
Настройки
Раздел Settings позволяет хранить настройки сайта. Например, изображение логотипа или текстовый заголовок главной страницы.
Настройки группируются. Если создать настройку в группе site с ключом title, её можно использовать в любом месте приложения:
<?php echo setting('site.title');
Или в Blade:
{{ setting('site.title') }}
Так можно добавлять любые настройки в Voyager и использовать их в приложении.
Compass
Compass — быстрый раздел со ссылками, шрифтами, запуском команд и просмотром логов.
- На первой вкладке собраны ссылки на ресурсы и все шрифты, доступные в Voyager.
- На вкладке Command можно выполнять Artisan-команды прямо из Voyager.
- На вкладке Logs отображаются логи приложения.
Роли и разрешения
Voyager включает роли и разрешения. У каждого пользователя есть роль, а у роли — набор разрешений.
В админ-панели роли можно добавлять, редактировать и удалять. При редактировании роли задаются разрешения BREAD.
Начиная с версии 1.0 авторизация Voyager следует подходу Laravel. Проверка прав выполняется так:
// через объект пользователя $canViewPost = $user->can('read', $post); $canViewPost = Auth::user()->can('read', $post); // через контроллер $canViewPost = $this->authorize('read', $post);
Стандартные разрешения:
browse_admin— доступ к админ-панели Voyager;browse_database— доступ к разделу базы данных;browse_bread— доступ к разделу BREAD;browse_media— доступ к разделу медиа;browse_menu— доступ к разделу меню;browse_settings— доступ к разделу настроек;read_settings— просмотр настройки;edit_settings— редактирование настройки;add_settings— добавление настройки;delete_settings— удаление настройки.
Для каждого созданного BREAD можно включить Generate permissions. Тогда будут созданы разрешения browse, read, edit, add и delete.
Пример: для BREAD таблицы products создаются ключи browse_products, read_products, edit_products, add_products и delete_products.
Если пункт меню связан с BREAD, проверяется разрешение
browse. Например, для пунктаPostsпроверяетсяbrowse_posts. Если у пользователя нет разрешения, пункт меню скрывается.
Разрешения для собственной страницы
Если нужно ограничить доступ к собственной странице, используйте разрешения. Это работает, когда slug идёт сразу после /admin/. Для страницы вида /admin/sub/foo пункт меню не будет скрыт.
Создание разрешения
Создайте разрешение в таблице permissions (например, через BREAD; модель — TCG\Voyager\Models\Permission). Колонка table_name должна быть null. Колонка key должна иметь вид browse_slug, где slug — slug страницы. Например, для страницы /admin/create_bill создайте разрешение browse_create_bill.
Назначение роли
Отметьте разрешение для нужных ролей на странице admin/roles. В примере появится чекбокс «Browse Create Bill». Если у пользователя нет разрешения, пункт меню со страницей будет скрыт.
Настройка контроллера
Создайте собственный gate:
Gate::define('browse_create_bill', function ($user) { return $user->hasPermission('browse_create_bill'); });
Используйте authorize в контроллере:
public function index() { $this->authorize('browse_create_bill'); //..
Если используете собственный guard, добавьте его в контроллер:
/** * Get the guard to be used during authentication. * * @return \Illuminate\Contracts\Auth\StatefulGuard */ protected function guard() { return Auth::guard(app('VoyagerGuard')); }
Разрешения в Blade
Проверка разрешений в шаблонах:
@can('browse', $post) I can browse posts @endcan
С условием else:
@can('browse', $post) I can browse posts @else I cannot browse posts @endcan
Журнал активности
В форк встроен журнал действий администраторов. Он отвечает на вопросы:
- кто выполнил действие;
- когда оно произошло;
- какое действие выполнено;
- над каким объектом;
- с каким результатом.
Журнал фиксирует изменения и удаления записей, загрузку и удаление файлов, изменения настроек, назначение ролей и разрешений, вход и выход пользователей, отказы в доступе, клонирование записей, работу с меню, Галереями и BREAD.
Что записывается
Для изменения записи сохраняются имена изменённых полей. Старые и новые значения полей в журнал не попадают. Для удаления сохраняются тип и идентификатор объекта, без снимка содержимого. Для файлов сохраняются диск, относительный путь и размер, но не содержимое файла.
Каждая запись содержит:
event_uuid— уникальный идентификатор события;occurred_atиrecorded_at— время события и время записи в UTC;category— категория (content,media,access,configuration,auth);event— код события, напримерrecord.updated;result— результат (success,failure,denied,partial);actor_typeиactor_id— тип и идентификатор автора действия;subject_typeиsubject_id— тип и идентификатор объекта;resource— раздел админки или BREAD;changed_fields— только имена изменённых полей;metadata— безопасные служебные данные события;request_idиoperation_id— идентификаторы запроса и операции;source— источник (admin,api,console,job);ip_address,route_nameиschema_version.
Установка
Миграция журнала входит в пакет и выполняется вместе с остальными миграциями Voyager:
php artisan migrate
Команда установки создаёт разрешения и пункт меню:
php artisan voyager:activity:install
Она добавляет разрешения:
browse_activity_logs— просмотр журнала;browse_activity_log_context— просмотр технического контекста (IP-адрес, route name, request ID, operation ID).
Оба разрешения выдаются роли admin. Пункт меню «Журнал активности» создаётся в административном меню. Команда безопасна для повторного запуска: существующие разрешения и пункт меню не дублируются.
php artisan voyager:install вызывает установку журнала автоматически.
Раздел в админке
Журнал доступен по адресу /admin/activity. Список поддерживает фильтры:
- период (
from,to); - автор (
actor_id); - категория, событие и результат;
- раздел (
resource); - тип и идентификатор объекта;
- идентификатор операции.
Страница события показывает изменённые поля и безопасные метаданные. Технический контекст виден только при разрешении browse_activity_log_context.
Конфигурация
Опубликуйте конфигурацию:
php artisan vendor:publish --provider="TCG\Voyager\VoyagerServiceProvider" --tag=voyager-activity-config
Параметры файла config/voyager-activity.php:
enabled— включает журнал; по умолчаниюtrue;retention_days— срок хранения в днях; по умолчанию180;store_ip— сохранять ли IP-адрес;max_details_bytes— максимальный размерchanged_fieldsиmetadataв байтах;page_sizeиmax_page_size— размер страницы журнала;cleanup_chunk_size— размер порции при очистке;fallback_log_days— срок хранения резервного лога;excluded_fields— поля, которые не считаются изменёнными;excluded_resources— разделы, которые нужно исключить;custom_events— собственные события и разрешённые ключи метаданных.
Пример:
return [ 'enabled' => env('VOYAGER_ACTIVITY_ENABLED', true), 'retention_days' => 365, 'store_ip' => false, 'max_details_bytes' => 2048, 'custom_events' => [ 'report.exported' => ['format', 'rows'], ], ];
Очистка старых записей
Удалите записи старше срока хранения:
php artisan voyager:activity:prune
Проверьте количество без удаления:
php artisan voyager:activity:prune --dry-run
Переопределите срок хранения:
php artisan voyager:activity:prune --days=90
Команда удаляет записи порциями и не запускает вторую очистку одновременно. Добавьте её в планировщик:
$schedule->command('voyager:activity:prune')->daily();
Собственные события
Зарегистрируйте событие в custom_events и укажите только безопасные ключи метаданных:
'custom_events' => [ 'report.exported' => ['format', 'rows'], ],
Запишите событие через ActivityRecorder:
use TCG\Voyager\Activity\ActivityRecorder; app(ActivityRecorder::class)->recordEventSafe( 'report.exported', 'success', null, 'reports', [], ['format' => 'csv', 'rows' => 120], 'report', (string) $report->id );
recordEventSafe() не прерывает основное действие, если журнал недоступен. Ошибка записывается в storage/logs/voyager-activity-fallback.log. Метод recordEvent() выбрасывает исключение и подходит только для случаев, когда запись в журнал обязательна.
Ограничения безопасности
- Значения полей, содержимое файлов, пароли, токены и тела запросов не сохраняются.
- Для изменений доступны только имена полей.
- Для удалений доступны только тип и идентификатор объекта.
- Метаданные проходят проверку по белому списку ключей для каждого события.
- Недопустимые ключи, опасные строки и абсолютные пути отклоняются.
- IP-адрес сохраняется только при
store_ip = trueи только в валидном формате. - При отказе в доступе создаётся событие
access.deniedс результатомdenied. - Если запись в журнал не удалась, административное действие не откатывается.
Helper-методы
Voyager предоставляет helper-функции, которые упрощают разработку.
URL миниатюр
Voyager создаёт миниатюры для поля изображения, если заданы дополнительные параметры поля.
Чтобы вывести миниатюру или получить её URL, подключите трейт Resizable в модели:
use TCG\Voyager\Traits\Resizable; class Post extends Model { use Resizable; }
Одно изображение
@foreach($posts as $post) <img src="{{Voyager::image($post->thumbnail('small'))}}" /> @endforeach
Или с именем поля изображения (по умолчанию image):
@foreach($posts as $post) <img src="{{Voyager::image($post->thumbnail('small', 'photo'))}}" /> @endforeach
Несколько изображений
@foreach($posts as $post) $images = json_decode($post->images); @foreach($images as $image) <img src="{{ Voyager::image($post->getThumbnail($image, 'small')) }}" /> @endforeach @endforeach
Мультиязычность
Voyager поддерживает несколько языков для моделей. Сначала выполните настройку.
Настройка
Укажите locales и включите мультиязычность в config/voyager.php:
'multilingual' => [ 'enabled' => true, 'default' => 'en', 'locales' => [ 'en', 'da', ], ],
Подключите трейт Translatable в модели и перечислите переводимые атрибуты:
use TCG\Voyager\Traits\Translatable; class Post extends Model { use Translatable; protected $translatable = ['title', 'body']; }
После этого в BREAD Pages появится выбор языка.
Использование
Eager-load переводов
// Загружает все переводы $posts = Post::with('translations')->get(); // Загружает все переводы $posts = Post::all(); $posts->load('translations'); // Загружает переводы для текущей локали и fallback-локали $posts = Post::withTranslations()->get(); // Загружает переводы для указанных локалей и fallback-локали $posts = Post::withTranslations(['en', 'da'])->get(); // Загружает перевод для локали da и fallback-локали $posts = Post::withTranslation('da')->get(); // Загружает перевод для текущей локали и fallback-локали $posts = Post::withTranslation()->get();
Значение языка по умолчанию
echo $post->title;
Переведённое значение
echo $post->getTranslatedAttribute('title', 'locale', 'fallbackLocale');
Если локаль не указана, используется текущая локаль приложения. Можно передать свою локаль строкой. Если fallbackLocale не указана, используется fallback-локаль приложения. Можно передать свою строку. Чтобы отключить fallback, передайте false. Если значение не найдено ни для локали, ни для fallback, атрибут становится null.
Перевод всей модели
$post = $post->translate('locale', 'fallbackLocale'); echo $post->title; echo $post->body; // Метод translate можно вызвать на коллекции Eloquent, // чтобы перевести все модели в коллекции. $posts = $posts->translate('locale', 'fallbackLocale'); echo $posts[0]->title;
Правила для локали и fallback такие же, как выше. Если значение не найдено, атрибут становится null.
Проверка переводимости модели
// со строкой if (Voyager::translatable(Post::class)) { // модель переводима } // с объектом модели или коллекции if (Voyager::translatable($post)) { // модель переводима }
Установка переводов атрибутов
$post = $post->translate('da'); $post->title = 'foobar'; $post->save();
Будет обновлён или создан перевод title для локали da. Если изменяемый атрибут не переводимый, изменения попадут напрямую в модель, то есть перезапишут значение языка по умолчанию.
Поиск по переводам
Для поиска по переведённому значению используйте whereTranslation. Например, для поиска по slug страницы:
$page = Page::whereTranslation('slug', 'my-translated-slug'); // То же самое $page = Page::whereTranslation('slug', '=', 'my-translated-slug'); // Искать только в локалях en, de и в локали по умолчанию $page = Page::whereTranslation('slug', '=', 'my-translated-slug', ['en', 'de']); // Искать только в локалях en и de $page = Page::whereTranslation('slug', '=', 'my-translated-slug', ['en', 'de'], false);
Параметры whereTranslation:
field— поле поиска;operator— оператор, по умолчанию=. Может быть значением, как в where;value— искомое значение;locales— массив локалей.nullозначает поиск по всем локалям;default— искать ли также в значении по умолчанию. По умолчаниюtrue.
Переопределение файлов
Переопределение представлений BREAD
Представления BREAD можно переопределить для одного BREAD, создав папку resources/views/vendor/voyager/slug-name, где slug-name — slug таблицы. Доступны четыре файла:
browse.blade.phpedit-add.blade.phpread.blade.phporder.blade.php
Или переопределите представления для всех BREAD, создав эти файлы в resources/views/vendor/voyager/bread.
Переопределение кнопки отправки
Кнопку отправки можно изменить без переопределения всего edit-add.blade.php, расширив секцию submit-buttons:
@extends('voyager::bread.edit-add') @section('submit-buttons') @parent <button type="submit" class="btn btn-primary save">Save And Publish</button> @endsection
Собственные контроллеры
Контроллер для одного BREAD можно переопределить, создав класс, который наследует контроллер Voyager:
<?php namespace App\Http\Controllers; class VoyagerCategoriesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController { //... }
Затем в настройках BREAD укажите полное имя класса в поле Controller Name. После этого можно переопределять любые методы VoyagerBaseController.
Переопределение контроллеров Voyager
Используйте только при необходимости Мы не рекомендуем переопределять все контроллеры: изменения в будущих версиях не попадут в вашу копию.
Измените namespace в config/voyager.php:
/* |-------------------------------------------------------------------------- | Controllers config |-------------------------------------------------------------------------- | | Here you can specify voyager controller settings | */ 'controllers' => [ 'namespace' => 'App\\Http\\Controllers\\Voyager', ],
Затем выполните:
php artisan voyager:controllers
Voyager будет использовать дочерние контроллеры, созданные в App/Http/Controllers/Voyager.
Переопределение моделей Voyager
Модели Voyager можно заменить. Добавьте в метод register класса AppServiceProvider:
Voyager::useModel($name, $object);
Где name — имя класса модели, а object — полное имя вашей модели. Например:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Events\Dispatcher; use TCG\Voyager\Facades\Voyager; class AppServiceProvider extends ServiceProvider { public function boot() { Voyager::useModel('DataRow', \App\DataRow::class); } // ... }
Создайте модель, наследующую оригинал. Для DataRow:
<?php namespace App; class DataRow extends \TCG\Voyager\Models\DataRow { // ... }
Если у заменяемой модели есть BREAD, откройте настройки BREAD и замените Model Name на полное имя вашего класса.
Переопределение маршрутов
Любые маршруты Voyager можно переопределить, описав свои маршруты после Voyager::routes(). Например, чтобы заменить LoginController:
Route::group(['prefix' => 'admin'], function () { Voyager::routes(); // Ваши переопределения Route::post('login', ['uses' => 'MyAuthController@postLogin', 'as' => 'postlogin']); });
Дополнительные CSS и JS
В последних версиях дополнительные CSS и JS подключаются к master-шаблону Voyager без копирования и изменения самого шаблона. Файлы добавляются после ресурсов Voyager, поэтому могут переопределять стили и поведение.
Настройка выполняется в config/voyager.php:
// Здесь можно указать дополнительные ресурсы для master.blade 'additional_css' => [ //'css/custom.css', ], 'additional_js' => [ //'js/custom.js', ],
Путь передаётся в функцию Laravel
asset().
Мягкое удаление
Этот раздел помогает включить мягкое удаление моделей в Voyager. Подробности — в документации Laravel.
Настройка таблицы
При создании таблицы в менеджере базы данных выберите Add Soft Deletes, а при добавлении BREAD укажите имя модели. После этого достаточно изменить файл модели.
Изменение модели
Обычная модель выглядит так:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class YourModelName extends Model { }
Измените её:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class YourModelName extends Model { use SoftDeletes; protected $casts = [ 'deleted_at' => 'datetime', ]; }
Теперь при удалении записи она не удаляется физически: в колонку deleted_at записывается текущая дата и время.
Дополнительные атрибуты связей
Начиная с Voyager 1.1 в связях можно показывать дополнительные атрибуты.
Например, Post связан с Author, и нужно вывести полное имя пользователя. Сначала определите аксессор:
public function getFullNameAttribute() { return "{$this->first_name} {$this->last_name}"; }
Затем укажите аксессор в модели:
public $additional_attributes = ['full_name'];
Теперь full_name можно выбрать в настройках связи.
Свои formfields
Добавить новый formfield в Voyager просто. В примере ниже создаётся числовое поле (оно уже есть в Voyager по умолчанию).
Создайте класс NumberFormField в проекте:
<?php namespace App\FormFields; use TCG\Voyager\FormFields\AbstractHandler; class NumberFormField extends AbstractHandler { protected $codename = 'number'; public function createContent($row, $dataType, $dataTypeContent, $options) { return view('formfields.number', [ 'row' => $row, 'options' => $options, 'dataType' => $dataType, 'dataTypeContent' => $dataTypeContent ]); } }
Переменная codename используется в выпадающем списке конструктора BREAD. Метод createContent возвращает представление для отображения поля.
Создайте представление:
<input type="number"
class="form-control"
name="{{ $row->field }}"
data-name="{{ $row->display_name }}"
@if($row->required == 1) required @endif
step="any"
placeholder="{{ isset($options->placeholder)? old($row->field, $options->placeholder): $row->display_name }}"
value="@if(isset($dataTypeContent->{$row->field})){{ old($row->field, $dataTypeContent->{$row->field}) }}@else{{old($row->field)}}@endif">
В представлении можно добавлять любую логику.
Зарегистрируйте formfield в service provider, например в AppServiceProvider:
<?php namespace App\Providers; use TCG\Voyager\Facades\Voyager; use App\FormFields\NumberFormField; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { //.. public function register() { Voyager::addFormField(NumberFormField::class); } }
Координаты в модели
Voyager умеет хранить координаты и выбирать их на карте. Колонка таблицы должна иметь тип GEOMETRY или POINT.
Подключите трейт Spatial в модели и укажите колонку:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use TCG\Voyager\Traits\Spatial; class Category extends Model { use Spatial; protected $spatial = ['your_column']; }
Затем в настройках BREAD установите для поля тип Coordinates. Появится карта для выбора координат.
Укажите Google Maps API-ключ в конфигурации. Там же задаётся положение карты по умолчанию.
Получение координат
$model->getCoordinates();
Метод возвращает массив с lat (широта) и lng (долгота).
BREAD-аксессоры
Иногда атрибут нужно форматировать только для одного или нескольких действий BREAD. Например, есть поле name, и на странице списка нужно показать текст, если поле пустое:
<?php public function getNameBrowseAttribute() { return $this->name ?? 'Empty'; }
Если поле пустое, будет показано Empty, иначе — значение.
Аналогично для других действий:
<?php public function getNameReadAttribute() { // } public function getNameEditAttribute() { // } public function getNameAddAttribute() { // }
Собственный guard
Начиная с Voyager 1.2 можно определить собственный guard, который используется во всём Voyager. Привяжите имя guard к VoyagerGuard.
Сначала определите guard по документации Laravel. Затем в методе register класса AuthServiceProvider добавьте:
$this->app->singleton('VoyagerGuard', function () { return 'your-custom-guard-name'; });
Теперь вместо стандартного guard используется указанный.
Пример: отдельная модель и таблица для администраторов
Создайте таблицу admins:
<?php Schema::create('admins', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('role_id')->unsigned()->nullable(); $table->string('name'); $table->string('email')->unique(); $table->string('avatar')->nullable()->default('users/default.png'); $table->string('password')->nullable(); $table->string('remember_token')->nullable(); $table->text('settings')->nullable()->default(null); $table->timestamps(); $table->foreign('role_id')->references('id')->on('roles'); });
Создайте модель, наследующую модель пользователя Voyager:
<?php namespace App; class Admin extends \TCG\Voyager\Models\User { }
Создайте guard admin в config/auth.php:
'guards' => [ 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], // ... ],
И провайдер пользователей admins:
'providers' => [ 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], // ... ],
Укажите новый guard в AppServiceProvider.php:
public function register() { $this->app->singleton('VoyagerGuard', function () { return 'admin'; }); }
BREAD пользователей по-прежнему редактирует
users, а неadmins. Если нужно управлять администраторами, создайте BREAD для таблицыadmins.
Кнопки действий
Кнопки действий показываются при просмотре BREAD рядом с каждой строкой.
Создайте класс действия, наследующий AbstractAction, например app/Actions/MyAction.php:
<?php namespace App\Actions; use TCG\Voyager\Actions\AbstractAction; class MyAction extends AbstractAction { public function getTitle() { return 'My Action'; } public function getIcon() { return 'voyager-eye'; } public function getPolicy() { return 'read'; } public function getAttributes() { return [ 'class' => 'btn btn-sm btn-primary pull-right', ]; } public function getDefaultRoute() { return route('my.route'); } }
Зарегистрируйте действие в методе boot() класса app/Providers/AppServiceProvider.php:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Events\Dispatcher; use TCG\Voyager\Facades\Voyager; class AppServiceProvider extends ServiceProvider { public function boot() { Voyager::addAction(\App\Actions\MyAction::class); } }
После этого кнопка появится при просмотре любого BREAD.
Показ и скрытие действий
Чтобы показывать действие только для определённых типов данных, реализуйте shouldActionDisplayOnDataType():
<?php public function shouldActionDisplayOnDataType() { return $this->dataType->slug == 'posts'; }
Чтобы управлять показом для каждой строки, реализуйте shouldActionDisplayOnRow($row):
<?php public function shouldActionDisplayOnRow($row) { return $row->id > 10; }
Массовые действия
Массовые действия вызываются для нескольких записей модели. Чтобы действие стало массовым, реализуйте метод:
<?php public function massAction($ids, $comingFrom) { // Do something with the IDs return redirect($comingFrom); }
Решение проблем
HTTPS и изображения
Симптом: при открытии сайта по HTTPS изображения Voyager не загружаются.
Причина: URL изображений создаются так:
Storage::disk(config('voyager.storage.disk'))->url($file);
Если voyager.storage.disk равен public, а диск public используется по умолчанию, в конфигурации диска задан абсолютный URL:
'url' => env('APP_URL').'/storage',
Он использует APP_URL без HTTPS и строит абсолютный URL.
Решение: уберите env('APP_URL') из конфигурации диска public. Тогда будет формироваться относительный URL, использующий текущий домен и протокол.
Если нужен абсолютный URL, оберните вызов Voyager::image('...') в asset():
asset(Voyager::image('...'))
Такой вариант вернёт текущий протокол, домен и правильный путь к изображению.
Missing required parameter
Симптом: появляется страница ошибки:
Missing required parameters for [Route...]
Причина: возможны две причины:
- В таблице нет первичного ключа.
- Первичный ключ есть, но он называется не
id.
Решение:
- Создайте поле
idв таблице. - Укажите первичный ключ в модели:
protected $primaryKey = 'your_primary_key';
Соблюдайте соглашения моделей Eloquent.
Разработка и тестирование
Проверка пакета перед релизом:
composer validate vendor/bin/phpunit
Актуальный набор тестов: 140 тестов, 937 утверждений на PHP 8.4. Отдельно проверена установка в чистом приложении Laravel 13.39.0:
php artisan voyager:install --with-dummy
Проверены вход, панель управления, BREAD CRUD, редактор BREAD, менеджер базы данных, конструктор меню, ресурсы расширения, клонирование, переводы, изображения и проверка капчи.
История изменений
Подробная история — в CHANGELOG.md.
Версионирование
Проект следует semver. Изменения без обратной совместимости выпускаются в новой минорной или мажорной версии. Исправления ошибок — в патч-релизах.
Лицензия
Voyager распространяется по лицензии MIT. Подробности — в файле license.
Благодарности
Voyager proudly supported by our amazing sponsors: