如何使用AdonisJs和MySQL构建励志报价应用程序

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Tech Education Fund 来接受捐赠。

介绍

AdonisJs 是一个 Node.js Web 框架,用纯 JavaScript 编写,可在所有主要操作系统上运行。 它使用流行的 MVC(模型 - 视图 - 控制器) 设计模式,并为编写服务器端 Web 应用程序提供了一个稳定的生态系统。 该框架具有无缝身份验证、SQL ORM(对象关系映射)、迁移数据库播种。 AdonisJs 与 PHP Web 应用程序框架 Laravel 具有相似的架构,包括相同的文件夹结构和几个共享的设置概念。

默认情况下,AdonisJs 使用专为直观使用而设计的 Edge 模板引擎。 就像 Laravel 一样,AdonisJs 附带一个称为 Lucid 的 ORM,它用作应用程序模型和数据库之间通信的接口。 使用 AdonisJs,开发人员可以构建一个全栈应用程序,其中后端服务器将负责应用业务逻辑、路由和渲染应用程序的所有页面。 还可以创建 Web 服务 API 以从控制器返回 JSON 响应; 然后可以使用 Vue.jsReactAngular 等前端框架来使用这些 Web 服务。

在本教程中,您将使用 AdonisJs 的 CLI 构建一个应用程序。 您将在应用程序中创建路由、控制器、模型和视图,并执行表单验证。 本教程中的示例将是一个励志报价应用程序,用户可以在其中注册并登录以创建励志报价。 此演示应用程序将使您有机会执行 CRUD(创建、读取、更新和删除)操作。

先决条件

在开始本指南之前,您将需要以下内容:

  • Node.js(至少 v8)和 npm(至少 v3.0)的本地安装。 Node.js 是一个 JavaScript 运行时环境,允许您在浏览器之外运行代码。 它带有一个名为 npm 的预安装包管理器,可让您安装和更新包。 要在 macOS 或 Ubuntu 18.04 上安装这些,请按照 如何在 macOS 上安装 Node.js 和创建本地开发环境中的步骤或 使用 PPA 部分安装 中的步骤如何在 Ubuntu 18.04 上安装 Node.js。
  • MySQL 安装在您的机器上。 按照此处的说明下载并安装它以供您选择操作系统。 要成功安装 MySQL,您可以在 Mac 上使用 Homebrew 安装它,或者对于 Ubuntu 18.04,请按照我们的教程 如何在 Ubuntu 18.04 上安装 MySQL。
  • 对 JavaScript 有基本的了解; 请参阅我们的 如何在 JavaScript 中编写代码系列。
  • 已安装文本编辑器,例如 Visual Studio CodeAtomSublime Text

注意:本教程使用macOS机器进行开发。 如果您使用的是其他操作系统,您可能需要在第一步中将 sudo 用于 npm 命令。


第 1 步 — 安装 Adonis CLI

在本节中,您将在本地计算机上安装 Adonis CLI 及其所有必需的软件包。 CLI 将允许您构建一个新的 AdonisJs 项目,并为您的应用程序中的控制器、中间件和模型创建和生成样板。 您还将为项目创建数据库。

运行以下命令,通过 npm 在您的机器上全局安装 AdonisJs CLI:

npm i -g @adonisjs/cli

安装过程完成后,在终端输入以下命令确认安装 AdonisJs 并查看当前版本:

adonis --version

您将看到显示当前 AdonisJs 版本的输出:

Output4.1.0

随着 AdonisJs CLI 的成功安装,您现在可以访问并使用 adonis 命令来创建 AdonisJs 项目的全新安装,管理您的项目,并生成相关文件,例如控制器、模型等.

现在,您可以使用 adonis 命令继续创建一个新的 AdonisJs 项目,如下所示:

adonis new adonis-quotes-app

上述命令将在本地项目目录中的同名新目录中创建一个名为 adonis-quotes-app 的应用程序,并具有相关的 AdonisJs MVC 结构。

移动到新的应用程序文件夹:

cd adonis-quotes-app

然后通过运行启动您的应用程序:

adonis serve --dev

这将在您的应用程序的根 .env 文件中指定的默认端口 3333 上启动开发服务器。 导航到 http://localhost:3333 以查看 AdonisJs 的欢迎页面。

现在您将完成数据库的设置。 在这里,您将安装 mysql 驱动程序 以通过 npm 从 Node.js 应用程序连接到 MySQL 服务器。 首先,返回到当前正在运行应用程序的终端,使用 CTRL + C 停止进程并运行以下命令:

npm i mysql

现在您已经成功地为这个应用程序安装了 MySQL Node.js 驱动程序,您需要创建应用程序数据库并设置到它的适当连接。

