One place for hosting & domains

      вдохновляющими

      Создание приложения с вдохновляющими цитатами с помощью AdonisJs и MySQL


      Автор выбрал 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).

      Предварительные требования

      Для прохождения этого обучающего руководства вам потребуется следующее:

      • Локальная установка Node.js (версия не ниже 8) и npm (версия не ниже 3.0). Node.js — это среда исполнения на базе JavaScript, позволяющая выполнять код за пределами браузера. Она содержит предустановленный диспетчер пакетов npm, позволяющий устанавливать и обновлять пакеты. Чтобы установить его в macOS или Ubuntu 18.04, следуйте указаниям руководства Установка Node.js и создание локальной среды разработки в macOS или раздела Установка с помощью PPA руководства Установка Node.js в Ubuntu 18.04.
      • Установленная на компьютере СУБД MySQL. Следуйте приведенным здесь инструкциям для ее загрузки и установки в выбранной операционной системе. Для успешной установки MySQL можно использовать Homebrew для Mac или следовать указаниям руководства Установка MySQL в Ubuntu 18.04 для установки этой СУБД в Ubuntu 18.04.
      • Понимание основных принципов JavaScript; ознакомьтесь с нашей серией Программирование на JavaScript.
      • Установленный текстовый редактор, например Visual Studio Code, Atom или Sublime Text.

      Примечание. Для разработки в этом обучающем руководстве будет использоваться компьютер под управлением macOS. Если вы используете другую операционную систему, вам может потребоваться использовать права sudo для выполнения команд npm на первых шагах.

      Шаг 1 — Установка Adonis CLI

      В этом разделе мы установим Adonis CLI и все его требуемые пакеты на наш локальный компьютер. CLI позволяет создать структуру нового проекта AdonisJs, а также создать и сгенерировать шаблоны контроллеров, связующих элементов и моделей в вашем приложении. Также вы создадите базу данных для проекта.

      Выполните следующую команду для глобальной установки AdonisJs CLI на компьютере с помощью npm:

      После завершения процесса установки введите в терминал следующую команду для подтверждения установки AdonisJs и просмотра текущей версии:

      Вы увидите вывод с указанием текущей версии AdonisJs:

      Output

      4.1.0

      Мы успешно установили AdonisJs CLI и теперь можем использовать команду adonis для установки новых проектов AdonisJs, управления проектами и генерирования требуемых файлов, в том числе контроллеров, моделей и т. д.

      Теперь мы можем перейти к созданию нового проекта AdonisJs, используя команду adonis, как показано здесь:

      • adonis new adonis-quotes-app

      Приведенная выше команда создаст приложение adonis-quotes-app в новой директории с тем же именем внутри директории локального проекта, используя соответствующую структуру AdonisJs MVC.

      Перейдите в папку нового приложения:

      Запустите приложенеи с помощью следующей команды:

      Эта команда запустит сервер разработки на порту по умолчанию 3333, как указано внутри файла root .env для вашего приложения. Введите адрес http://localhost:3333 для просмотра приветственной страницы AdonisJs.

      Приветственная страница AdonisJs

      Теперь мы завершим настройку базы данных. Здесь вы установите драйвер mysql для подключения к вашему серверу MySQL из вашего приложения Node.js с помощью npm. Для начала вернитесь в терминал, где запущено приложение, остановите процесс нажатием CTRL + C и запустите следующую команду:

      Вы успешно установили драйвер MySQL Node.js для этого приложения, и теперь вам нужно создать базу данных приложения и настроить подключение к ней.

      Последняя версия MySQL, установленная согласно указаниям предварительных требований обучающего руководства, использует плагин аутентификации по умолчанию под названием caching_sha2_password. Этот плагин в настоящее время не поддерживается драйверами Node.js для MySQL. Чтобы избежать проблем при подключении вашего приложения к базе данных, вам нужно будет создать нового пользователя MySQL и использовать поддерживаемый плагин аутентификации mysql_native_password.

      Для начала откройте клиент MySQL, используя учетную запись root:

      В диалоге введите пароль учетной записи root, заданный во время установки MySQL.

      Затем создайте пользователя и пароль, используя плагин mysql_native_password:

      • CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Создайте базу данных приложения с помощью следующей команды:

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 1 row affected (0.03 sec)

      Вы успешно создали базу данных для своего приложения.

      Теперь активируйте доступ к созданной базе данных для нового пользователя MySQL. Запустите следующую команду для предоставления всех привилегий пользователю в базе данных:

      • GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';

      Перезагрузите таблицы grant, запустив следующую команду для применения внесенных изменений:

      Результат будет выглядеть следующим образом:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Закройте клиент MySQL с помощью следующей команды:

      Мы успешно установили AdonisJs CLI, создали новый проект AdonisJs и выполнили установку mysql с помощью npm. Также мы создали базу данных для этого приложения и настроили пользователя MySQL с соответствующими правами доступа к нему. Базовая конфигурация приложения готова, и на следующем шаге мы начнем создавать необходимые представления для вашего приложения.

      Шаг 2 — Использование системы шаблонов Edge

      AdonisJs поставляется с собственной системой шаблонов Edge. Это позволяет создать многоразовый шаблон HTML и внести в приложение логику клиентской части с минимальным объемом кода. Edge дает разработчикам приложений JavaScript инструменты для создания схемы на базе компонентов, написания условных выражений, использования итераций и создания уровней представлений для хранения логики. Все файлы шаблонов с расширением .edge хранятся в директории resources/views.

      Далее указаны представления, необходимые приложению для надлежащей работы:

      • Генеральный макет. С помощью Edge вы можете создать страницу, содержащую таблицы CSS, общие файлы JavaScript, jQuery и части пользовательского интерфейса, которые будут едиными для всего приложения, в том числе панель навигации, логотип, заголовок и т. д. После создания генерального макета он будет наследоваться другими представлениями (страницами) вашего приложения.
      • Представление указателя. Эта страница будет использовать генеральный макет для наследования общих файлов, а также выполнять рендеринг содержимого для главной страницы приложения.
      • Страница входа. Эта страница также будет использовать генеральный макет, а также будет выполнять рендеринг формы с полями ввода имени пользователя и пароля для входа пользователей в систему.
      • Страница регистрации. Здесь пользователи найдут форму для регистрации и сохранения своих реквизитов в базе данных.
      • Страница создания цитаты. Пользователи будут использовать эту страницу для создания вдохновляющих цитат.
      • Страница редактирования цитаты. Пользователи будут использовать эту страницу для редактирования цитат.
      • Страница просмотра цитаты. Пользователи будут использовать эту страницу для просмотра определенных цитат.

      Для начала используйте команду adonis для создания страницы генерального макета, как показано здесь:

      • adonis make:view layouts/master

      Результат будет выглядеть примерно так:

      Output

      ✔ create resources/views/layouts/master.edge

      Эта команда автоматически создаст файл master.edge в папке resources/views/layouts. Откройте новый файл:

      • nano resources/views/layouts/master.edge

      Добавьте в него следующий код:

      /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 для создания панели навигации:

      Результат будет выглядеть примерно так:

      Output

      ✔ create resources/views/navbar.edge

      Откройте созданный файл:

      • nano resources/views/navbar.edge

      Затем добавьте в него следующий код:

      /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="https://www.digitalocean.com/">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="https://www.digitalocean.com/#" 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. С этим тегом мы можем написать условное выражение для прошедшего аутентификацию пользователя и выводить соответствующее содержание, когда это требуется. Для прошедшего аутентификацию пользователя приложение отображает имя пользователя и кнопку создания новой цитаты. Если пользователь не прошел аутентификацию, приложение будет отображать кнопку для входа или регистрации. Эта страница будет добавляться как часть каждой другой страницы, как и в случае с генеральным макетом приложения.

      Сохраните и закройте файл.

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

      Вы увидите примерно следующий результат:

      Output

      ✔ create resources/views/index.edge

      Созданный нами файл будет располагаться в директории resources/views/index.edge. Откройте файл:

      • nano resources/views/index.edge

      Добавьте следующий код:

      /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="https://www.digitalocean.com/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="http://www.digitalocean.com/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
                                      <a href="http://www.digitalocean.com/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

      Добавьте следующее содержимое:

      /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

      Добавьте следующий код:

      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

      Добавьте следующее содержание:

      /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="https://www.digitalocean.com/" 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:

      /resources/views/quotes/edit-quote.edge

      @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="https://www.digitalocean.com/" 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

      Добавьте следующий код:

      /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="https://www.digitalocean.com/" 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. Далее мы настроим и создадим подключение к базе данных нашего приложения.

      Шаг 3 — Создание схемы баз данных

      Если мы запустим приложение сейчас, оно выдаст ошибку, поскольку мы не подключили его к базе данных. В этом разделе мы настроим подключение к базе данных, а затем используем команду adonis для генерирования файла миграции, который будет использоваться для создания таблиц для нее.

      В комплект AdonisJs входит модель ORM под названием Lucid ORM, обеспечивающая реализацию активных записей для работы с базой данных. Эта модель избавляет от необходимости писать запросы SQL, извлекающие данные из базы данных в реальном времени. Это особенно полезно при работе над сложными приложениями, для которых требуется большое количество запросов. Например, мы можем получить все цитаты из нашего приложения с помощью следующей команды:

      const quotes = await Quote.all()
      

      Чтобы продолжить настройку базы данных приложения, необходимо убедиться, что вы все еще находитесь в корневой директории вашего приложения, и создать в ней файл .env:

      Откройте созданный файл и добавьте в него следующее содержание:

      .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

      Обновите его содержимое с помощью следующего кода:

      database/migrations/…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: используется для создания новых таблиц и изменения существующих.
      • down: используется для отмены изменений, примененных с помощью метода up.

      В дополнение к полям timestamps() и increments() мы обновим содержание файла схемы, указав атрибуты полей user_id, username и body для создаваемой цитаты. В полях user_id и username указываются данные пользователя, создавшего определенную цитату. Файл построен по принципу отношения одного к многим. Это означает, что пользователю может принадлежать бесконечное количество цитат, а цитата может принадлежать только одному пользователю.

      Сохраните и закройте файл.

      В AdonisJs по умолчанию установлены модель User и ее файл миграции. В связи с этим требуется лишь небольшое изменение для установки отношения между моделями User и Quote.

      Откройте модель User в app/Models/User.js:

      Добавьте этот метод сразу же после метода tokens():

      app/Models/User.js

      ...
      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() для всех файлов миграции:

      Вы увидите примерно следующий результат:

      Output

      migrate: 1503248427885_user.js migrate: 1503248427886_token.js migrate: 1568209992854_quote_schema.js Database migrated successfully in 3.42 s

      Мы настроили и защитили соединение с базой данных. Также мы создали модель Quote и соответствующий файл схемы и создали отношение один ко многим между моделями User и Quote. Далее мы сгенерирурем маршруты и создадим контроллеры для обработки запросов HTTP и бизнес-логики для создания, изменения и удаления вдохновляющей цитаты.

      Шаг 4 — Создание контроллеров и настройка маршрутов

      В этом разделе мы начнем с создания контроллеров для обработки всей логики приложения, а затем прикрепим эти контроллеры к определенному маршруту, чтобы пользователи могли использовать 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

      Добавьте в него следующее содержание:

      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("https://www.digitalocean.com/")
          }
      }
      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

      Добавьте в него следующее содержание:

      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("https://www.digitalocean.com/")
        }
      
        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("https://www.digitalocean.com/")
        }
      
        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("https://www.digitalocean.com/")
        }
      }
      module.exports = QuoteController
      

      В этом контроллере мы импортировали модель Quote и обновили следующие методы, которые были автоматически созданы с помощью AdonisJs CLI:

      • index(): доставка всех цитат из базы данных и их рендеринг на главной странице приложения.
      • create(): рендеринг страницы для создания цитат.
      • store(): сохранение созданной цитаты в базе данных и вывод соответствующего ответа.
      • show(): получение идентификатора определенной цитаты, ее извлечение из базы данных и рендеринг на странице редактирования цитаты.
      • edit(): получение деталей определенной цитаты из базы данных и ее рендеринг для редактирования.
      • update(): обработка любых изменений цитаты и возвращение пользователя на главную страницу.
      • destroy(): удаление определенной цитаты и ее полное удаление из базы данных.

      Сохраните и закройте файл.

      После создания всех необходимых контроллеров для этого приложения мы можем настроить маршруты, чтобы пользователи могли легко взаимодействовать с приложением. Для начала перейдите в файл start/routes.js.

      Замените его содержание на следующее:

      start/routes.js

      'use strict'
      const Route = use('Route')
      
      Route.get("https://www.digitalocean.com/",'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 для проверки вводимых пользователем данных.

      Сохраните и закройте файл.

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

      Шаг 5 — Проверка вводимых пользователем данных

      AdonisJs не имеет встроенных по умолчанию средств проверки. Поэтому средство проверки для вашего приложения нужно установить и зарегистрировать вручную.

      Запустите следующую команду для его установки:

      Откройте следующий файл для регистрации поставщика средства проверки:

      Зарегистрируйте поставщика средства проверки, добавив его в список поставщиков, как показано далее:

      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

      Добавьте в файл следующий код:

      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
      

      Для определенных полей в приложении можно определять правила. Если проверка не будет пройдена на любом этапе, средство проверки автоматически выведет всплывающее сообщение об ошибке и возвратит пользователя в форму.

      Сохраните и закройте файл после завершения редактирования.

      Для добавление стилей в ваше приложение откройте следующий файл:

      Замените его содержание на следующее:

      /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.

      Мы установили и зарегистрировали поставщика средства проверки с целью проверки данных, вводимых пользователями при регистрации. Также мы обновили содержание таблицы стилей, добавив в приложение дополнительные стили. На последнем шаге мы проведем тестирование нашего приложения.

      Шаг 6 — Выполнение приложения

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

      Чтобы протестировать приложение, запустите сервер разработки, выполнив следующую команду в корневой директории вашего приложения:

      Приложение будет запущено на порту, заданном в файле root .env, а именно на порту 3333. Откройте в браузере адрес http://localhost:3333.

      Главная страница приложения с цитатами

      Сейчас главная страница пустая, поскольку мы не создали никаких цитат. Нажмите кнопку Регистрация.

      Страница регистрации

      Введите свои данные и нажмите кнопку Отправить, чтобы завершить процедуру регистрации. Вы будете перенаправлены на страницу входа. Введите свой адрес электронной почты и пароль для аутентификации.

      Страница входа

      После аутентификации нажмите кнопку Создать цитату.

      Страница создания цитаты

      Введите цитату и перейдите на страницу Показать все для ее просмотра.

      Страница просмотра всех цитат

      Мы протестировали приложение, создав пользователя, пройдя аутентификацию и написав цитату.

      Заключение

      В этом обучающем руководстве мы создали веб-приложение с помощью AdonisJs. Мы настроили приложение с помощью AdonisJs CLI и использовали CLI для создания других важных файлов, в том числе контроллеров, моделей и представлений.

      В этой инфраструктуре вы можете создавать веб-приложения любого размера и сложности. Исходный код проекта можно загрузить на GitHub здесь. Дополнительную информацию можно найти в официальной документации.

      Если вы хотите посмотреть наши другие обучающие руководства по инфраструктуре JavaScript, обратите внимание на следующие:



      Source link