1. AdonisJS là gì?

Nodejs là một công nghệ đang nổi, đồng nghĩa với việc Javascript ngày càng trở nên phổ biến hơn. Có rất nhiều framework node js được sinh sôi hàng ngày. Trong đó có một MVC framwork cũng đang phổ biến "AdonisJS".

AdonisJs được lấy cảm hứng từ một Php Framework gọi là Laravel. Nó mượn các khái niệm về tiêm phụ thuộc và các nhà cung cấp dịch vụ để viết mã đẹp có thể kiểm chứng được tới cốt lõi của nó. Kế thừa những tính năng nổi bật của nodejs, Adonis cũng tập trung vào một số thành phần khác hỗ trợ như:

  • Powerful ORM to make secure SQL queries.
  • API & Session based Authentication System.
  • Easy way to send emails via SMTP or Web Service (Mailgun, Mandrill, etc.)
  • Validate & Sanitise every user’s inputs.
  • Strong emphasis on security.
  • Extendable application layout.

2. Cài đặt Adonis như thế nào?

Yêu cầu cơ bản!

Cũng có một phần chuyên biệt, document của adonis cũng dễ tìm hiểu và sử dụng. Hướng dẫn cài đặt cho Adonis chúng ta cũng có thể tìm hiểu tại:

http://adonisjs.com/docs/3.2/installation

Về cơ bản, chúng ta cần phải đạt các yêu cầu theo từng phiên bản, chẳng hạn phiên bản mới nhất hiện nay là V3.2:

  • Nodejs: >= v4.0.0
  • Và npm: >= 3.0.0

Adonis-CLI

  • Để cài đặt Adonis-CLI: npm i -g adonis-cli
  • Tương tự với laravel/installer, Adonis-CLI sử dụng để tạo mới project:
adonis new project_name
  • Mở rộng với Adonis-CLI:
Flag Value Description
--skip-install Boolean Bỏ qua cài đặt các package từ npm hoặc yarn
--branch String Chọn branch source để cài đặt, mặc định là branch master
--blueprint String Tạo một project từ repo git (ex: adonisjs/adonis-app)
--yarn/--npm Boolean sử dụng npm hoặc yarn để cài đặt các module

Khởi tạo project mới...

  • Sau khi cài đặt thành công chúng ta nhận được kết quả:
✔ Your current Node.js & npm version match the AdonisJs requirements!

⠋ Cloning master branch of adonisjs/adonis-app blueprint
    clone: Repository cloned

⠧ Installing dependencies using npm
  • Tiếp tục chạy lệnh:
cd project_name
npm run serve:dev
  • Nếu nhận được kết quả sau thì bạn đã cài đặt và tạo mới một project với Adonis thành công:
[nodemon] starting `node server.js`
info adonis:framework serving app on http://localhost:3333
  • Mặc định Adonis sử dụng cổng 3333. Nào hãy mở http://localhost:3333 để tận hưởng thành quả nào!!!

3. Khám phá AdonisJS

3.1 Cấu trúc thư mục.

Thiết kế lấy cảm hứng từ laravel, Adonis cũng có một cấu trúc thư mục gần giống với laravel các phiên bản trước đây:

├── app
│   ├── Commands
│   ├── Http
│   ├── Listeners
│   ├── Model
├── bootstrap
├── config
├── database
│   ├── migrations
│   └── seeds
├── providers
├── public
├── resources
│   └── views
├── storage

Nếu các bạn đã từng làm việc qua với laravel, hẳn chúng ta cũng đoán được chức năng của từng thư mục rồi chứ!

Name Chức năng
app Nơi chứa các thành phần chính của app như Controller , Middleware , Routes, Model, Listeners, hay Commands
bootstrap Nơi chứa những file khởi tạo và đăng ký app như app.js, events.js, extend.js
config Tương tự trên laravel, thư mục này chứa những file config cho hệ thống như database, session, auth...
database Chứa các file migration, seeder, hay factory để chúng ta khởi tạo dữ liệu với DB như trên laravel hay lưu trữ cơ sở dữ liệu SQLite.
providers Nơi đăng ký những provider có sẵn hoặc bên thứ 3 để sử dụng trong hệ thống
public Chứa các thành phần như ảnh, css, javascript.
resources Nơi chứa views (template Nunjucks).
storage Nơi chứa các file biên dịch template, session hay log hệ thống.

3.2 Ace - Config - Autoload - Provider - Alias

3.2.1 Ace - powerful command line tool crafted for AdonisJs