您从先决条件教程安装的最新版本的 MySQL 使用名为 caching_sha2_password 的默认身份验证插件。 MySQL 的 Node.js 驱动程序当前不支持此功能。 为避免您的应用程序出现任何数据库连接问题,您需要创建一个新的 MySQL 用户并使用当前支持的身份验证插件 - mysql_native_password

首先,使用 root 帐户访问 MySQL 客户端:

mysql -u root -p

系统会提示您输入在 MySQL 安装期间设置的 root 帐户密码。

接下来,使用 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';

通过运行以下命令重新加载授权表以应用您刚刚所做的更改:

FLUSH PRIVILEGES;

您将看到以下输出:

OutputQuery OK, 0 rows affected (0.00 sec)

退出 MySQL 客户端:

quit;

您已经成功安装了 AdonisJs CLI,创建了一个新的 AdonisJs 项目,并通过 npm 安装了 mysql。 您还为此应用程序创建了数据库,并设置了一个具有相应权限的 MySQL 用户。 这是您的应用程序的基本设置,在下一节中,您将开始为您的应用程序创建必要的视图。

第 2 步 — 使用边缘模板引擎

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

此命令将自动在您的 resources/views/layouts 文件夹中创建一个 master.edge 文件。 打开新文件:

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>

在此文件中,您包含 Bootstrap CSS、Bootstrap JavaScript、jQuery 的 CDN 文件。 添加一个全局 CSS 文件名 style.css 并在 div 中包含一个名为 navbarpartial 文件。 要在应用程序的多个页面中重用您需要的 HTML 代码片段,例如 navfooter,您可以合并部分代码。 这些是包含重复代码的较小文件,因此可以更快地在一个地方更新这些元素的代码,而不是在每次出现时更新。 navbar 包含 LoginRegister 按钮、徽标和主页链接的标记。

有了这个,将为该应用程序创建的所有后续页面都可以扩展主布局并呈现 navbar,而无需重新编写内容。 您将在本教程后面创建此 navbar 文件。

最后,您定义一个部分标记 @!section() 以包含来自其他页面的内容并让它们由主布局呈现。 为使其按预期工作,将扩展主布局的所有新页面还必须定义具有相同名称的部分标记(即 @section(``'``content``'``))。

完成编辑后保存并退出文件。

接下来,您将使用 adonis 命令创建导航栏:

adonis make:view navbar

您将看到类似于以下内容的输出:

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="/">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

然后添加以下代码:

/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 布局。 此页面现在可以访问 master 布局中包含的所有库、样式表和 navbar。 接下来,您使用内置的 @each 标签遍历 quotes 数组。 quotes 数组将从您将在本教程后面创建的 QuoteController 传递到此视图。 如果没有引号,将显示适当的消息。

保存并退出此文件。

现在,要创建登录页面,请从终端运行以下命令:

adonis make:view auth/login

您将看到类似于以下内容的输出:

Output✔ create  resources/views/auth/login.edge

这将在 resources/views 中自动创建一个 auth 文件夹,并在其中创建一个 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 在从您的应用程序发送 POSTPUTDELETE 请求时将使用它来传递 CSRF 访问令牌。

