Работа на Vesp

Знакомимся с фронтендом

Как вы уже поняли по предыдущим заметкам, бэкенд и фронтенд Vesp не зависят друг от друга вообще никак. На прошлом занятии мы отправляли запросы в API из консоли через cURL и всё нормально работало.

Вместо консоли это могло быть и мобильное приложение, и любой веб-сайт. Я же предлагаю использовать веб-приложение, написанное на VueJS, с использованием NuxtJS - потому что они мне очень нравятся. И сейчас расскажу, почему.

Читать далее

Авторизация в контроллерах

Как мы уже выяснили в прошлой заметке, пользователь авторизовывается в контроллерах при каждем запросе с помощью токена JWT, который передаётся или в заголовках, или в GET параметре, или получается из куки.

Теперь давайте посмотрим, как происходит получение этого токена пользователем.

Согласно нашему route.php запросы на авторизацию принимаются по адресу api/security/login контроллером App\Controllers\Security\Login, который расширяет Vesp\Controllers\Security\Login:

<?php
// Это оригинальный контроллер из vesp/core
namespace Vesp\Controllers\Security;

use Psr\Http\Message\ResponseInterface;
use Vesp\Controllers\Controller;
use Vesp\Helpers\Jwt;
use Vesp\Models\User;

class Login extends Controller
{
    // Контроллер работает с моделью User
    protected $model = User::class;

    // Обращаться можно только методом POST
    public function post(): ResponseInterface
    {
        // для авторизации требуются username и password
        $username = trim($this->getProperty('username', ''));
        $password = trim($this->getProperty('password', ''));

        // Выбираем пользователя по username
        $user = (new $this->model())->newQuery()->where('username', $username)->first();
        // Если есть такой, и указан верный пароль
        if ($user && $user->verifyPassword($password)) {
            // Проверяем его статус, и возвращаем токен, или ошибку
            return !$user->active
                ? $this->failure('This user is not active', 403)
                : $this->success(['token' => Jwt::makeToken($user->id)]);
        }

        // Авторизовать не удалось - возвращаем ошибку
        return $this->failure('Wrong username or password');
    }
}
Читать далее

Проверка прав доступа в контроллерах

Мы продолжаем знакомиться с внутренним устройством Vesp и сегодня пришла пора поговорить о системе прав доступа к данным.

После работы с MODX мне не хотелось изобретать что-то сложное, поэтому я придумал следующее:

  1. Права доступа прописываются группе, а не пользователю и хранятся в JSON колонке scope (область действия)
  2. Каждый пользователь может принадлежать только к одной группе
  3. Права в группе могут быть указаны для конкретного метода. Если users позволяет любые запросы, то users/get только получение данных, без put, patch и delete.

Таким образом каждой группе можно гибко давать разрешения на конкретные методы в контроллерах.

Когда подобной системы недостаточно, и нужно проверять, например, id автора комментария при редактировании, то мы просто расширяем метод checkScope у контроллера.

Давайте посмотрим, как он работает по-умолчанию.

Читать далее

Контроллеры Vesp

На прошлых уроках мы работали с миграциями Phinx и моделями Eloquent - это всё сторонние библиотеки, а где же сам Vesp?

А он в контроллерах, которые были написаны под сильным впечатлением от процессоров MODX, и работают через Slim 4. Интересный факт - MODX 3 в своё время планировали завязать именно на Slim, но что-то пошло не так, и эти планы забросили.

Итак, все запросы от пользователей приходят в один-единственный коннектор www/api.php. Он подключает всё нужное файлом core/bootstrap.php (который можно использовать во всяких консольных скриптах) и создаёт экземпляр приложения Slim.

Дальше в это приложение грузятся наши маршруты из файла core/routes.php, и теперь система знает, какой контроллер отвечает за конкретный запрос. Давайте разберёмся с маршрутами.

Читать далее

Модели Eloquent

Сегодня посмотрим как работать с нашими новыми таблицами, созданными в прошлом уроке.

Модели - это PHP классы, лежащие в core/src/Models, расширяющие Illuminate\Database\Eloquent\Model и представляющие собой записи в соответствующей таблице базы данных. В отличие от MODX и его xDPO, здесь не нужно писать никаких схем и генерировать непонятные map файлы. Одна модель - это всегда один класс и одна таблица в БД, всё очень просто и понятно. Если миграции меняют таблицу, то эти изменения нужно будет отразить и в модели.

Vesp устанавливает 4 модели по умолчанию: File, UserRole, User, UserToken - они отражают записи в таблицах files, user_roles, users и user_tokens соответственно.

Как видно, имена моделей чётко соотносятся с таблицами согласно правилам английского языка - и это не случайно. В Eloquent приняты определённые соглашения по многим ключевым моментам, включая имена моделей и таблиц.

Читать далее

Разбираемся с миграциями

На прошлом уроке мы дошли до запуска проекта со стандартными таблицами и данными, теперь давайте разберёмся, откуда они взялись.

