- PVSM.RU - https://www.pvsm.ru -
Из этого урока Вы узнаете как можно быстро создать RESTful API для любого сайта на любой CMS, MODX [1] — это только пример.
Для создания API я буду использовать:
Результат здесь:
https://github.com/andchir/modx2-api [4]
Всё описанное я проделывал на Linux, но я думаю, что на Windows разница в командах будет не большая. Предварительно я установил Composer [5] и утилиту Symfony [6].
Создаю проект:
composer create-project symfony/skeleton modx2-api
Устанавливаю необходимые пакеты для создания API:
cd modx2-api
composer req api
composer req migrations
composer req form
composer req maker --dev
Запускаю локальный сервер.
Если установлена утилита Symfony:
symfony server:start
или так:
php -S 127.0.0.1:8000 -t public
Открываю в браузере адрес для проверки, что всё работает:
http://127.0.0.1:8000/ [7]
Открываю файл .env и редактирую строку подключения к базе данных проекта на MODX:
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
Теперь нужно создать пользователя и настроить систему авторизации по логину и паролю.
Устанавливаю дополнительные пакеты:
composer req jwt-auth
composer req orm-fixtures --dev
composer req profiler --dev
В файле .env появились новые параметры пакета "jwt-authentication-bundle".
Создаю классы сущности и репозитория пользователя:
php bin/console make:user
Появились два файла:
src/Entity/User.php
src/Repository/UserRepository.php
Создаю таблицу "user" в базе данных:
bin/console doctrine:schema:create
Настраиваю авторизацию пользователей в соответствии с инструкциями:
<?php
namespace AppController;
use AppEntityUser;
use AppFormTypeLoginType;
use AppFormTypeUpdateProfileType;
use DoctrineORMEntityManagerInterface;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
use SymfonyComponentValidatorValidatorValidatorInterface;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="app_login")
* @param AuthenticationUtils $authenticationUtils
* @return Response
*/
public function loginAction(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('api_entrypoint');
}
$form = $this->createForm(LoginType::class);
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', [
'form' => $form->createView(),
'last_username' => $lastUsername,
'error' => $error
]);
}
}
Генерирую класс для создания пользователей:
php bin/console make:fixtures
Подробнее здесь: https://symfony.com/doc/current/security.html#a-create-your-user-class [10]
<?php
namespace AppDataFixtures;
use AppEntityUser;
use DoctrineBundleFixturesBundleFixture;
use DoctrineCommonPersistenceObjectManager;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
class UserFixtures extends Fixture
{
private $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
public function load(ObjectManager $manager)
{
$user = new User();
$user
->setEmail('admin@admin.com')
->setRoles(['ROLE_USER', 'ROLE_ADMIN']);
$user->setPassword($this->passwordEncoder->encodePassword(
$user,
'admin'// пароль
));
$manager->persist($user);
$manager->flush();
}
}
Создаю администратора с адресом почты "admin@admin.com" и паролем "admin":
php bin/console doctrine:fixtures:load --append --group=UserFixtures
Позже эти данные можно будет изменить.
Генерирую ключи в папке config/jwt/:
jwt_passhrase=$(grep ''^JWT_PASSPHRASE='' .env | cut -f 2 -d ''='')
echo "$jwt_passhrase" | openssl genpkey -out config/jwt/private.pem -pass stdin -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096
echo "$jwt_passhrase" | openssl pkey -in config/jwt/private.pem -passin stdin -out config/jwt/public.pem -pubout
setfacl -R -m u:www-data:rX -m u:"$(whoami)":rwX config/jwt
setfacl -dR -m u:www-data:rX -m u:"$(whoami)":rwX config/jwt
Проверяю создание токена:
curl -X POST -H "Content-Type: application/json" http://localhost:8000/authentication_token -d '{"email":"admin@admin.com","password":"admin"}'
Создаю миграцию:
php bin/console make:migration
Теперь самое интересное.
Генерирую классы сущностей для всех таблиц базы данных:
php bin/console doctrine:mapping:import "AppEntity" annotation --path=src/Entity
Генерирую геттеры и сеттеры для классов:
php bin/console make:entity --regenerate App
Открываю код одного класса, например src/Entity/ModxSiteContent.php. Добавляю аннотацию @ApiResource:
API для ModxSiteContent готово.
Открываю страницу http://localhost:8000/api [11]
Беру токен, нажимаю кнопку "Authorize", вставляю строку с токеном:
Bearer MY_TOKEN
Нажимаю кнопку "Try it out" и затем кнопку "Execute". Получаю такой результат:
Я не буду описывать как создаются фильтры, чтобы не дублировать документацию [12], но приведу пример как можно создать связи для таблиц, т.к. это немного сложнее.
В случае MODX данные пользователей хранятся в отдельной таблице "user_attributes". Например, мне нужно в выборку пользователей по GET запросу добавить их email, имя, телефон и т.д. Открываю код класса AppEntityModxUsers, добавляю приватное свойство $attributes
и описываю связь с классом AppEntityModxUserAttributes в аннотоции "@ORMOneToOne":
/**
* @var ModxUserAttributes
*
* @ORMOneToOne(targetEntity="ModxUserAttributes", mappedBy="user")
* @Groups({"read", "attributes"})
*/
private $attributes;
Снова добавляю недостающие геттеры и сеттеры:
php bin/console make:entity --regenerate App\Entity\ModxUsers
Обратите внимание, что я добавил группу "attributes" в аннотацию @ApiResource
Открываю код класса AppEntityModxUserAttributes, добавляю аннотацию @ApiResource
и связь с классом AppEntityModxUsers
:
/**
* @var ModxUsers
*
* @ORMOneToOne(targetEntity="ModxUsers", mappedBy="attributes")
* @ORMJoinColumn(name="internalKey", referencedColumnName="id")
*/
private $user;
Всем свойствам, которые нужно добавить в выборку, вставляю аннотацию @Groups({"attributes"})
.
Результат:
В итоге для авторизации в вашем приложении вам нужно сначала отправить логин (email) и пароль на URL "/authentication_token", получить токен и потом этот токен отправлять в каждом запросе в заголовке "Authorization":
[13]
Если проект https://github.com/andchir/modx2-api [4] будет интересен пользователям, он будет развиваться. Также жду PR от всех желающих помочь.
Автор: Андрей Ч.
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/modx/339294
Ссылки в тексте:
[1] MODX: https://modx.com/
[2] https://symfony.com/: https://symfony.com/
[3] https://api-platform.com/: https://api-platform.com/
[4] https://github.com/andchir/modx2-api: https://github.com/andchir/modx2-api
[5] Composer: https://getcomposer.org/
[6] Symfony: https://symfony.com/download
[7] http://127.0.0.1:8000/: http://127.0.0.1:8000/
[8] https://symfony.com/doc/current/security/form_login_setup.html: https://symfony.com/doc/current/security/form_login_setup.html
[9] https://api-platform.com/docs/core/jwt/#configuring-the-symfony-securitybundle: https://api-platform.com/docs/core/jwt/#configuring-the-symfony-securitybundle
[10] https://symfony.com/doc/current/security.html#a-create-your-user-class: https://symfony.com/doc/current/security.html#a-create-your-user-class
[11] http://localhost:8000/api: http://localhost:8000/api
[12] документацию: https://api-platform.com/docs/core/filters/
[13] Image: https://habrastorage.org/webt/fw/lf/z3/fwlfz3l7udoavafmgz95dopwgum.png
[14] Источник: https://habr.com/ru/post/479168/?utm_source=habrahabr&utm_medium=rss&utm_campaign=479168
Нажмите здесь для печати.