## Set up
> adonis install @adonisjs/validator
- Đăng kí Validator Provider
File start/app.js
<!-->
const providers = [
'@adonisjs/validator/providers/ValidatorProvider'
]
-->
## Ví dụ cơ bản
File start/routes.js
> Route.resource('users', 'UserController')
Tạo file resources/views/user/create.edge
<!-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Hello Adonis</title>
{{ style('style') }}
{{ cspMeta() }}
</head>
<body>
<div class="subtitle">
<form method="POST" action="{{ route('UserController.store') }}">
<div>
<input type="text" name="email" value="{{ old('email', '') }}" />
<br/>
{{ elIf('<span>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
</div>
<div>
<input type="text" name="password" />
<br/>
{{ elIf('<span>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
</div>
{{ csrfField() }}
<br/>
<button type="submit"> Submit </button>
</form>
</div>
</body>
</html>
-->
File app/Controllers/Http/UserController.js
<!-->
'use strict'
const { validate } = use('Validator')
...
class UserController {
...
async create ({ request, response, view }) {
return view.render('user.create')
}
async store ({ request, response }) {
const rules = {
email: 'required|email|unique:users,email',
password: 'required'
}
const validation = await validate(request.all(), rules)
if (validation.fails()) {
session
.withErrors(validation.messages())
.flashExcept(['password'])
return response.redirect('back')
}
return response.route('UserController.index')
}
...
}
-->
Cơ bản xử lý:
1. Định nghĩa quy tắc mà post data phải đúng chuẩn mới được xử lý
2. Sử dụng method validate với tham số đầu vào là post data, tham số thứ 2 là quy tắc cần được áp dụng
3. kiểm tra với `validation.fails()`, nếu bằng true(tức là post data không đúng quy tắc)
thì ghi lỗi vào session flash và trở về trang trước đó
## Validator methods
1. validate(data, rules, [messages], [formatter])
Ví dụ: const validation = await validate(data, rules)
`validate` dừng xủ lý ngay khi phát hiện 1 rule bất kì không thỏa điều kiện.
2. validateAll(data, rules, [messages], [formatter])
Ví dụ: const validation = await validateAll(data, rules)
Khác với `validate` là `validateAll` sẽ quét qua tất cả các rules rồi mới dừng lại.
3. sanitize(data, rules)
Phương thức này trả về một đối tượng mới với dữ liệu được làm sạch
<!-->
const { sanitize } = use('Validator')
const data = sanitize(request.all(), rules)
-->
4. sanitizor
Trả về một tham chiếu sanitizor từ lớp Validator
<!-->
const { sanitizor } = use('Validator')
const slug = sanitizor.slug('My first blog post')
-->
5. formatters
Trả về một tham chiếu formatters từ lớp Validator
<!-->
const { formatters } = use('Validator')
validate(data, rules, messages, formatters.JsonApi)
-->
## Route validator
Để code gọn gàn hơn, sạch đẹp hơn.
Chúng ta sẽ đăng kí validator ngay ở phần khai báo route.
1. Cập nhật file start/routes.js
<!-->
// For a single route
Route
.post('users', 'UserController.store')
.validator('StoreUser')
// For a resourceful route
Route
.resource('users', 'UserController')
.validator(new Map([
[['users.store'], ['StoreUser']],
[['users.update'], ['UpdateUser']]
]))
-->
2. Tạo file Validator
> adonis make:validator StoreUser
==> File mới được tạo ra ở `app/Validators/StoreUser.js`
Cập nhật lại nội dung file như bên dưới:
<!-->
'use strict'
class StoreUser {
get validateAll () {
return true
}
get sanitizationRules () {
return {
email: 'normalize_email',
// age: 'to_int',
password: 'to_string'
}
}
get rules () {
return {
email: 'required|email|unique:users',
password: 'required'
}
}
get messages () {
return {
'email.required': 'You must provide a email address.',
'email.email': 'You must provide a valid email address.',
'email.unique': 'This email is already registered.',
'password.required': 'You must provide a password'
}
}
}
module.exports = StoreUser
-->
3. Chỉnh sửa lại file app/Controllers/Http/UserController.js
<!-->
async store ({ request, response }) {
// TODO: save data to database...
return response.route('UserController.index')
}
-->
4. Tùy chỉnh validation failure
Nếu bạn không thích cách hệ thống làm tự động, ban có thể xử lý lại như bên dưới:
<!-->
class StoreUser {
async fails (errorMessages) {
return this.ctx.response.send(errorMessages)
}
}
module.exports = StoreUser
-->
5. Validate các giá trị nằm ở header
Đôi khi ngoài việc validate post data, ta cần phải validate cả các giá trị nằm trên header gửi đến
<!-->
class StoreUser {
get rules () {
return {
sessionId: 'required'
}
}
get data () {
const requestBody = this.ctx.request.all()
// lấy session id từ header
const sessionId = this.ctx.request.header('X-Session-Id')
return Object.assign({}, requestBody, { sessionId })
}
}
module.exports = StoreUser
-->
6. Format kết quả trả về
<!-->
const { formatters } = use('Validator')
class StoreUser {
get formatter () {
return formatters.JsonApi // trả về json cho API
}
}
-->
7. Authorization
Trong trường hợp bạn muốn kiểm tra lại permission của user trước khi cho phép thực hiện.
<!-->
class StoreUser {
async authorize () {
if (!isAdmin) {
this.ctx.response.unauthorized('Not authorized')
return false
}
return true
}
}
module.exports = StoreUser
-->
8. Request context
Tất cả các route validators đều có thể truy cập vào đối tượng request(request object) thông qua this.ctx
## Custom Rules
Các rule mở rộng
1. unique(tableName, [fieldName], [ignoreField], [ignoreValue])
Kiểm tra giá trị nhập vào của field đó đã tồn tại trong DB chưa.
<!-->
'use strict'
class StoreUser {
get rules () {
return {
email: 'unique:users,email' // kiểm tra email đã tồn tại hay chưa
}
}
}
-->
Trong trường hợp update mà email không thay đổi thì cần igonre cái field này
<!-->
class StoreUser {
get rules () {
const userId = this.ctx.params.id
return {
email: `unique:users,email,id,${userId}`
}
}
}
-->
## Extending Validator
1. Thêm định nghĩa rule mới
<!-->
const Validator = use('Validator')
const Database = use('Database')
const existsFn = async (data, field, message, args, get) => {
const value = get(data, field)
if (!value) {
/**
* skip validation if value is not defined. `required` rule
* should take care of it.
*/
return
}
const [table, column] = args
const row = await Database.table(table).where(column, value).first()
if (!row) {
throw message
}
}
Validator.extend('exists', existsFn)
-->
2. Đăng ký ở Providers hoặc ở Ignitor Hooks
3. Sử dụng
get rules () {
return {
post_id: 'exists:posts,id'
}
}
Không có nhận xét nào:
Đăng nhận xét