这是为了保护您的应用程序免受 Cross-Site Request Forgery (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

添加以下代码:

资源/视图/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 表单,用于在注册过程中收集用户的 nameemailpassword . 还包括 模板:CsrfField(),因为它是 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="/" 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="/" 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="/" 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 附带一个名为 Lucid ORM 的 ORM,它提供了 活动记录 实现来处理您的数据库。 它消除了编写从数据库中实时检索数据的 SQL 查询的麻烦。 这在处理需要大量查询的复杂应用程序时特别有用。 例如,可以通过编写以下代码来从应用程序中检索所有引号:

const quotes = await Quote.all()

要继续为您的应用程序数据库进行适当的配置,请确保您仍在应用程序的根目录中并创建一个 .env 文件:

nano .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_USERDB_PASSWORDDB_DATABASE 占位符替换为您的凭据。

接下来,您将使用 Adonis CLI 为 Quote 创建模型和迁移文件。 为此,请运行以下命令:

adonis make:model Quote --migration

您将看到类似于以下内容的输出:

Output✔ create  app/Models/Quote.js
✔ create  database/migrations/1568209992854_quote_schema.js

此命令将在 app/Models 文件夹中为 Quote 创建一个模型,并在 database/migrations 文件夹中创建一个模式文件。 新创建的模式文件将以当前时间戳为前缀。 使用以下命令打开架构文件:

nano database/migrations/1568209992854_quote_schema.js

使用以下代码更新其内容:

数据库/迁移/...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_idusernamebody 将创建的报价。 user_idusername 字段引用创建特定报价的用户的详细信息。 这定义了 一对多关系 并且意味着用户可以拥有无限数量的报价,而单报价只能属于一个用户。

保存并退出文件。

AdonisJs默认安装了User模型及其迁移文件,只需稍作修改即可建立UserQuote模型之间的关系。

app/Models/User.js中打开User模型:

app/Models/User.js

tokens() 方法之后立即添加此方法:

应用程序/模型/User.js

...
class User extends Model {
  ...
  tokens () {
    return this.hasMany('App/Models/Token')
  }

  quote () {
    return this.hasMany('App/Models/Quote')
  }
}

module.exports = User

这将使用 user_id 作为外键与 Quote 表建立一对多关系。

保存并退出文件。

结束本节,使用以下命令运行迁移,它将执行所有迁移文件的 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 模型及其对应的模式文件,并在 UserQuote 之间创建了 一对多 关系。 接下来,您将生成路由并创建控制器来处理 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

使用以下内容更新它:

应用程序/控制器/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():此方法将通过 AdonisJs 中内置的 request 方法获取发布的 emailpassword 的值,然后验证此用户是否数据库中的详细信息。 如果这样的用户存在于数据库中并且输入了正确的凭据,他们将被重定向回主页并进行身份验证,然后才能创建新报价。 否则,将显示一条指示错误凭据的消息。
  • postRegister():这将接收 usernameemailpassword 的值,供用户在数据库中为该用户创建帐户。 指示此类用户已成功创建的消息将传递给会话,并且用户将被重定向到登录页面以进行身份验证并开始创建报价。
  • 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

使用以下内容更新它:

应用程序/控制器/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():获取特定报价的id,从数据库中检索,并呈现在编辑报价页面上。
  • edit():从数据库中获取特定报价的详细信息并渲染它以供编辑。
  • update():处理对报价的任何更新并将用户重定向回主页。
  • destroy():删除特定报价并将其从数据库中完全删除。

保存并退出文件。

在为这个应用程序创建了所有必要的控制器之后,您现在可以设置路由,以便用户可以轻松地与您的应用程序交互。 首先,导航到 start/routes.js 文件

nano start/routes.js

将其内容替换为以下内容:

开始/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 动词,并将路由绑定到每个控制器中的特定方法。 您还可以命名这些路由中的每一个,因为它们已在控制器和视图中被引用。

为确保只有经过身份验证的用户才能访问所有报价路由,您分配了一个名为的组中间件。 最后,将验证器方法附加到 register.store 路由以验证用户输入。

保存并退出文件。

您已经创建了控制器并为您的应用程序设置了路由。 接下来,您将创建此步骤中定义的验证器方法。

第 5 步 - 验证用户输入

AdonisJs 默认没有内置验证器。 因此,您将手动为您的应用程序安装和注册验证器。

运行以下命令来安装它:

adonis install @adonisjs/validator

打开以下文件以注册验证器提供程序:

nano start/app.js

然后通过将验证器提供程序附加到提供程序列表来注册验证器提供程序,如下所示:

开始/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

这将在 App/validators 目录中创建一个 Register.js 文件。 使用以下命令打开文件:

nano app/Validators/Register.js

将以下代码添加到文件中:

应用程序/验证器/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

将其内容替换为以下内容:

/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;
}

在此文件中,您可以在 style.css 文件中更新应用程序的 CSS 样式。

您已经安装并注册了一个验证器提供程序,用于在注册过程中检查用户的输入。 您还更新了样式表的内容以向应用程序添加更多样式。 在最后一步中,您将测试您的应用程序。

第 6 步 — 为应用程序提供服务

在此步骤中,您将为应用程序提供服务并创建用户和密码以测试身份验证。 您还将向您的应用添加报价并在主页上查看。

要测试您的应用程序,请从应用程序的根目录使用以下命令启动开发服务器:

adonis serve --dev

这将在根 .env 文件中定义的端口上启动应用程序,即 3333。 从浏览器导航到 http://localhost:3333。

由于您尚未创建任何报价,因此主页目前是空的。 单击注册按钮。

输入您的详细信息,然后单击提交按钮完成注册过程。 您将被重定向到登录页面。 输入您的电子邮件地址和密码以进行身份验证。

通过身份验证后,单击 创建报价 按钮。

输入报价并导航至 查看全部 页面以查看您的报价。

您已经通过创建和验证用户然后编写报价来测试您的应用程序。

结论

在本教程中,您已经使用 AdonisJs 构建了一个 Web 应用程序。 您使用 AdonisJs CLI 设置应用程序并利用 CLI 创建其他相关文件,例如控制器、模型和视图。

无论大小和复杂程度如何,您都可以使用此框架构建 Web 应用程序。 随意在 GitHub 上的 此处 下载此项目的源代码。 要探索更多功能,您还可以访问官方文档

如果您想探索我们的其他一些 JavaScript 框架教程,请查看以下内容: