Vesp 3.0
Совершенно неожиданно вышла новая версия Vesp - 3.0.
Как известно, Vesp состоит из Vue, Eloquent, Slim и Phinx. 3 части названия состовляет PHP бэкенд (пакет vesp/core), оставшаяся 1 часть - это фронтенд на Vue (пакет @vesp/frontend).
В новой версии обновлены они оба, но фронтенду досталось сильно больше из-за перехода на Vue 3.
Vesp/Core
Минимальная версия теперь PHP 8.1, прекрасно поддерживается и текущая стабильная 8.3.
Зависимости обновлены до последних версий: Eloquent 10, JWT 6, PhpUnit 10.
Во всех классах, где это возможно, добавлены типы переменным. Например, было так
abstract class ModelController extends Controller
{
/** @var string $model */
protected $model;
protected $primaryKey = 'id';
protected $maxLimit = 1000;
А стало вот так
abstract class ModelController extends Controller
{
protected string $model;
protected string|array $primaryKey = 'id';
protected int $maxLimit = 1000;
Если вы будете обновлять на новую версию старый проект, то IDE вам обязательно должно подчеркнуть ошибки в старых контроллерах и моделях - просто укажите правильные типы, ничего сложного.
Для более удобного расширения контроллеров создан отдельный метод инициализации. Раньше для переопределения основного метода __invoke надо было прописывать кучу всего обязятельного, и только где-то в конце менять нужное, а теперь вот так:
class MyController extends Controller
{
public function __invoke(RequestInterface $request, ResponseInterface $response): ResponseInterface
{
// Выставление $this->request, $this->response, $this->route, $this->user
// и свойств, доступных через $this->getProperties()
$this->initController($request, $response);
// Дальше ваша особенная логика
}
}
Контроллеры теперь отдают не красиво распечатанный JSON, а обычный в одну строку - так расходуется меньше трафика на ответы от сервера. Флаг JSON_PRETTY_PRINT в ответах заменён на JSON_THROW_ON_ERROR.
В контроллере изображений добавлена поддержка композитного ключа. Везде эта поддержка была, а в картинках почему-то не было.
Добавил поддержку нового имени для куки авторизации auth:token, старая auth._token.local тоже осталась. Она была от фронтового пакет @nuxtjs/auth, в новой версии фронтенда его нет, так что имя куки стало проще.
Очень много изменений было в работе с файлами. Основное отличие - теперь файловые методы привязаны не к файловой системе, а к собственно модели, через новый trait FileModel.
Все методы, типа uploadFile, getFile, getSaveName теперь в нём, а значит, что вы можете создать сколько угодно моделей для разной логики работы с файлами.
Файловая система может быть одна, а вот логика наименования файлов в ней зависеть от модели. Лично мне так кажется гораздо более удобно и логичнее.
Добавлена композитная модель UserFile, как пример использования нового трейта. Довольно часто в проектах нужно загружать какие-то файлы юзерам, так что лишним не будет.
Улучшена работа с большими файлами: и загрузка и отдача. Автоматическое получение размеров картинок теперь работает только для файлов <= 50 мегабайт.
composer.json и composer.lock переехали внутрь директории core. Раньше были снаружи, что как-то не согласуется с полным разделением бэкенда и фронтенда.
Тесты теперь можно быстренько прогнать через Docker.
git clone https://github.com/bezumkin/vesp-core.git
cd ./vesp-core
docker-compose up
Вам это не нужно, а мне приятно.
@Vesp/Frontend
Здесь было гораздо больше изменений, благодаря переходу на:
- Vue 3
- Nuxt 3
- Typescript
- Bootstrap 5 SCSS
- Bootstrap Vue Next
- Pinia вместо Vuex
- Vue Toastification для всплывающих уведомлений
Благодаря новому композитному синтаксису пришлось переписать вообще всё. Плюс, для нового Nuxt нет многих старых привычных модулей, например авторизации и подключения Font Awesome - и мне пришлось написать их самостоятельно.
Как и раньше, @vesp/frontend является модулем для Nuxt, нужно просто подключить его и указать настройки. Работает поддержка типов, всё экспортируется, подсказки в IDE вам помогут:
Благодаря новым возможностям Nuxt больше нет разделения на 2 приложения: admin и site. Админка теперь это просто вложенные странички сайта, которые не рендерятся на сервере. А весь остальной сайт рендерится.
Соответственно, нет нужды и запускать 2 процесса Nuxt через concurrently - меньше тратится ресурсов.
Я крайне не советую обновлять старые проекты на новую версию, это равносильно переписыванию всего с нуля. Если, конечно, именно такой задачи у вас и не стоит.
Bootstrap Vue Next сейчас в очень активной разработке, и похоже будет там еще долго. Но я всё равно смог с ним подружиться и наладить нормальную работу. Поэтому версия пакета будет жёстко фиксироваться, чтобы он сам не обновлялся и не ломал уже работающее.
Я постарался, как мог, прописать поддержку собственных типов Vesp, вы увидете это в исходниках. Рекомендую пользоваться, чтобы делать меньше ошибок.
Typescript не является обязательным, он не участвует в компиляции и его ошибки ни на что не влияют, они должны просто помогать вам писать более правильный код.
SCSS файлы так же экспортируются модулем, вы можете их легко подключить в своих стилях:
@import 'bootstrap-scss/bootstrap';
@import '@vesp/frontend/assets/components';
@import '@vesp/frontend/assets/toast';
@import '@fortawesome/fontawesome-svg-core/styles.css';
Понятное дело, что там всё завязано на Bootstrap и вы можете переопределить переменные SCSS.
На данный момент модуль добавляет следующие компоненты:
- vesp-table - компонент для вывода таблиц админки
- vesp-modal - модалка с поддержкой отправки форм и обновления соответствующей таблицы
- vesp-fa - иконки FontAwesome
- vesp-change-locale - компонент для переключения языка
- vesp-input-alias - компонент для ввода адресов страниц, использует slugify
- vesp-input-combo-box - ввод с автодополнением через запросы к API
- vesp-input-date-picker - ввод даты или диапазона дат, использует vue-datepicker-next
- vesp-input-password - ввод пароля с кнопочкой "показать\скрыть"
- vesp-input-remote-links - ввод JSON массива "название сервиса-адрес", например для ссылок на соцсети
- vesp-input-text-mask - ввод телефонов или других данных по маске, использует text-mask-core
В основном эти компоненты расширяют что-то из BootstrapVue.
Также есть разные полезные функции:
- useGet, usePost, usePut, usePatch, useDelete - простые запросы в API с поддержкой авторизации и безо всяких наворотов, вроде сохранения состояния и кэширования.
- useApi - тоже самое, но с возможностью более тонкого указания параметров - функции выше используют эту функцию внутри себя
- useCustomFetch - а это как раз запрос в API со всеми наворотами, плюс поддержка авторизации. Подробнее читать в документации Nuxt
try {
const data = await useGet('user/profile')
console.log(data)
} catch (e) {
console.error(e)
}
Дальше работа с авторизацией через композит useAuth:
const {loggedIn, token, user, login, logout, loadUser, setToken} = useAuth()
console.log(loggedIn.value, user.value, token.value)
Экспортируются переменные:
- loggedIn - computed переменная со статусом авторизации, внутри true или false.
- token - ref на куку с токеном, может быть строкой или undefined.
- user - ref на юзера, может быть объектом типа VespUser или undefined.
И полезные функции:
- login(username, password) - авторизация
- logout() - выход и удаление токена на сервере
- loadUser() - загрузка профиля с сервера
- setToken(string) - выставление нового токена в куку авторизации
Простейший пример авторизации:
<template>
<div v-if="loggedIn">
<pre>{{ user }}</pre>
<b-button @click="() => logout()">Logout</b-button>
</div>
<div v-else>
<b-form @submit.prevent="onSubmit">
<b-form-group label="Username">
<b-form-input v-model="form.username" required />
</b-form-group>
<b-form-group label="Password">
<vesp-input-password v-model="form.password" required />
</b-form-group>
<b-button type="submit">Submit</b-button>
</b-form>
</div>
</template>
<script setup lang="ts">
const {loggedIn, user, login, logout} = useAuth()
const form = ref({username: '', password: ''})
async function onSubmit() {
try {
await login(form.value.username, form.value.password)
form.value = {username: '', password: ''}
} catch (e) {
console.error(e)
}
}
</script>
Дальше функции по выводу всплывающих сообщений:
- useToastInfo(message, options)
- useToastSuccess(message, options)
- useToastError(message, options)
- useToastsClear() - убирает выведенные сообщения
Всё понятно из названий. Первым параметром идёт сообщение, вторым можно указать дополнительные опции для вывода.
Если при запросе в API произошла ошибка, она будет выведена автоматически через useToastError().
Есть еще полезные функции:
- getApiUrl() - определяет базовый адрес для запроса в API
- getImageLink(VespFile, VespFileOptions) - формирует ссылку на вывод картинки из API, принимает переменные указанных типов
- hasScope(permission) - проверяет, есть ли у юзера разрешение на что-то, типа users/get
Скорее всего, список всяких полезных функций еще будет расширяться.
Самое прикольное, что ничего импортировать не нужно: ни компоненты, ни функции, ни авторизацию. Оно всё просто доступно во всех vue файлах, за это отвечает Nuxt.
Docker
Новая версия рассчитана на работу в Docker. По умолчанию прописан production конфиг, который вы можете переопределить файлом docker-compose.override.yml.
Я приложил в комплект такой файлик с расширением dist, его можно переименовать и запускать контейнеры в режиме для разработки. Разница, в общем-то, только в открытии внешних портов, но вы можете переопределить и что-то еще.
Также упростил файл .env и прописал умолчания в docker-compose.yml, теперь из настроек для Docker только хост Nginx и возможность установить Xdebug в PHP.
В общем, никаких раздельных конфигов, всё оптимизировано и упрощено.
Заключение
Новая версия теперь по умолчанию в репозитории, запустить новый проект проще простого.
git clone https://github.com/bezumkin/vesp.git
cd vesp
cp .env.dist .env
cp docker-compose.override.yml.dist docker-compose.override.yml
docker-compose up --build
Если у вас уже есть проект с названием vesp в докере, нужно указать новое имя в .env перед запуском, например:
COMPOSE_PROJECT_NAME=vesp-new
Миграции и сиды теперь накатываются при первом же старте, никаких лишних телодвижений.
Дожидаемся в консоли надписи Vite client warmed up in, открываем 127.0.0.1:8080 и входим в админку, используя логин и пароль admin.
Все свои новые проекты я буду делать на этой версии, так что будут еще разные правки по мере нахождения проблем.
1
👍
👎
❤️
🔥
😮
😢
😀
😡
875
24.01.2024, 15:31:33
108 комментариев
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
inna
06.11.2024, 15:47:13
Да. Все работает. Спасибо.
Vesp 3.0
108
Ivan CR
24.10.2024, 15:20:54
С днем рождения!!! Класс, что в твоей жизни есть такие интересные достижения.
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.
this в Composition API не используем?
Плагины не нужно регистрировать в nuxt.config.ts?