В директории core/db есть 2 поддиректории: migrations и seeds. В первой, понятно, миграции, а во второй скрипты для "засеивания" начальных данных. Для работы используется Phinx, конфигурация которого хранится в core/phinx.php - там нам ничего менять не нужно, все настройки берутся из настроек окружения .env.

Миграциями называют изменение структуры базы данных без потери её консистентности. Каждая миграция может быть отменена, при этом она возвращает структуру БД к предыдущему виду. На продакшене, конечно же, никто миграции не откатывает - это нужно только на время разработки.

Для запуска миграций в Vesp мы используем команду composer db:migrate, для отката composer db:rollback.

Теперь давайте посмотрим на сами файлы миграций.

Читать далее

Создание нового проекта

Первым делом нам нужно разобраться с вашей рабочей средой. Я использую одни из самых популярных инструментов:

  • Операционную систему MacOS с менеджером пакетов Homebrew
  • Laravel Valet для локальной разработки
  • Интегрированную среду PhpStorm
  • Веб-сервер Nginx
  • База данных MySQL 8.0
  • Php 7.4 и NodeJS 17

Здесь нет ничего особенного, обычный набор веб-разработчика.

Если вы используете такой же сетап, то поздравляю, вам будет максимально легко следовать моим инструкциям - нужно только установить специальный драйвер для Valet из репозитория vesp-valet-driver, что делается простым копированием файла VespValetDriver.php в ~/.config/valet/Drivers.

Структурно Vesp состоит из 2х больших частей: фронтенда на VueJS и бэкенда на PHP. Обе части разрабатываются (и могут быть использованы) независимо друг от друга и хранятся в разных репозиториях:

Объединяются они в 1 общем пакете, который называется просто Vesp и ставится из Packagist при помощи composer. Давайте создадим наш новый проект VespShop.

composer create-project vesp/vesp ./VespShop

Команда create-project у composer не просто скачивает пакеты, но и запускает скрипты, прописанные в composer.json. В нашем случае они устанавливают зависимости Node.js.

Далее заходим в директорию VespShop и делаем valet link vesp-shop, что создаёт в нашем Valet новый сайт vesp-shop.test.

В нём пока ничего нет, поэтому делаем в той же директории composer node:generate и переходим по локальному адресу http://vesp-shop.test - теперь вы должны увидеть такую картинку:

Давайте разберёмся как это всё работает.

Читать далее

Начинаем новый курс!

Примерно с 2020 года я работаю на своём собственном фреймворке Vesp, который мне очень нравится. Он простой, быстрый, построен на известных популярных решениях и не ограничивает разработчика.

Именно на Vesp построен и сам сайт bezumkin.ru.

Одна проблема - я никак не могу написать к нему документацию, чтобы и другие разработчики могли его оценить по достоинству. Мне кажется любому программисту гораздо проще писать код, чем рассказывать, как именно он работает.

Поэтому я решил написать не просто скучную документацию, а сразу подробный обучающий курс - где мы сможем пообщаться в процессе.

Мы напишем интернет-магазин с функционалом примерно как у miniShop2, попутно пройдя все этапы создания проекта:

  • Проектирование и создание таблиц для хранения данных
  • Создание моделей для работы с таблицами на Eloquent
  • Напишем контроллеры для работы с этими моделями
  • Работать будем из собственной админки на VueJS
  • И вишенкой на торте сделаем небольшой SPA интернет-магазин на VueJS

Вы освоите: Slim4, Eloquent, VueJS, NuxtJs, Phinx и что там еще по пути потребуется.

Читать далее
bezumkin
Василий Наумкин
04.07.2022 23:34
Что-то странное у тебя произошло: миграция есть, и вроде как выполнена, но таблицы при этом отсутств...
inetlover
Александр Наумов
03.07.2022 20:36
Василий, спасибо! Все понятно!
bezumkin
Василий Наумкин
02.07.2022 20:28
Спасибо, поправил!
bezumkin
Василий Наумкин
30.06.2022 03:58
Есть ли возможность формировать &quot;friendly URL aliases&quot;, используя аналог translit MODx? ...
bezumkin
Василий Наумкин
27.06.2022 03:32
Спасибо за исправления, очень выручаешь =) Но учитывая количество не описаных в заметке дополнительн...
bezumkin
Василий Наумкин
27.06.2022 03:10
что будет использоваться для вывода многоуровневого меню Посмотри как работают комментарии на этом ...
bezumkin
Василий Наумкин
25.06.2022 11:56
Поправил, спасибо!
bezumkin
Василий Наумкин
21.06.2022 01:58
onLoad(data) { this.total = data.total }, и onLoad({total}) { this.total = total }, В нашем случ...
bezumkin
Василий Наумкин
20.06.2022 14:01
Прекрасно тебя понимаю, я когда сам в этом разбирался - голова дымилась. Но зато теперь прямо-таки п...
bezumkin
Василий Наумкин
20.06.2022 09:30
Не надо, оно по умолчанию так - я просто чуть более подробно написал.