Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations.
AdonisJs — это веб-инфраструктура Node.js, написанная на простом языке JavaScript, поддерживаемом всеми основными операционными системами. Она использует популярную схему MVC (модель — представление — контроллер) и предлагает стабильную экосистему для написания серверной части веб-приложений. Инфраструктура поддерживает удобную аутентификацию, SQL ORM (реляционные карты объектов), миграцию и пополнение баз данных. Архитектура AdonisJs похожа на архитектуру веб-инфраструктуры Laravel для приложений PHP и имеет такую же структуру папок и несколько сходных концепций настройки.
По умолчанию AdonisJs использует систему шаблонов Edge, разработанную для интуитивно простого использования. Как и в Laravel, в AdonisJs имеется система ORM под названием Lucid, служащая интерфейсом для взаимодействия между моделями приложения и базой данных. С помощью AdonisJs разработчики могут создавать комплексные приложения, где серверная часть отвечает за применение бизнес-логики, маршрутизацию и рендеринг всех страниц приложения. Также можно создать API веб-служб для возврата ответов JSON от контроллера. Эти веб-службы можно использовать с помощью клиентских инфраструктур, таких как Vue.js, React и Angular.
В этом обучающем руководстве мы создадим приложение с помощью AdonisJs, используя CLI. Мы создадим маршруты, контроллеры, модели и представления приложения, а также проведем проверки форм. В качестве примера для этого обучающего руководства мы выбрали приложение, в которое пользователь может входить для создания вдохновляющих цитат. Это демонстрационное приложение позволит выполнять операции создания, чтения, обновления и удаления (CRUD).
Для прохождения этого обучающего руководства вам потребуется следующее:
Примечание. Для разработки в этом обучающем руководстве будет использоваться компьютер под управлением macOS. Если вы используете другую операционную систему, вам может потребоваться использовать права sudo
для выполнения команд npm
на первых шагах.
В этом разделе мы установим Adonis CLI и все его требуемые пакеты на наш локальный компьютер. CLI позволяет создать структуру нового проекта AdonisJs, а также создать и сгенерировать шаблоны контроллеров, связующих элементов и моделей в вашем приложении. Также вы создадите базу данных для проекта.
Выполните следующую команду для глобальной установки AdonisJs CLI на компьютере с помощью npm
:
- npm i -g @adonisjs/cli
После завершения процесса установки введите в терминал следующую команду для подтверждения установки AdonisJs и просмотра текущей версии:
- adonis --version
Вы увидите вывод с указанием текущей версии AdonisJs:
Output4.1.0
Мы успешно установили AdonisJs CLI и теперь можем использовать команду adonis
для установки новых проектов AdonisJs, управления проектами и генерирования требуемых файлов, в том числе контроллеров, моделей и т. д.
Теперь мы можем перейти к созданию нового проекта AdonisJs, используя команду adonis
, как показано здесь:
- adonis new adonis-quotes-app
Приведенная выше команда создаст приложение adonis-quotes-app
в новой директории с тем же именем внутри директории локального проекта, используя соответствующую структуру AdonisJs MVC.
Перейдите в папку нового приложения:
- cd adonis-quotes-app
Запустите приложенеи с помощью следующей команды:
- adonis serve --dev
Эта команда запустит сервер разработки на порту по умолчанию 3333
, как указано внутри файла root .env
для вашего приложения. Введите адрес http://localhost:3333 для просмотра приветственной страницы AdonisJs.
Теперь мы завершим настройку базы данных. Здесь вы установите драйвер mysql
для подключения к вашему серверу MySQL из вашего приложения Node.js с помощью npm
. Для начала вернитесь в терминал, где запущено приложение, остановите процесс нажатием CTRL + C
и запустите следующую команду:
- npm i mysql
Вы успешно установили драйвер MySQL Node.js для этого приложения, и теперь вам нужно создать базу данных приложения и настроить подключение к ней.
Последняя версия MySQL, установленная согласно указаниям предварительных требований обучающего руководства, использует плагин аутентификации по умолчанию под названием caching_sha2_password
. Этот плагин в настоящее время не поддерживается драйверами Node.js для MySQL. Чтобы избежать проблем при подключении вашего приложения к базе данных, вам нужно будет создать нового пользователя MySQL и использовать поддерживаемый плагин аутентификации mysql_native_password
.
Для начала откройте клиент MySQL, используя учетную запись root:
- mysql -u root -p
В диалоге введите пароль учетной записи root, заданный во время установки MySQL.
Затем создайте пользователя и пароль, используя плагин mysql_native_password
:
- CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Результат будет выглядеть следующим образом:
OutputQuery OK, 0 rows affected (0.02 sec)
Создайте базу данных приложения с помощью следующей команды:
- CREATE DATABASE adonis;
Результат будет выглядеть следующим образом:
OutputQuery OK, 1 row affected (0.03 sec)
Вы успешно создали базу данных для своего приложения.
Теперь активируйте доступ к созданной базе данных для нового пользователя MySQL. Запустите следующую команду для предоставления всех привилегий пользователю в базе данных:
- GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';
Перезагрузите таблицы grant, запустив следующую команду для применения внесенных изменений:
- FLUSH PRIVILEGES;
Результат будет выглядеть следующим образом:
OutputQuery OK, 0 rows affected (0.00 sec)
Закройте клиент MySQL с помощью следующей команды:
- quit;
Мы успешно установили AdonisJs CLI, создали новый проект AdonisJs и выполнили установку mysql
с помощью npm
. Также мы создали базу данных для этого приложения и настроили пользователя MySQL с соответствующими правами доступа к нему. Базовая конфигурация приложения готова, и на следующем шаге мы начнем создавать необходимые представления для вашего приложения.
AdonisJs поставляется с собственной системой шаблонов Edge. Это позволяет создать многоразовый шаблон HTML и внести в приложение логику клиентской части с минимальным объемом кода. Edge дает разработчикам приложений JavaScript инструменты для создания схемы на базе компонентов, написания условных выражений, использования итераций и создания уровней представлений для хранения логики. Все файлы шаблонов с расширением .edge
хранятся в директории resources/views
.
Далее указаны представления, необходимые приложению для надлежащей работы:
Для начала используйте команду adonis
для создания страницы генерального макета, как показано здесь:
- adonis make:view layouts/master
Результат будет выглядеть примерно так:
Output✔ create resources/views/layouts/master.edge
Эта команда автоматически создаст файл master.edge
в папке resources/views/layouts
. Откройте новый файл:
- nano resources/views/layouts/master.edge
Добавьте в него следующий код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>adonis-quotes-app</title>
{{ style('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') }}
{{ style('style') }}
{{ script('https://code.jquery.com/jquery-3.3.1.slim.min.js') }}
</head>
<body>
<div class="container-fliud">
@include('navbar')
@!section('content')
</div>
{{ script('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') }}
</body>
</html>
В этот файл добавляются файлы CDN для Bootstrap CSS, Bootstrap JavaScript и jQuery. Также добавляется имя глобального файла CSS style.css
, а в div
добавляется частичный файл с именем navbar
. Для повторного использования требуемых фрагментов кода HTML (например, nav
или footer
) на разных страницах приложения можно использовать частичные файлы. Это небольшие файлы, содержащие повторяющийся код и позволяющие быстро обновлять код этих элементов в одном месте, а не на каждой странице по отдельности. Файл navbar
содержит разметку для кнопок Вход и Регистрация, логотип и ссылку на главную страницу.
С этим файлом все последующие страницы этого приложения смогут использовать генеральный макет и выводить панель навигации
без написания соответствующего кода для каждой страницы. Мы создадим этот файл navbar
на следующих шагах этого обучающего руководства.
В заключение мы определим тэг раздела @! section()
, чтобы включить контент других страниц и обеспечить их рендеринг в генеральном макете. Чтобы эта система работала ожидаемым образом, все новые страницы на основе генерального макета должны также определять тег раздела с одним и тем же именем (т. е. @section(``'``content``'``)
).
Сохраните и закройте файл, когда закончите его редактирование.
Далее мы используем команду adonis
для создания панели навигации:
- adonis make:view navbar
Результат будет выглядеть примерно так:
Output✔ create resources/views/navbar.edge
Откройте созданный файл:
- nano resources/views/navbar.edge
Затем добавьте в него следующий код:
<nav class="navbar navbar-expand-lg navbar-dark text-white">
<a class="navbar-brand" >LOGO</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active ">
<a class="btn text-white" href="/">Home</a>
</li>
</ul>
</div>
<div class="navbar-right" id="navbarNav">
@loggedIn
<ul class="navbar-nav">
<li>
<div class="text-right">
<a href="{{route('create.quote')}}" class="btn btn-outline-primary">Create Quote</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ auth.user.username}}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<form method="POST" action="{{route('logout')}}">
{{ csrfField() }}
<button type="submit" class="dropdown-item" href="">logout</button>
</form>
</div>
</li>
</ul>
@else
<ul class="navbar-nav">
<li class="nav-item active pr-2">
<a href="{{route('login.create')}}" class="btn btn-outline-danger">
login
</a>
</li>
<li class="nav-item active pr-2">
<a href="{{route('register.create')}}" class="btn btn-outline-primary">
Register
</a>
</li>
</ul>
@endloggedIn
</div>
</nav>
В дополнение к определениям ссылок на главную страницу и кнопок для регистрации и входа мы добавим тег @loggedIn
. С этим тегом мы можем написать условное выражение для прошедшего аутентификацию пользователя и выводить соответствующее содержание, когда это требуется. Для прошедшего аутентификацию пользователя приложение отображает имя пользователя и кнопку создания новой цитаты. Если пользователь не прошел аутентификацию, приложение будет отображать кнопку для входа или регистрации. Эта страница будет добавляться как часть каждой другой страницы, как и в случае с генеральным макетом приложения.
Сохраните и закройте файл.
Теперь мы создадим страницу указателя, которую используем в качестве главной страницы приложения. Она выполняет рендеринг и выводит список всех вдохновляющих цитат, написанных пользователями:
- adonis make:view index
Вы увидите примерно следующий результат:
Output✔ create resources/views/index.edge
Созданный нами файл будет располагаться в директории resources/views/index.edge
. Откройте файл:
- nano resources/views/index.edge
Добавьте следующий код:
@layout('layouts/master')
@section('content')
<div class="container">
<div class="text-center">
@if(flashMessage('successmessage'))
<span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
@endif
</div>
<div class="row">
@each(quote in quotes)
<div class="col-md-4 mb-4 quote-wrapper">
<a href="/view-quote/{{quote.id}}" class="w-100">
<div class="card shadow-lg bg-dark text-white">
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>{{quote.body}}</p>
<footer class="blockquote-footer">
<cite title="Source Title"> {{quote.username}}</cite>
</footer>
</blockquote>
@if(auth.user.id == quote.user_id)
<div>
<a href="/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
<a href="/delete-quote/{{quote.id}}" class="btn btn-danger">delete</a>
</div>
@endif
</div>
</div>
</a>
</div>
@else
<div class="col-md-12 empty-quote text-center">
<p>No inspirational quote has been created</p>
</div>
@endeach
</div>
</div>
@endsection
Здесь вы указываете, что это представление будет использовать макет master
посредством его расширения. Теперь эта страница имеет доступ ко всем библиотекам, таблицам стилей и файлу navbar
в составе макета master
. Далее мы выполним итерацию по массиву цитат
, используя встроенный тег @each
. Массив quotes
будет передаваться в это представление из модуля QuoteController
, который мы создадим на следующих шагах этого обучающего руководства. В случае отсутствия цитат будет выведено соответствующее сообщение.
Сохраните и закройте файл.
Для создания страницы входа запустите в терминале следующую команду:
- adonis make:view auth/login
Вы увидите примерно следующий результат:
Output✔ create resources/views/auth/login.edge
Система автоматически создаст папку auth
в директории resources/views
, а также создаст в ней файл login.edge
. Откройте файл login.edge
:
- nano resources/views/auth/login.edge
Добавьте следующее содержимое:
@layout('layouts/master')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-4 shadow bg-white mt-5 rounded offset-md-4">
<form method="POST" action="{{route('login.store')}}">
{{ csrfField() }}
<div>
@if(flashMessage('successmessage'))
<span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
@endif
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}" placeholder="Enter email">
{{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
</div>
<div class="form-group">
<label for="pasword">Password</label>
<input type="password" class="form-control" id="password" name="password" value="{{old('password','')}}" placeholder="Password">
{{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
@endsection
В этом файле хранится форма, содержащая элементы ввода, которые вы будете использовать для получения имени пользователя и пароля зарегистрированного пользователя, прежде чем он сможет пройти аутентификацию и начать создавать цитаты. Еще один важный элемент на этой странице — {{ csrfField() }}
. Это глобальная переменная, которую AdonisJs будет использовать для передачи токена доступа CSRF при отправке запросов POST
, PUT
и DELETE
из приложения.
Она размещена для защиты вашего приложения от атак методом подделки межсайтовых запросов (CSRF). Она работает посредством генерирования для каждого посещающего сайт пользователя уникального секрета CSRF. При отправке пользователями запроса HTTP через клиент для этого секрета генерируется соответствующий токен, передаваемый вместе с запросом. Это позволяет связующему элементу, создаваемому для этого запроса в AdonisJs, проверять корректность токена и секрета CSRF и их принадлежность пользователю, прошедшему аутентификацию.
Сохраните и закройте файл после завершения.
Далее мы создадим страницу регистрации, используя следующую команду:
- adonis make:view auth/register
Вы увидите примерно следующий вывод:
Output✔ create resources/views/auth/register.edge
Найдите и откройте созданный файл в директории resources/views/auth/register.edge
:
- nano resources/views/auth/register.edge
Добавьте следующий код:
@layout('layouts/master')
@section('content')
<div class="container ">
<div class="row">
<div class="col-md-4 bg-white p-3 mt-5 shadow no-border rounded offset-md-4">
<form method="POST" action="{{route('register.store')}}">
{{ csrfField() }}
<div class="form-group">
<label for="name">Fullname</label>
<input type="text" class="form-control" id="name" name="name" value="{{old('name','')}}" placeholder="Enter Fullname">
{{ elIf('<span class=text-danger>$self</span>', getErrorFor('name'), hasErrorFor('name')) }}
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}" placeholder="Enter email">
{{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
</div>
<div class="form-group">
<label for="pasword">Password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
{{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
@endsection
Как и в случае со страницей входа, этот файл содержит форму HTML с полями ввода имени
, электронной почты
и пароля
пользователя при регистрации. Также здесь присутствует переменная {{ csrfField() }}
, поскольку она требуется для каждого запроса post для приложения AdonisJs.
Сохраните и закройте файл.
Теперь мы сгенерируем новый файл для создания вдохновляющей цитаты, запустив следующую команду из терминала:
- adonis make:view quotes/create-quote
Вы увидите примерно следующее:
Output✔ create resources/views/quotes/create-quote.edge
Откройте resources/views/quotes/create-quote.edge
:
- nano resources/views/quotes/create-quote.edge
Добавьте следующее содержание:
@layout('layouts/master')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6 shadow bg-white mt-5 rounded p-3">
<div class="float-right">
<a href="/" class="btn btn-outline-dark ">back</a>
</div>
<br>
<div class="clear-fix"></div>
<form method="POST" action="{{route('store.quote')}}">
{{ csrfField() }}
<div class="form-group">
<label for="quote">Create Quote</label>
<textarea type="text" rows="5" name='body' id="body" class="form-control" id="quote" placeholder="Write an inspirational quote"></textarea>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
<div class="col-md-3"></div>
</div>
</div>
@endsection
Эта страница расширяет генеральный макет и содержит форму HTML с элементом текстовой области, позволяющим пользователю вводить текст в нескольких строках, после чего этот текст отправляется и обрабатывается по заданному маршруту.
Сохраните и закройте файл после завершения.
Далее мы создадим страницу для редактирования конкретной цитаты. Запустите в терминале следующую команду:
- adonis make:view quotes/edit-quote
Результат будет выглядеть следующим образом:
Output✔ create resources/views/quotes/edit-quote.edge
Откройте файл с помощью следующей команды:
- nano resources/views/quotes/edit-quote.edge
Добавьте следующее содержание в файл resources/views/quotes/edit-quote
:
@layout('layouts/master')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-6 shadow bg-white rounded p-3 offset-md-3">
<div class="float-right">
<a href="/" class="btn btn-outline-dark ">back</a>
</div>
<br>
<div class="clear-fix"></div>
<form method="POST" action="/update-quote/{{quote.id}}">
{{ csrfField() }}
<div class="form-group">
<label for="pasword">Edit Quote</label>
<textarea type="text" rows="5" name='body' id="body" class="form-control" id="quote" placeholder="write the inspirational quote">{{quote.body}}</textarea>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
</div>
</div>
</div>
@endsection
Содержание этой страницы похоже на содержание файла create-quote.edge
. Отличие заключается в том, что она содержит данные конкретной цитаты, которую нужно отредактировать: <form method="POST" action="/update-quote/{{quote.id}}">
.
Сохраните и закройте файл.
В заключение мы сгенерируем страницу для просмотра одной вдохновляющей цитаты:
- adonis make:view quotes/quote
Вы увидите примерно следующий вывод:
Output✔ create resources/views/quotes/quote.edge
Откройте файл с помощью следующей команды:
- nano resources/views/quotes/quote.edge
Добавьте следующий код:
@layout('layouts/master')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="card shadow-lg bg-dark text-white">
<div class="card-body">
<div class="float-right">
<a href="/" class="btn btn-outline-primary ">back</a>
</div>
<br>
<div class="clear-fix"></div>
<blockquote class="blockquote mb-0">
<p>{{quote.body}}</p>
<footer class="blockquote-footer">
<cite title="Source Title">{{quote.username}}</cite>
</footer>
</blockquote>
</div>
</div>
</div>
</div>
</div>
@endsection
Эта страница выполняет рендеринг деталей конкретной цитаты, включая тело цитаты quote.body
и пользователя, создавшего цитату, quote.username
.
После завершения работы с этим файлом сохраните и закройте его.
Вы создали все требуемые страницы для вашего приложения, используя систему шаблонов Edge. Далее мы настроим и создадим подключение к базе данных нашего приложения.
Если мы запустим приложение сейчас, оно выдаст ошибку, поскольку мы не подключили его к базе данных. В этом разделе мы настроим подключение к базе данных, а затем используем команду adonis
для генерирования файла миграции, который будет использоваться для создания таблиц для нее.
В комплект AdonisJs входит модель ORM под названием Lucid ORM, обеспечивающая реализацию активных записей для работы с базой данных. Эта модель избавляет от необходимости писать запросы SQL, извлекающие данные из базы данных в реальном времени. Это особенно полезно при работе над сложными приложениями, для которых требуется большое количество запросов. Например, мы можем получить все цитаты из нашего приложения с помощью следующей команды:
const quotes = await Quote.all()
Чтобы продолжить настройку базы данных приложения, необходимо убедиться, что вы все еще находитесь в корневой директории вашего приложения, и создать в ней файл .env
:
- nano .env
Откройте созданный файл и добавьте в него следующее содержание:
HOST=127.0.0.1
PORT=3333
NODE_ENV=development
APP_URL=http://${HOST}:${PORT}
CACHE_VIEWS=false
APP_KEY=bTVOEgUvmTCfkvgrK8gEBC3Qxt1xSYr0
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=sammy
DB_PASSWORD=password
DB_DATABASE=adonis
SESSION_DRIVER=cookie
HASH_DRIVER=bcrypt
По умолчанию для подключения приложений AdonisJs к базе данных используется СУБД SQLite, которую мы здесь заменим на MySQL. Также мы укажем PORT
для приложения, среду приложения и учетные данные для входа в базу данных. Замените DB_USER
, DB_PASSWORD
и DB_DATABASE
своими учетными данными для базы данных.
Далее мы создадим модель и файл миграции для Quote
, используя Adonis CLI. Для этого нужно запустить следующую команду:
- adonis make:model Quote --migration
Результат будет выглядеть примерно так:
Output✔ create app/Models/Quote.js
✔ create database/migrations/1568209992854_quote_schema.js
Эта команда создаст модель Quote
в папке app/Models
и файл схемы в папке database/migrations
. Созданный файл схемы будет иметь префикс с указанием текущей временной метки. Откройте файл схемы с помощью следующей команды:
- nano database/migrations/1568209992854_quote_schema.js
Обновите его содержимое с помощью следующего кода:
'use strict'
/** @type {import('@adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')
class QuoteSchema extends Schema {
up () {
this.create('quotes', (table) => {
table.increments()
table.integer('user_id').notNullable()
table.string('username', 80).notNullable()
table.string('body').notNullable()
table.timestamps()
})
}
down () {
this.drop('quotes')
}
}
module.exports = QuoteSchema
Для файла схемы в AdonisJs требуются два разных метода:
up
.В дополнение к полям timestamps()
и increments()
мы обновим содержание файла схемы, указав атрибуты полей user_id
, username
и body
для создаваемой цитаты. В полях user_id
и username
указываются данные пользователя, создавшего определенную цитату. Файл построен по принципу отношения одного к многим. Это означает, что пользователю может принадлежать бесконечное количество цитат, а цитата может принадлежать только одному пользователю.
Сохраните и закройте файл.
В AdonisJs по умолчанию установлены модель User
и ее файл миграции. В связи с этим требуется лишь небольшое изменение для установки отношения между моделями User
и Quote
.
Откройте модель User
в app/Models/User.js
:
- app/Models/User.js
Добавьте этот метод сразу же после метода tokens()
:
...
class User extends Model {
...
tokens () {
return this.hasMany('App/Models/Token')
}
quote () {
return this.hasMany('App/Models/Quote')
}
}
module.exports = User
Эта команда устанавливает отношение «один ко многим» с таблицей Quote
, используя user_id
как посторонний ключ.
Сохраните и закройте файл.
В завершение этого раздела мы используем для проведения миграции следующую команду, которая выполнит метод up()
для всех файлов миграции:
- adonis migration:run
Вы увидите примерно следующий результат:
Outputmigrate: 1503248427885_user.js
migrate: 1503248427886_token.js
migrate: 1568209992854_quote_schema.js
Database migrated successfully in 3.42 s
Мы настроили и защитили соединение с базой данных. Также мы создали модель Quote
и соответствующий файл схемы и создали отношение один ко многим между моделями User
и Quote
. Далее мы сгенерирурем маршруты и создадим контроллеры для обработки запросов HTTP и бизнес-логики для создания, изменения и удаления вдохновляющей цитаты.
В этом разделе мы начнем с создания контроллеров для обработки всей логики приложения, а затем прикрепим эти контроллеры к определенному маршруту, чтобы пользователи могли использовать URL-адрес для получения доступа к ним.
Для начала мы используем Adonis CLI для создания нового контроллера запросов HTTP для обработки всех процессов аутентификации нашего приложения, выполнив следующую команду:
- adonis make:controller Auth --type http
Эта команда создаст файл AuthController.js
и сохранит его в папке app/Controllers/Http
. Используйте флаг --type
, чтобы указать, что этот контроллер должен быть контроллером HTTP.
Вы увидите примерно следующий результат:
Output✔ create app/Controllers/Http/AuthController.js
Затем откройте созданный файл контроллера:
- nano app/Controllers/Http/AuthController.js
Добавьте в него следующее содержание:
'use strict'
const User = use('App/Models/User')
class AuthController {
loginView({ view }) {
return view.render('auth.login')
}
registrationView({ view }) {
return view.render('auth.register')
}
async postLogin({ request, auth, response}) {
await auth.attempt(request.input('email'), request.input('password'))
return response.route('index')
}
async postRegister({ request, session, response }) {
const user = await User.create({
username: request.input('name'),
email: request.input('email'),
password: request.input('password')
})
session.flash({ successmessage: 'User have been created successfully'})
return response.route('login.create');
}
async logout ({ auth, response }) {
await auth.logout()
return response.route('/')
}
}
module.exports = AuthController
В этом файле мы импортируем модель User
и создаем два метода с именами loginView()
и registerView()
для рендеринга страниц входа в систему и регистрации соответственно. В заключение мы создадим следующие асинхронные методы:
postLogin()
: этот метод получает значения email
и password
, опубликованные посредством встроенного метода request
в AdonisJs, а затем сверяет эти учетные данные пользователя с базой данных. Если такой пользователь существует в базе данных и ввел правильные учетные данные, пользователь возвращается на главную страницу как прошедший аутентификацию и может создать новую цитату. В ином случае появится сообщение о том, что учетные данные введены неверно.postRegister()
: этот метод получает значения username
, email
и password
для создания учетной записи пользователя в базе данных. В сеанс приложения передается сообщение об успешном создании пользователя, а пользователь перенаправляется на страницу входа в систему для прохождения аутентификации, после чего он может создать цитату.logout()
: этот метод выполняет функцию выхода из системы и возвращает пользователя на главную страницу.Сохраните и закройте файл.
Мы настроили контроллер для регистрации и аутентификации пользователей. Теперь мы создадим контроллер запросов HTTP для управления всеми операциями с цитатами.
Вернитесь в терминал и запустите следующую команду для создания контроллера QuoteController
:
- adonis make:controller Quote --type http --resource
Используйте флаг --resource
для создания контроллера с заданными методами ресурсов для операций создания, чтения, обновления и удаления (CRUD).
Вы увидите следующее:
Output✔ create app/Controllers/Http/QuoteController.js
Найдите этот файл в папке app/Controllers/Http/QuoteController.js
:
- nano app/Controllers/Http/QuoteController.js
Добавьте в него следующее содержание:
'use strict'
const Quote = use('App/Models/Quote')
class QuoteController {
async index ({ view }) {
const quote = await Quote.all()
return view.render('index', {
quotes: quote.toJSON()
})
}
async create ({ view }) {
return view.render('quotes.create-quote')
}
async store ({ request,auth,session, response }) {
const quote = await Quote.create({
user_id: auth.user.id,
username: auth.user.username,
body: request.input('body')
})
session.flash({ 'successmessage': 'Quote has been created'})
return response.redirect('/')
}
async show ({ params, view }) {
const quote = await Quote.find(params.id)
return view.render('quotes.view-quote', {
quote: quote.toJSON()
})
}
async edit ({ params, view }) {
const quote = await Quote.find(params.id)
return view.render('quotes.edit-quote', {
quote: quote.toJSON()
})
}
async update ({ params, request, response, session }) {
const quote = await Quote.find(params.id)
quote.body = request.input('body')
await quote.save()
session.flash({'successmessage': 'Quote has been updated'})
return response.redirect('/')
}
async destroy ({ params, response, session }) {
const quote = await Quote.find(params.id)
await quote.delete()
session.flash({'successmessage': 'Quote has been deleted'})
return response.redirect('/')
}
}
module.exports = QuoteController
В этом контроллере мы импортировали модель Quote
и обновили следующие методы, которые были автоматически созданы с помощью AdonisJs CLI:
index()
: доставка всех цитат из базы данных и их рендеринг на главной странице приложения.create()
: рендеринг страницы для создания цитат.store()
: сохранение созданной цитаты в базе данных и вывод соответствующего ответа.show()
: получение идентификатора
определенной цитаты, ее извлечение из базы данных и рендеринг на странице редактирования цитаты.edit()
: получение деталей определенной цитаты из базы данных и ее рендеринг для редактирования.update()
: обработка любых изменений цитаты и возвращение пользователя на главную страницу.destroy()
: удаление определенной цитаты и ее полное удаление из базы данных.Сохраните и закройте файл.
После создания всех необходимых контроллеров для этого приложения мы можем настроить маршруты, чтобы пользователи могли легко взаимодействовать с приложением. Для начала перейдите в файл start/routes.js
.
- nano start/routes.js
Замените его содержание на следующее:
'use strict'
const Route = use('Route')
Route.get('/','QuoteController.index').as('index')
Route.get('/register','AuthController.registrationView').as('register.create')
Route.post('/register-store','AuthController.postRegister').as('register.store').validator('Register')
Route.get('/login','AuthController.loginView').as('login.create')
Route.post('/login-store','AuthController.postLogin').as('login.store')
Route.get('/view-quote/:id','QuoteController.show').as('view.quote')
Route.group(() => {
Route.get('/create-quote','QuoteController.create').as('create.quote')
Route.post('/store-quote','QuoteController.store').as('store.quote')
Route.get('/edit-quote/:id','QuoteController.edit').as('edit.quote')
Route.post('/update-quote/:id','QuoteController.update').as('update.quote')
Route.get('/delete-quote/:id','QuoteController.destroy').as('delete.quote')
Route.post('/logout','AuthController.logout').as('logout')
}).middleware(['auth'])
Здесь мы определяем путь к каждому маршруту нашего приложения, задаем глаголы HTTP для каждого действия и привязываем маршрут к определенному методу в каждом контроллере. Также мы присвоим имена каждому из маршрутов, поскольку контроллеры и представления ссылаются на них.
Чтобы обеспечить доступ ко всем маршрутам цитат только для пользователей, прошедших аутентификацию, мы назначим соответствующую группу middleware. В заключение мы прикрепим метод проверки к маршруту register.store
для проверки вводимых пользователем данных.
Сохраните и закройте файл.
Мы создали контроллеры и настроили маршруты приложения. Далее мы создадим метод проверки, определяемый на этом шаге.
AdonisJs не имеет встроенных по умолчанию средств проверки. Поэтому средство проверки для вашего приложения нужно установить и зарегистрировать вручную.
Запустите следующую команду для его установки:
- adonis install @adonisjs/validator
Откройте следующий файл для регистрации поставщика средства проверки:
- nano start/app.js
Зарегистрируйте поставщика средства проверки, добавив его в список поставщиков, как показано далее:
...
const providers = [
...
'@adonisjs/cors/providers/CorsProvider',
'@adonisjs/shield/providers/ShieldProvider',
'@adonisjs/session/providers/SessionProvider',
'@adonisjs/auth/providers/AuthProvider',
'@adonisjs/validator/providers/ValidatorProvider'
]
Мы установили и зарегистрировали поставщика средства проверки в нашем приложении. Теперь мы создадим собственное средство проверки ввода данных пользователем при регистрации с помощью следующей команды:
- adonis make:validator Register
Эта команда создаст файл Register.js
в директории App/validators
. Откройте файл с помощью следующей команды:
- nano app/Validators/Register.js
Добавьте в файл следующий код:
'use strict'
class Register {
get rules () {
return {
name:'required',
email:'required|email|unique:users',
password:'required|min:8'
}
}
get messages(){
return{
'name.required':'Full name is required',
'email.required':'email is required',
'email.unique':'email already exists',
'password.required':'password is required',
'password.min':'password should be at least 8 characters'
}
}
}
module.exports = Register
Для определенных полей в приложении можно определять правила. Если проверка не будет пройдена на любом этапе, средство проверки автоматически выведет всплывающее сообщение об ошибке и возвратит пользователя в форму.
Сохраните и закройте файл после завершения редактирования.
Для добавление стилей в ваше приложение откройте следующий файл:
- nano public/style.css
Замените его содержание на следующее:
@import url('https://fonts.googleapis.com/css?family=Montserrat:300');
html, body {
height: 100%;
width: 100%;
}
body {
font-family: 'Montserrat', sans-serif;
font-weight: 300;
background-image: url("/splash.png");
background-color: #220052;
}
* {
margin: 0;
padding: 0;
}
a {
color: inherit;
text-decoration: underline;
}
p {
margin: 0.83rem 0;
}
.quote-wrapper {
margin-top: 20px;
}
.quote-wrapper a {
text-decoration: none;
}
.quote-wrapper a:hover {
color: #ffffff;
}
.empty-quote {
color: #ffffff;
}
form {
padding: 20px;
}
В этом файле мы обновляем стили CSS нашего приложения в файле style.css
.
Мы установили и зарегистрировали поставщика средства проверки с целью проверки данных, вводимых пользователями при регистрации. Также мы обновили содержание таблицы стилей, добавив в приложение дополнительные стили. На последнем шаге мы проведем тестирование нашего приложения.
На этом шаге мы запустим наше приложение и создадим пользователя и пароль для тестирования аутентификации. Также мы добавим в приложение цитату и просмотрим ее на главной странице.
Чтобы протестировать приложение, запустите сервер разработки, выполнив следующую команду в корневой директории вашего приложения:
- adonis serve --dev
Приложение будет запущено на порту, заданном в файле root .env
, а именно на порту 3333
. Откройте в браузере адрес http://localhost:3333.
Сейчас главная страница пустая, поскольку мы не создали никаких цитат. Нажмите кнопку Регистрация.
Введите свои данные и нажмите кнопку Отправить, чтобы завершить процедуру регистрации. Вы будете перенаправлены на страницу входа. Введите свой адрес электронной почты и пароль для аутентификации.
После аутентификации нажмите кнопку Создать цитату.
Введите цитату и перейдите на страницу Показать все для ее просмотра.
Мы протестировали приложение, создав пользователя, пройдя аутентификацию и написав цитату.
В этом обучающем руководстве мы создали веб-приложение с помощью AdonisJs. Мы настроили приложение с помощью AdonisJs CLI и использовали CLI для создания других важных файлов, в том числе контроллеров, моделей и представлений.
В этой инфраструктуре вы можете создавать веб-приложения любого размера и сложности. Исходный код проекта можно загрузить на GitHub здесь. Дополнительную информацию можно найти в официальной документации.
Если вы хотите посмотреть наши другие обучающие руководства по инфраструктуре JavaScript, обратите внимание на следующие:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!