Tương tự với Artisan của laravel, Ace cũng được sử dụng để tạo các thành phần như controllers, models, chạy migrations hay chạy những command line của provider. Ngoài ra chúng ta cũng có thể tạo cho riêng mình những command line riêng, chúng được đặt trong thư mục app/Commands, đồng thời để Ace có thể sử dụng được, chúng ta cần đăng ký command line vừa tạo trong file bootstrap/app.js. Bạn có thấy giống với laravel ko nào? Để tìm hiểu thêm bạn có thể thử chạy câu lệnh: /ace -h hoặc có thể tìm hiểu thêm tại link

Usage: ace [options] [command]
  Commands:

    greet <name>                      Greet a user with a name
    auth:setup                        Setup migrations and models for authentication
    repl                              Start a new repl session when goodness of Es6 generators
    make:controller [options] <name>  Create a new controller
    route:list                        List all Routes registered for this app
    make:migration [options] <name>   Create a new migration file
    make:model [options] <name>       Create a new model with optional migration
    make:view [options] <name>        Create a new template view by optionally extending a master view
    make:command <name>               Create a new ace command
    make:hook [options] <name>        Create a new hook for your models
    make:middleware [options] <name>  Create a new middleware for Http requests
    make:seed <name>                  Create a new seeder
    make:listener [options] <name>    Create a new listener for your events
    migration:run [options]           Run all pending migrations and optionally seed database
    migration:rollback [options]      Rollback migrations to a given or last batch
    migration:refresh [options]       Refresh migrations by dropping and re-running all migrations
    migration:reset [options]         Reset migrations to latest batch
    db:seed [options]                 Seeds database by running all or a given seed file
    migration:status                  Check migrations current status
    key:generate [options]            Generate encryption key for your application

  Options:
    -h, --help     output usage information
    -V, --version  output the version number

  Extras:
    [command] --help output command detail info

3.2.2. Configuration.

Config được sử dụng bằng cách nạp Provider: Adonis/Src/Config .

  • Giống với laravel, config trong Adonis cũng cung cấp cho ta hàm để có thể get, set config.
Phương thức Chức năng Ví dụ
get(key, [defaultValue]) Get giá trị config. Config.get('database.host', 'localhost')
set(key, value) Set giá trị config. Config.set('database.host', '127.0.0.1')
  • Các file config được lưu tại thư mục: config

3.2.3. Autoload - Provider - Alias

  • Autoload trong Adonis được config ở file package.json:
"autoload": {
    "App": "./app"
  },
  • Provider: là những package của bên thứ 3 hoặc các package mở rộng. Trong laravel chúng ta cài đặt các package qua composer thì với Adonis chúng ta cài đặt thông qua npm hoặc yarn. Các package tải về sẽ được lưu trong node_modules. Để sử dụng được các provider, chúng ta cần khai báo chúng trong file bootstrap/app.js
  • Alias: bằng cách khai báo này chúng ta có thể gọi provider một cách ngắn gọn Command thay vì Adonis/Src/Command.
const aliases = {
  Command: 'Adonis/Src/Command',
  Config: 'Adonis/Src/Config',
}

3.3. Routing & Middleware.

3.3.1 Routing.

Adonis cũng hỗ trợ hầu hết các loại route như của laravel:

  • Các method cơ bản như: Route.get, Route.post, Route.put, Route.patch, Route.delete
  • Hay muốn custom một route khác:
const Route = use('Route')
// SINGLE VERB
Route.route('/', 'COPY', function * (request, response) { })

// MULTIPLE VERBS
Route.route('/', ['COPY', 'MOVE'], function * (request, response) { })
  • Hoặc đáp ứng cho app SPA: any(url, action)
Route.any('*', function * (request, response) {
  yield response.sendView('home')
})
  • Nhóm các route lại thành 1 group hay thêm prefix: group(uniqueName, callback)
Route.group('admin', function () {
  Route.get('users', function * (request, response) {
    // ...
  })
}).prefix('backend')
  • Đặt tên cho route: as(name)
#Route:
Route
  .get('users/:id', 'UserController.show')
  .as('profile')
#View
{{ linkTo('profile', 'View Profile', { id: 1 }) }}
  • Hoặc route resource: resource(name, controller)
Route.resource('users', 'UserController')
  • Còn nhiều phương thức hỗ trợ cho route rất mạnh mẽ nữa, bạn có thể tìm hiểu tại Routing

3.3.2. Middleware.

