CHƯƠNG 3 : HIỆN THỰC MƠ HÌNH MVC
3.3 GỬI DỮ LIỆU RA VIEW
3.3.1. GIỚI THIỆU
Views chứa mã HTML, hiển thị giao diện web đến người dùng. Thông thường, các views được lưu trữ tại resources/views. Ví dụ minh họa 1 view được lưu trữ tại resources/views/greeting.blade.php
Tên view được đặt theo cú pháp sau: NAME.blade.php.
Theo mẫu MVC, view được gọi từ controller để hiển thị nội dung gửi đến người dùng. Ngồi ra, Laravel cịn cho phép gọi đến view từ lúc khai báo route. Ví dụ minh họa:
class UserController extends Controller { public function __construct(){
$this->middleware('auth'); $this->middleware('log')->only('index'); $this->middleware('subscribed')->except('store'); } } <html> <body> <h1>Hello World</h1> </body> </html>
Dùng View::exists('emails.customer') để kiểm tra view có tồn tại hay không.
3.3.2. TÙY BIẾN TRONG VIEW Gửi dữ liệu đến view Gửi dữ liệu đến view
Theo cú pháp sau:
Trong đó, $array_data là một mảng các giá trị được gửi đến view. View nhận chỉ số của mảng làm biến, giá trị của biến chính là giá trị của chỉ số trong mảng được gửi.
Ví dụ 1: Gửi thông tin sinh viên đến view. Thông tin sinh viên được lưu trữ trong mảng:
$student_info = [‘id’ => 1, ‘name’ => ‘Inona’, ‘sex’ => ‘male’]
Tại view view_student (view_student.blade.php) sẽ nhận được 3 biến tương ứng với 3 chỉ số của mảng, giá trị của biến tương ứng với giá trị của chỉ số trong mảng.
$id = 1
$name = ‘Inona’ $sex = ‘male’ Blade Templates
Hai điểm chính thể hiện lợi ích khi sử dụng view trong Laravel: tính kế thừa và Route::get('/', function () {
return view('VIEW_NAME'); });
view('VIEW_NAME', $array_data);
Ví dụ 2: Tạo view resources/views/layouts/app.blade.php
$yield, $sections được đưa ra nhằm thể hiện tính kế thừa như trong lập trình hướng đối tượng. Có một layout master như một lớp cha, các lớp con kế thừa và hiện thực các hàm mẫu.
Kế thừa layout
Tiếp tục ví dụ trên, xét view resources/views/child.blade.php kế thừa view app.php <html> <head> <title>App Name - @yield('title')</title> </head> <body> @section('sidebar')
This is the master sidebar. @show <div class="container"> @yield('content') </div> </body> </html> @extends('layouts.app')
@section('title', 'Page Title') @section('sidebar')
@parent
<p>This is appended to the master sidebar.</p>
@endsection
@section('content')
@extends cho phép view child.php kế thừa từ layout app.php
@section có hai tham số, tham số thứ 1 thể hiện vị trí của nhãn @yield trong
layout master, tham số thứ 2 là giá trị cần thay thế
@section có 1 tham số, thể hiện vị trí cần thay thế. Trong trường hợp này được
kết thúc bằng @endsection
@parent giữ lại nội dung cần thay thế và cập nhật thêm vào @include nhúng view
Hiển thị dữ liệu
Views nhận chỉ số của mảng (từ nơi gửi ra view) làm biến. Dùng cú pháp sau để hiển thị giá trị ngoài view
Chú ý: sử dụng {{ }} để ngăn chặn cách tấn công XSS. Một số lệnh PHP cần nhớ trong views Lệnh if Thay vì viết: {{ $name }}. HOẶC <?php echo $name ?> HOẶC {!! $name !!}. <?php if ($number == 1):?> Laravel <?php endif?>
Có thể viết
Tương tự, Laravel cung cấp cú pháp sau:
Lệnh lặp 3.4 TRUY VẤN DỮ LIỆU 3.4.1. GIỚI THIỆU @if($number == 1) Laravel @endif //Lệnh if @if(Biểu thức) @else: @endif //Lệnh isset @isset(Biến) @endisset //Lệnh for
@for ($i = 0; $i < 10; $i++) The current value is {{ $i }} @endfor
//Lệnh foreach
@foreach ($users as $user)
<p>This is user {{ $user->id }}</p> @endforeach
//Lệnh while @while (true)
<p>I'm looping forever.</p> @endwhile
Laravel hỗ trợ mạnh mẽ các tính năng đến lập trình viên khi xử lý với database. Ngay cả việc, hướng đến đối tượng tiếp cận đã quen với cách viết SQL thuần thông qua bộ hỗ trợ query builder. Laravel giới thiệu cách xử lý với mơ hình ORM thơng qua Eloquent.
Hiện nay có rất nhiều ORM (Object-Relational Mapping) như Doma, Hypernate, … Eloquent là một trong số các ORM đó. Có thể hiểu ORM là một ánh xạ của cơ sở dữ liệu vào các đối tượng, chỉ cần tương tác trên các đối tượng thay vì phải tương tác trực tiếp với cơ sở dữ liệu.
Hiện tại, Laravel cung cấp các hỗ trợ tương tác với các database như: MySQL, PostgreSQL, SQLite, SQLServer.
3.4.2. CẤU HÌNH DATABASE
Thơng tin cấu hình database được khai báo tại config/database.php. Trong file này, khai báo tất cả thơng số cấu hình liên quan đến database.
'mysql' => [ 'read' => [ 'host' => '192.168.1.1', ], 'write' => [ 'host' => '196.168.1.2' ], 'driver' => 'mysql', 'database' => 'database', 'username' => 'root', 'password' => '', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', ],
Mặc định, cấu hình đơn giản nhất được khai báo tại file thiết lập môi trường .env tại thư mục gốc của Laravel.
Các thông số cần thiết khi khai báo một database gồm: host (địa chỉ, nơi lưu trữ database), username (tên đăng nhập database), password (mật khẩu đăng nhập), port (cổng cài đặt database, mặc định 3306).
3.4.3. TRUY VẤN DỮ LIỆU ĐƠN GIẢN
Khi đã cấu hình thành cơng thơng tin kết nối database, DB facade được sử dụng để thực hiện các phương thức cho các kiểu truy vấn như: select, update, insert, delete và câu SQL.
Thực hiện câu truy vấn SELECT trong ứng dụng
DB:select nhận 2 thông số, thông số thứ 1 là câu truy vấn SQL, thông số thứ 2 là danh sách các giá trị được ánh xạ tuần tự tới vị trí đã được đánh dấu bằng dấu ‘?’ trong thống số thứ 1. Kết quả trả về là một array, với mỗi phần tử thuộc kiểu StdClass là thơng tin của một dịng dữ liệu trong database.
Ví dụ nhận kết quả dữ liệu trả về
Laravel hỗ trợ cách thức ánh xạ dữ liệu từ thông số thứ 2 đến thông số thứ 1 dựa vào tên thay vì dựa vào tính tuần tự ánh xạ như ví dụ trên.
Thực hiện câu truy vấn INSERT trong ứng dụng
<?php
namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; use App\Http\Controllers\Controller; class UserController extends Controller {
/**
* Hiển thị danh sách người dùng phù hợp với điều kiện. *
* @return Response */
public function index() {
$users = DB::select('select * from users where active = ?', [1]);
return view('user.index', ['users' => $users]); }
}
foreach ($users as $user) { echo $user->name;
Để thực hiện thêm một dịng dữ liệu mới thơng qua truy vấn INSERT, Laravel cung cấp cú pháp tương tự như truy vấn SELECT
Thực hiện câu truy vấn UPDATE trong ứng dụng
Để thực hiện cập nhật dịng dữ liệu đã có trong database. Số dịng dữ liệu được cập nhật được trả về khi thực hiện truy vấn UPDATE
Thực hiện câu truy vấn DELETE trong ứng dụng
Phương thức delete trong DB facade được dùng để xóa dữ liệu trong database. Tương tự như phương thức update, số dòng dữ liệu được tác động được trả về khi thực hiện phương thức delete
Thực hiện câu truy vấn trong ứng dụng
Để thực hiện câu truy vấn khác, có thể mơ tả câu SQL trong phương thức statement
3.4.4. TRUY VẤN DỮ LIỆU QUAN HỆ
Việc phát triển ứng dụng tách biệt với hệ quản trị cơ sở dữ liệu là yêu cầu thiết yếu của các ứng ụng. Khi việc chuyển đổi hệ quản trị không ảnh hưởng tới ứng dụng. ORM (Object-relational mapping) là kỹ thuật lập trình giúp ánh xạ các record dữ liệu sang đối tượng.
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
$deleted = DB::delete('delete from users');
DB::statement('drop table users');
$result = DB::table('users')->insert(['email' => 'john@example.com', 'votes' => 0]
Hình 3- 1 Kiến trúc tổng quan ứng dụng
Với kỹ thuật như trên, việc tương tác với database do ORM quản lý. Khi đó tầng ứng dụng chỉ cần sử dụng những gì ORM cung cấp để phát triển ứng dụng. Laravel hiện thực tầng ORM với hai kỹ thuật: query builder và eloquent ORM.
Ví dụ sử dụng query builder để thực hiện truy vấn dữ liệu
Ví dụ sử dụng eloquent để thực hiện truy vấn dữ liệu
Laravel hỗ trợ tương tác với bốn cơ sở dữ liệu
MySQL
PostgreSQL
SQLite
SQL Server
Ngoài bốn phương thức cơ bản (select, insert, update, delete) như mô tả ở trên do query builder cung cấp. Trong phần này mô tả thêm các phương thức khác.
Laravel query builder dùng kỹ thuật PDO để bảo vệ cơ sở dữ liệu tránh các lỗi tấn cơng SQL injection. Do đó, khơng cần thực hiện thêm thao tác xóa ký tự đặc biệt, xóa các mã độc, …
Lấy tất cả các hàng từ một bảng
$results = DB::select('select * from users);
Dùng phương thức table trong DB để thực hiện truy vấn.
Lấy một dòng với các điều kiện
Lấy dòng dữ liệu đầu tiên (trong số nhiều dòng thỏa điều kiện)
Chỉ định rõ các cột cần lấy trong truy vấn select
Quan hệ inner join
Laravel query builder cung cấp phương thức join để xử lý các vấn đề quan hệ inner join trong cơ sở dữ liệu. Nhờ đó, ứng dụng có thể truy vấn quan hệ trên nhiều bảng dữ liệu khác nhau.
$users = DB::table('users')->get(); foreach ($users as $user) {
echo $user->name; }
$user = DB::table('users')->where('name', 'John')->first(); echo $user->name;
$users = DB::table('users')->select('name', 'email as user_email')- >get();
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get();
Quan hệ left join
3.5 BÀI TẬP
1) Tiếp tục phát triển bài tập tại mục 2.3), trong đó dữ liệu được truy vấn từ database Thiết kế database đề nghị như sau:
a) Thay đổi thiết kế database sao cho phù hợp với yêu cầu b) Tạo dữ liệu mẫu cho các bảng dữ liệu
c) Hiển thị dữ liệu được truy vấn từ cơ sở dữ liệu $users = DB::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get();
CHƯƠNG 4: TƯƠNG TÁC DATABASE VỚI ELOQUENT ORM ELOQUENT ORM
Giới thiệu
Eloquent ORM đã được tích hợp trong Laravel, cung cấp ActiveRecord đầy đủ, đơn giản để làm việc với database. Thông thường, mỗi bảng trong database sẽ có một ‘Model’ tương ứng, và model này được sử dụng để tương tác với bảng.
Mục tiêu
Kết thúc chương này, sinh viên có thể:
- Chọn lựa được Query Builder hay Eloquent ORM để tương tác với database
- Sử dụng được Eloquent ORM để tương tác với database
4.1 TỔNG QUAN
Thơng tin cấu hình database được lưu trữ tại: config/database.php.
Tất cả model được kế thừa từ lớp model của hệ thống Illuminate\Database\Eloquent\Model
Có thể hiểu, Eloquent ORM được cung cấp bởi Laravel, là cầu nối trung gian cho việc truy cập database
Hình 4- 1 Kiến trúc Eloquent ORM
Hình 4- 2 Eloquent ORM tương tác với các model trong Laravel - Nguồn Dev.To Ví dụ 1: Cho bảng dữ liệu Flight trong cơ sở dữ liệu, model tương ứng là Ví dụ 1: Cho bảng dữ liệu Flight trong cơ sở dữ liệu, model tương ứng là
Khai báo tên bảng $table = 'my_flights';
Khai báo khóa chính $primaryKey = ‘flight_id’ <?php namespace App;
use Illuminate\Database\Eloquent\Model; class Flight extends Model {
protected $table = 'my_flights'; }
Đối với khóa chính có thuộc tính AI thì thiết lập thuộc tính: $incrementing = true. Ngược lại thiết lập false.
Khai báo thời gian tạo và cập nhật
Eloquent giả sử trong bảng tồn tại 2 cột: created_at, updated_at. Giá trị hai cột này sẽ được tự động cập nhật nếu thiết lập $timestamps = true. Ngược lại sẽ có giá trị false. Khi đã tạo model, việc truy vấn dữ liệu trở nên đơn giản hơn.
Ví dụ 2: Hiển thị dữ liệu trong bảng flights thông qua model flights
<?php
use App\Flight;
$flights = App\Flight::all(); foreach ($flights as $flight) { echo $flight->name;
}
<?php namespace App;
use Illuminate\Database\Eloquent\Model; class Flight extends Model {
//Hiện thực code
protected $primaryKey = 'flight_id'; }
Phương thức all trả về tất cả dữ liệu trong bảng. Ngoài ra, Eloquent get sẽ thêm các điều kiện ràng buộc khi truy vấn dữ liệu.
Ví dụ 3: Truy vấn dữ liệu với những ràng buộc
4.1.1. TRUY VẤN SINGLE MODEL
Cả hai phương thức all, get đều trả về nhiều dòng dữ liệu. Sử dụng phương thức find, first để trả về 1 dòng dữ liệu.
$flights = App\Flight::where('active', 1) ->orderBy('name', 'desc') ->take(10)
Ví dụ 4: truy vấn trả về 1 dịng dữ liệu duy nhất (nếu có)
Đếm số kết quả hoặc tìm giá trị lớn nhất
4.1.2. INSERT, UPDATE MODEL
Khi thêm dữ liệu, trong Eloquent rất đơn giản, chỉ việc tạo đối tượng cho model và thiết lập các thuộc tính, các giá trị của cột và gọi đến phương thức save.
Ví dụ 5: Thêm thơng tin 1 dịng dữ liệu trong model
<?php
namespace App\Http\Controllers; use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class FlightController extends Controller { public function store(Request $request) { $flight = new Flight;
$flight->name = $request->name; $flight->save();
} }
$flight = App\Flight::find(1);
$flight = App\Flight::where('active', 1)->first(); $flights = App\Flight::find([1, 2, 3]);
$count = App\Flight::where('active', 1)->count(); $max = App\Flight::where('active', 1)->max('price');
Đối với cập nhật dữ liệu, trước tiên phải tìm ra được dịng dữ liệu cần cập nhật sau đó thiết lập các giá trị mới và gọi lại phương thức save
Ví dụ 6: Cập nhật giá trị của 1 dịng dữ liệu có id = 1
4.1.3. XĨA DỮ LIỆU
Tương tự như cập nhật dữ liệu, xóa dữ liệu cũng phải tìm ra được dịng cần xóa và gọi đến phương thức delete
Ví dụ 7: Xóa dịng dữ liệu có id = 1
Ngồi ra, Eloquent cịn cung cấp cơ chế cho phép xóa nhiều dịng dữ liệu với điều kiện cho trước
Ví dụ 8: Xóa dịng dữ liệu với điều kiện cho trước
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->save();
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->delete();
4.2 RELATIONSHIPS
Các bảng trong cơ sở dữ liệu thường có mối quan hệ lẫn nhau. Ví dụ: một blog (bảng blog) có thể có nhiều bình luận (bảng comments).
Có ba mối quan hệ chính giữa các bảng
o One to one o One to many o Many to many
4.2.1. ONE TO ONE
Đây là mối quan hệ 1:1, ví dụ 1 người có 1 mã số chứng minh nhân dân. Hoặc là 1 người dùng 1 số điện thoại
Ví dụ 1: User – Phone
<?php
namespace App;
use Illuminate\Database\Eloquent\Model; class User extends Model{
public function phone(){
return $this->hasOne('App\Phone'); }
4.2.2. ONE TO MANY
Mối quan hệ này trong trường hợp 1 model quan hệ với nhiều dòng trong 1 model khác. Ví dụ 1 bài post có nhiều bình luận (comment)
Ví dụ 2: Một bài post có nhiều bình luận (comment)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model; class Post extends Model
{
public function comments() {
return $this->hasMany('App\Comment'); } } <?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model{
public function post() {
return $this->belongsTo('App\Post'); }
4.2.3. MANY TO MANY
Là mối quan hệ phức tạp hơn one-to-one, one-to-many. Ví dụ một user có nhiều quyền (role), một role cũng có nhiều user. Như vậy, sẽ có ba bảng dữ liệu: users, roles,
role_user.
Việc khai báo mối quan hệ cũng hoàn toàn tương tự:
+ Định nghĩa phương thức roles trong User model
+ Định nghĩa phương thức usres trong Role model
<?php namespace App;
use Illuminate\Database\Eloquent\Model; class Role extends Model{
public function users(){
return $this->belongsToMany('App\User'); } } <?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model {
public function roles(){
return $this->belongsToMany('App\Role'); }
4.3 COLLECTIONS
Cung cấp nhiều thư viện tích hợp để xử lý database, nhằm giảm thời gian phát triển của lập trình viên.
Ví dụ khi truy vấn dữ liệu, kết quả trả về là json. Cấu trúc gọi hoàn toàn tương tự như hàm all, get
Phương thức: sortBy sắp xếp
Phương thức sum tính kết quả trả về Phương thức count: đếm số kết quả trả về
all diffAssoc keyBy only sort
average diffKeys keys pad sortBy
avg dump last partition sortByDesc
chunk duplicates macro pipe sortDesc
collapse duplicatesStrict make pluck sortKeys
collect each map pop sortKeysDesc
combine eachSpread mapInto prepend splice
concat every mapSpread pull split
contains except mapToGroups push sum
containsStrict filter mapWithKeys put take
count first max random takeUntil
4.4 MUTATORS
Accessors và Mutators cho phép định dạng các thuộc tính dữ liệu trong Eloquent khi lấy ra hay thiết lập các giá trị trong model. Ví dụ: mã hóa ngày tháng khi lưu vào database, giải mã ngày tháng khi lấy ra. Việc này giúp ích cho hệ thống có cùng định dạng ngày tháng, giúp cho việc tìm kiếm ngày tháng sẽ nhanh hơn.
Accessors sẽ tự động được gọi bởi Eloquent khi “lấy ra” giá trị của thuộc tính.
Mutators sẽ tự động được gọi bởi Eloquent khi “thiết lập” giá trị của thuộc tính.
4.4.1. ĐỊNH NGHĨA ACCESSOR
Để định nghĩa một accessor
Bước 1: Khai báo hàm getFooAttribute trong model, trong đó Foo là tên cột Bước 2: Hiện thực hàm
Ví dụ 1: Định nghĩa hàm getFirstNameAttribute cho cột first_name trong bảng user
như sau:
<?php namespace App;
use Illuminate\Database\Eloquent\Model; class User extends Model{
public function getFirstNameAttribute($value){ return ucfirst($value);
} }
Quy cách đặt tên cột trong bảng được đề nghị là: chữ thường, nếu có từ 2 từ trở lên sẽ được ngăn cách bởi dấu “_”. Khi đó, hàm accessor sẽ được viết hoa từ đầu của từ trong tên cột.