Về cơ bản, middleware trong Adonis được đặt trong folder app/Http/Middleware.

  • Chúng ta có thể tạo middleware bằng ace: ./ace make:middleware BackendMiddleware Middleware trong Adonis vẫn chưa được hỗ trợ mạnh mẽ như trên laravel, về cơ bản chúng ta có thể thấy:
  • Middleware cho route:
# Single
Route.get('/authenticated', function * (request, response) {
  response.send('This route is authenticated')
}).middleware('auth')

#Multiple
Route.get('/secured', function * (request, response) {
  response.send('This route is authenticated')
}).middleware(['auth', 'custom'])
  • Bạn có thể tìm hiểu thêm về cách đặt tên, xử lý request và response trong middleware tại Middleware Document

3.4. Controller - View

3.4.1. Controller

  • Controller trong Adonis được khai báo trong folder: app/Http/Controllers
  • Tạo một controller bằng ace:
#Tạo một controller blank
./ace make:controller Home

# Tạo một controller resource
./ace make:controller User --resource
  • Về cơ bản, route trong Adonis cũng giống như trong Laravel, bạn có thể tìm hiểu thêm tại Controllers

3.4.2 View

View trong Adonis cũng được hỗ trợ mạnh mẽ như trên laravel. Adonis sử dụng Nunjucks làm view.

  • View được đặt tại folder resources/views và extension là .njk, khi run app, view được compile ra thư mục storages.
  • Chúng ta có thể tạo các layout, file partial để tái sử dụng lại, hoặc cache view để app có thể chạy nhanh hơn.
  • Để tìm hiểu thêm về view trong Adonis, bạn có thể xem thêm:
  • Ví dụ về sử dụng template trong AdonisJS:
# master.njk
<html>
  <body>

    <header class="header">
      {% block header %}
        Common Header
      {% endblock %}
    </header>

    <section class="sidebar">
      {% block sidebar %}
        Common Sidebar
      {% endblock %}
    </section>

    <section class="content">
      {% block content %}{% endblock %}
    </section>

  </body>
</html>
# Use template in resources/views/home.njk
{% extends 'master' %}

{% block content %}
  Here comes the content of the home page.
{% endblock %}
#Output
<html>
  <body>

    <header class="header">
      Common Header
    </header>

    <section class="sidebar">
      Common Sidebar
    </section>

    <section class="content">
      Here comes the content of the home page.
    </section>

  </body>
</html>

3.5. Database - Model - Relation

3.5.1. Database

Tuy là một framework nodejs nhưng Adonis chưa hỗ trợ chính thức cho các cơ sở dữ liệu NoSQL. Muốn kết nối với các cơ sở dữ liệu NoSQL như MongoDB thì phải sử dụng đến những provider của bên thứ 3. Chẳng hạn như:

Với điểm trừ như vậy nhưng Adonis lại hỗ trợ rất tốt cho những DB khác như: PostgreSQL, SQLite, MySQL, MariaDB, Oracle, MSSQL. Như vậy cũng là đủ dùng rồi chứ các bạn.

  • Database trong Adonis cũng tương tự như trên Laravel, chúng ta có thể config ở file .env hoặc config trực tiếp trong file config ở config/database.js.
  • Adonis cũng hỗ trợ rất tốt việc debug Sql hay conenct Multi DB.
  • Ngoài ra, Adonis còn hỗ trợ Migrations hay Seeds And Factories

3.5.2 Model.

Liệu với một framework nodejs có hỗ trợ mạnh mẽ việc trừu tượng hóa DB hay không? Với cảm hứng từ Laravel, liệu model trong Adonis có gì hay ho? Câu trả lời là có, Adonis hỗ trợ mạnh mẽ việc tương tác với cơ sở dữ liệu.

Nếu chúng ta đã từng làm việc với laravel, việc sử dụng Query Builder cho đến Model để tương tác với cơ sở dữ liệu là khá đơn giản. Trong Adonis cũng vậy, việc tương tác với cơ sở dữ liệu cũng khá đơn giản thông qua Query Builder hoặc Model. Model trong Adonis sử dụng Lucid, là một package nodejs, lucid kế thừa những điểm mạnh mẽ của Active record. Chúng ta cùng xem Lucid có gì hay nhé!!!

  • Tạo model ư, dễ dàng với một dòng lệnh:
./ace make:model User

# or with migration
./ace make:model User --migration
  • Tương tự trên laravel, chúng ta có thể set connection cho model, chỉ định table trong model, hay set timestamp cho các cột.
  • Scope trong model ư, quá dễ dàng với Query Scopes trong Lucid.
  • PHP có traits, Adonis cũng hỗ trợ traits
  • Những phương thức như CRUD ư, quá đơn giản.
  • Ngoài ra, Lucid còn có những phương thức mạnh mẽ khác tương tự Eloquent như first(), find(), pair(), createMany()... và nhiều hơn nữa ở đây Lucid Mothods
  • Liệu Lucid có transaction không? Có chứ, nó mạnh mẽ không kém trong laravel. Bạn có thể tìm hiểu thêm về transaction tại đây
  • Trong laravel có Accessors hay Mutators, Adonis cũng có chứ. Trong Adonis ngoài Getters hay Setters còn có thêm Computed Properties.
  • Hooks trong Adonis cũng rất mạnh mẽ, các hook cơ bản cho việc create, update, delete hay restore, Adonis còn hỗ trợ chúng ta trong việc addHook hay removeHook cũng khá đơn giản. Bạn có thể tìm hiểu thêm tại đây.

3.5.3. Relationships

Trừu tượng hóa cơ sở dữ liệu thành từng đối tượng, không thể thiếu relationship. Adonis cũng hỗ trợ mạnh mẽ trong việc tạo và sử dụng relationship giữa các model với nhau, giúp giảm tải việc tương tác trực tiếp với cơ sở dữ liệu, giảm tải việc viết query và dễ tối ưu code. Có các loại relationship cơ bản như:

  • Has One Relationship
  • BelongsTo Relationship
  • HasMany Relationship
  • BelongsToMany Relationship
  • HasManyThrough Relationship

Adonis còn hỗ trợ cả Lazy Loading, Eager Loading hay cả Lazy Eager Loading Relationship mạnh mẽ là thế, để ứng dụng nó vào trong việc giao tiếp model - model, model - database, Adonis cũng cung cấp các hàm để giúp bạn query dễ dàng qua relationship như:

  • Filtering Records: has, whereHas, doesntHave, whereDoesntHave
  • CRUD: save, create, saveMany, createMany, attach, detach, sync ...
  • Pivot: updatePivot, withPivot...

3.6. Validation

Việc validate dữ liệu là một yếu tố quan trọng của bất kỳ framework nào. Trong Adonis, chúng ta có thể sử dụng validate trong controller, trong provider hoặc trong listeners:

  • Sử dụng trong controller:
# model
class User extends Lucid {
  static get rules () { 
    return {
      username: 'required|unique:users',
      email: 'required|email|unique:users',
      password: 'required|confirmed',
    }
  }
}

# controller
const Validator = use('Validator')
const User = use('App/Model/User')

class UsersController {

  * store(request, response) {
    const userData = request.all()
    const validation = yield Validator.validate(userData, User.rules)  

    if (validation.fails()) { 
      response.json(validation.messages()) 
      return
    }
  }

}
  • VIệc customize validatation cũng dễ dàng ví dụ:
const Validator = use('Adonis/Addons/Validator')
 Validator.extend('adult', (data, field, message, args, get) => {

   return new Promise((resolve, reject) => {
     const fieldValue = get(data, field)
     if (fieldValue > 18) {
       resolve('Allowed')
       return
     }
     reject(message)
   })

 }, 'You must be an adult')

Có một điểm trừ đó là Adonis chưa có form request để thuận tiện việc validate form như trên laravel.

4. Kết luận.

Adonis là một framwork nodejs khá mới, tuy nhiên nó cũng có những ưu điểm riêng nhất định. Adonis có tốc độ của ứng dụng nodejs, sức mạnh của việc kế thừa Active record, việc trừu tượng hóa cơ sở dữ liệu thành từng đối tượng khiến cho việc tương tác với cơ sở dữ liệu là khá dễ dàng. Với những ưu thế là vậy, nhưng vẫn còn những điểm yếu như chưa hỗ trợ chính thức NoSQL, hay việc custom validate và sử dụng vào form request.... Mong rằng trong những phiên bản tiếp theo, Adonis sẽ hỗ trợ những điều đó.

Còn rất nhiều điểm mạnh của Adonis mà chúng ta chưa thể đề cập hết như làm việc với Web socket, Redis, Authenticators, vấn đề bảo mật trong của Adonis như CSRF Protection, CORS hay Shield Middleware mà chúng ta sẽ đề cập đến trong những bài viết tiếp theo.Hi vọng rằng bài viết hữu ích đối với các bạn.

Một số thứ về Adonis: