Khởi tạo dự án Laravel 8 đầu tiên.
Trang 1PHẦN 1: KHỞI TẠO DỰ ÁN LARAVEL 8.x
Lab 1: Cài WampServer (Wampserver 3.2.0 64 bit x64)
Khi cài đặt chỉ nên chọn CSDL Maria DB, không chọn MySQL để tiết kiệm dung lượng ổ cứng
Lab 2 : Cài đặt Composer (Composer 2.x)
Nhớ chọn đường dẫn đến tập tin php.exe có phiên bản phù hợp với Laravel 8.x
Lab 3 : Cài đặt Laravel 8.x
Chuyển tới thư mục www
Lệnh cài:
composer create-project laravel/laravel larashop
Lab 4: B ỏ “public” khỏi đường dẫn
Đổi tên tập tin server.php ở thư mục chính thành index.php
Sao chép tập tin htaccess trong thư mục public ra ngoài thư mục chính
Bình thường, chúng ta sử dụng HTTP Server của Apache để chạy dịch vụ, nếu chúng ta không muốn bỏ “public” khỏi đường dẫn, và muốn sử dụng
HTTP Server tích hợp sẵn của PHP, thì dùng lệnh artisan từ dấu nhắc …\www\larashop>
php artisan serve
với http://127.0.0.1/larashop/public) Màn hình CMD phải được bật trong suốt quá trình chạy dịch vụ
Biên soạn: Nguyễn Hoàng Tùng Giấy phép CC BY-NC 4.0 Quốc tế
Trang 2Nếu cổng 8000 bị trùng thì chạy lại lệnh để đổi cổng khác
php artisan serve port=8001
Lab 5: T ạo Model – Controller – Migration bằng lệnh artisan
Chuyển tới thư mục www/larashop
Các lệnh:
php artisan make :model LoaiSanPham - mcr
php artisan make :model SanPham - mcr
php artisan make :model DonHang - mcr
php artisan make :model DonHang_ChiTiet - mcr
Ý nghĩa tham số:
Nếu không muốn tạo các hàm rỗng bên trong các tập tin controllers thì bỏ tham số -r đi
Ví dụ:
php artisan make :model LoaiSanPham - mc
php artisan make :model SanPham - mc
Lab 6: Ch ỉnh sửa các tập tin CSDL Migrations vừa tạo ra từ Lab 5
Mô tả CSDL:
- Bảng: loaisanpham
Trang 3- Bảng: sanpham
- Bảng: donhang
- Bảng: donhang_chitiet
Nội dung các tập tin migrations:
Các tập tin migrations nằm trong thư mục database/migrations
Laravel đã tạo sẵn 3 tập tin migrations (users, password_resets, failed_jobs)
Xem Lab 8 để xem cách đổi tên các bảng mặc định
- Loại sản phẩm
Trang 4public function up ()
{
Schema :: create ( 'loaisanpham' , function Blueprint $table ) {
$table -> id ();
$table ->string( 'tenloai' );
$table ->string( 'tenloai_slug' );
$table -> timestamp ( 'created_at' )-> useCurrent ();
$table -> timestamp ( 'updated_at' )-> useCurrentOnUpdate ();
$table -> engine = 'InnoDB' ;
});
}
- Sản phẩm
public function up ()
{
Schema :: create ( 'sanpham' , function Blueprint $table ) {
$table -> id ();
$table -> foreignId ( 'loaisanpham_id' )-> constrained ( 'loaisanpham' ); $table ->string( 'tensanpham' );
$table ->string( 'tensanpham_slug' );
$table ->integer( 'soluong' );
$table ->double( 'dongia' );
$table ->string( 'hinhanh' )-> nullable ();
$table -> text ( 'motasanpham' )-> nullable ();
$table -> timestamp ( 'created_at' )-> useCurrent ();
$table -> timestamp ( 'updated_at' )-> useCurrentOnUpdate ();
$table -> engine = 'InnoDB' ;
});
}
- Đơn hàng
public function up ()
{
Schema :: create ( 'donhang' , function Blueprint $table ) {
$table -> id ();
$table -> foreignId ( 'user_id' )-> constrained ( 'users' );
$table ->string( 'dienthoaigiaohang' , 20 );
$table ->string( 'diachigiaohang' );
$table -> tinyInteger ( 'tinhtrang' )->default( );
$table -> timestamp ( 'created_at' )-> useCurrent ();
$table -> timestamp ( 'updated_at' )-> useCurrentOnUpdate ();
$table -> engine = 'InnoDB' ;
});
}
Trang 5- Đơn hàng chi tiết
public function up ()
{
Schema :: create ( 'donhang_chitiet' , function Blueprint $table ) { $table -> id ();
$table -> foreignId ( 'donhang_id' )-> constrained ( 'donhang' ); $table -> foreignId ( 'sanpham_id' )-> constrained ( 'sanpham' ); $table ->integer( 'soluongban' );
$table ->double( 'dongiaban' );
$table -> timestamp ( 'created_at' )-> useCurrent ();
$table -> timestamp ( 'updated_at' )-> useCurrentOnUpdate (); $table -> engine = 'InnoDB' ;
});
}
- Người dùng
public function up ()
{
Schema :: create ( 'users' , function Blueprint $table ) {
$table -> id ();
$table ->string( 'name' );
$table ->string( 'email' )-> unique ();
$table -> timestamp ( 'email_verified_at' )-> nullable ();
$table ->string( 'password' );
$table -> rememberToken ();
$table -> timestamp ( 'created_at' )-> useCurrent ();
$table -> timestamp ( 'updated_at' )-> useCurrentOnUpdate (); $table -> engine = 'InnoDB' ;
});
}
Lab 7: Ch ỉnh sửa thông số kết nối CSDL trong tập tin env
Tập tin env nằm trong thư mục gốc của dự án (thư mục larashop) APP_NAME=LaraShop
APP_ENV=local
APP_KEY=base64:9KMMj7b+o5FpaBPzUw/P11muXL9U4oH/CE8+H3anEEA=
APP_DEBUG=true
APP_URL=http://127.0.0.1:8080/larashop
LOG_CHANNEL=stack
DB_CONNECTION=mysql
Trang 6DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=larashop
DB_USERNAME=root
DB_PASSWORD=
Lab 8: T ạo CSDL rỗng trong phpMyAdmin
Vào phpMyAdmin tạo CSDL rỗng có tên giống như cấu hình ở Lab 7
Lab 9: Ch ạy lệnh artisan để tạo các bảng
php artisan migrate
Vào phpMyAdmin xem lại các bảng vừa mới sinh ra
Sơ đồ quan hệ giữa các bảng:
Nếu ở bước này có phát sinh lỗi về chiều dài kiểu varchar (too long) thì xem cách fix lỗi tại link:
https://laravel.com/docs/8.x/migrations#index-lengths-mysql-mariadb
Trang 7Lab 10: T ạo form xác thực (Đăng ký, đăng nhập, quên mật khẩu,…)
Cài gói UI bằng lệnh: composer require laravel/ui
Tạo form xác thực bằng lệnh: php artisan ui:auth
Lab 11: Ch ỉnh giao diện Master
- Giao diện master nằm trong thư mục resources/views/layouts
- Nhúng liên kết CSS và JS Bootstrap phiên bản mới nhất
- Chỉnh lại Navbar
- Nhúng Font Awesome 5
<link rel ="stylesheet" href ="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" />
<link rel ="stylesheet" href ="{{ asset('public/css/all.min.css') }}" />
<script src ="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"></script>
- Xem code master đầy đủ tại Lab 15 bên dưới
Lab 12: Ch ỉnh các tập tin Models trong thư mục app/Models, lưu lý hasMany, belongsTo
Laravel đã tạo sẵn model User.php Xem Lab 8 để xem cách đổi User.php thành tên khác (ví dụ: NguoiDung.php)
- Tập tin LoaiSanPham.php
class LoaiSanPham extends Model
{
use HasFactory ;
protected $table 'loaisanpham' ;
// protected $primaryKey = 'id';
// protected $keyType = 'string';
public function SanPham ()
Trang 8{
return $this -> hasMany ( 'App\Models\SanPham' , 'loaisanpham_id' , 'id' );
}
}
- Tập tin SanPham.php
class SanPham extends Model
{
use HasFactory ;
protected $table 'sanpham' ;
// protected $primaryKey = 'id';
// protected $keyType = 'string';
public function LoaiSanPham ()
{
return $this -> belongsTo ( 'App\Models\LoaiSanPham' , 'loaisanpham_id' , 'id' ); }
public function DonHang_ChiTiet ()
{
return $this -> hasMany ( 'App\Models\DonHang_ChiTiet' , 'sanpham_id' , 'id' ); }
}
- Tập tin DonHang.php
class DonHang extends Model
{
use HasFactory ;
protected $table 'donhang' ;
// protected $primaryKey = 'id';
// protected $keyType = 'string';
public function User ()
{
return $this -> belongsTo ( 'App\Models\User' , 'user_id' , 'id' );
}
public function DonHang_ChiTiet ()
{
return $this -> hasMany ( 'App\Models\DonHang_ChiTiet' , 'donhang_id' , 'id' ); }
}
Trang 9- Tập tin DonHang_ChiTiet.php
class DonHang_ChiTiet extends Model
{
use HasFactory ;
protected $table 'donhang_chitiet' ;
// protected $primaryKey = 'id';
// protected $keyType = 'string';
public function DonHang ()
{
return $this -> belongsTo ( 'App\Models\DonHang' , 'donhang_id' , 'id' ); }
public function SanPham ()
{
return $this -> belongsTo ( 'App\Models\SanPham' , 'sanpham_id' , 'id' ); }
}
- Tập tin User.php
class User extends Authenticatable
{
use HasFactory , Notifiable ;
protected $fillable
'name' , 'email' , 'password' ,
];
protected $hidden
'password' , 'remember_token' ,
];
protected $casts
'email_verified_at' => 'datetime' ,
];
public function DonHang ()
{
return $this -> hasMany ( 'App\Models\DonHang' , 'user_id' , 'id' ); }
}
Trang 10Lab 13: Ch ỉnh các tập tin Controllers
Thống nhất tên các hàm để dễ copy/paste
Ví dụ: getDanhSach, getThem, postThem, getSua, postSua, getXoa
- Tập tin: LoaiSanPhamController.php
class LoaiSanPhamController extends Controller
{
public function getDanhSach ()
{
$loaisanpham LoaiSanPham :: all ();
return view ( 'loaisanpham.danhsach' , compact( 'loaisanpham' )); }
public function getThem ()
{
return view ( 'loaisanpham.them' );
}
public function postThem ( Request $request )
{
$orm new LoaiSanPham ();
$orm -> tenloai = $request -> tenloai ;
$orm -> tenloai_slug = Str :: slug ( $request -> tenloai , '-' );
$orm -> save ();
return redirect ()-> route ( 'loaisanpham' );
}
public function getSua ( $id )
{
$loaisanpham LoaiSanPham :: find ( $id );
return view ( 'loaisanpham.sua' , compact( 'loaisanpham' ));
}
public function postSua ( Request $request , $id )
{
$orm LoaiSanPham :: find ( $id );
$orm -> tenloai = $request -> tenloai ;
$orm -> tenloai_slug = Str :: slug ( $request -> tenloai , '-' );
$orm -> save ();
return redirect ()-> route ( 'loaisanpham' );
}
public function getXoa ( $id )
{
Trang 11$orm LoaiSanPham :: find ( $id );
$orm ->delete();
return redirect ()-> route ( 'loaisanpham' );
}
}
- Tương tự như vậy với các tập tin khác Dùng thao tác copy/paste và sửa lại nội dung các hàm cho phù hợp
Lab 14: Ch ỉnh nội dung tập tin web route tương ứng với các hàm trong Controllers (routes/web.php)
<?php
use Illuminate\Support\Facades\Route ;
use App\Http\Controllers\HomeController ;
use App\Http\Controllers\LoaiSanPhamController ;
use App\Http\Controllers\SanPhamController ;
use App\Http\Controllers\DonHangController ;
use App\Http\Controllers\DonHangChiTietController ;
use App\Http\Controllers\UserController ;
Auth :: routes ();
// Trang chủ
Route :: get ( '/' , [ HomeController ::class, 'getHome' ])-> name ( 'frontend' );
// Quản lý Loại sản phẩm
Route :: get ( '/loaisanpham' , [ LoaiSanPhamController ::class, 'getDanhSach' ])-> name ( 'loaisanpham' );
Route :: get ( '/loaisanpham/them' , [ LoaiSanPhamController ::class, 'getThem' ])-> name ( 'loaisanpham.them' );
Route :: post ( '/loaisanpham/them' , [ LoaiSanPhamController ::class, 'postThem' ])-> name ( 'loaisanpham.them' ); Route :: get ( '/loaisanpham/sua/{id}' , [ LoaiSanPhamController ::class, 'getSua' ])-> name ( 'loaisanpham.sua' ); Route :: post ( '/loaisanpham/sua/{id}' , [ LoaiSanPhamController ::class, 'postSua' ])-> name ( 'loaisanpham.sua' ); Route :: get ( '/loaisanpham/xoa/{id}' , [ LoaiSanPhamController ::class, 'getXoa' ])-> name ( 'loaisanpham.xoa' ); // Quản lý Sản phẩm
Route :: get ( '/sanpham' , [ SanPhamController ::class, 'getDanhSach' ])-> name ( 'sanpham' );
Route :: get ( '/sanpham/them' , [ SanPhamController ::class, 'getThem' ])-> name ( 'sanpham.them' );
Route :: post ( '/sanpham/them' , [ SanPhamController ::class, 'postThem' ])-> name ( 'sanpham.them' );
Route :: get ( '/sanpham/sua/{id}' , [ SanPhamController ::class, 'getSua' ])-> name ( 'sanpham.sua' );
Route :: post ( '/sanpham/sua/{id}' , [ SanPhamController ::class, 'postSua' ])-> name ( 'sanpham.sua' );
Route :: get ( '/sanpham/xoa/{id}' , [ SanPhamController ::class, 'getXoa' ])-> name ( 'sanpham.xoa' );
// Quản lý Đơn hàng
Route :: get ( '/donhang' , [ DonHangController ::class, 'getDanhSach' ])-> name ( 'donhang' );
Route :: get ( '/donhang/them' , [ DonHangController ::class, 'getThem' ])-> name ( 'donhang.them' );
Route :: post ( '/donhang/them' , [ DonHangController ::class, 'postThem' ])-> name ( 'donhang.them' );
Route :: get ( '/donhang/sua/{id}' , [ DonHangController ::class, 'getSua' ])-> name ( 'donhang.sua' );
Trang 12Route :: post ( '/donhang/sua/{id}' , [ DonHangController ::class, 'postSua' ])-> name ( 'donhang.sua' );
Route :: get ( '/donhang/xoa/{id}' , [ DonHangController ::class, 'getXoa' ])-> name ( 'donhang.xoa' );
// Quản lý Đơn hàng chi tiết
Route :: get ( '/donhang/chitiet' , [ DonHangChiTietController ::class, 'getDanhSach' ])-> name ( 'donhang.chitiet' );
Route :: get ( '/donhang/chitiet/sua/{id}' , [ DonHangChiTietController ::class, 'getSua' ])-> name ( 'donhang.chitiet.sua' ); Route :: post ( '/donhang/chitiet/sua/{id}' , [ DonHangChiTietController ::class, 'postSua' ])-> name ( 'donhang.chitiet.sua' ); Route :: get ( '/donhang/chitiet/xoa/{id}' , [ DonHangChiTietController ::class, 'getXoa' ])-> name ( 'donhang.chitiet.xoa' ); // Quản lý Tài khoản người dùng
Route :: get ( '/nguoidung' , [ UserController ::class, 'getDanhSach' ])-> name ( 'nguoidung' );
Route :: get ( '/nguoidung/them' , [ UserController ::class, 'getThem' ])-> name ( 'nguoidung.them' );
Route :: post ( '/nguoidung/them' , [ UserController ::class, 'postThem' ])-> name ( 'nguoidung.them' );
Route :: get ( '/nguoidung/sua/{id}' , [ UserController ::class, 'getSua' ])-> name ( 'nguoidung.sua' );
Route :: post ( '/nguoidung/sua/{id}' , [ UserController ::class, 'postSua' ])-> name ( 'nguoidung.sua' );
Route :: get ( '/nguoidung/xoa/{id}' , [ UserController ::class, 'getXoa' ])-> name ( 'nguoidung.xoa' );
Lab 15: Xây d ựng các views ứng với các Controller
Các views nằm trong thư mục resources/views
Một view con phải kế thừa một view master nào đó
Tập tin view phải có phần mở rộng blade.php
<!DOCTYPE html>
<html lang ="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset ="utf-8" />
<meta name ="viewport" content ="width=device-width, initial-scale=1" />
<! CSRF Token >
<meta name ="csrf-token" content ="{{ csrf_token() }}" />
<title>{{ config('app.name', 'Laravel') }}</title>
<! Scripts >
<script src ="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"></script>
@yield('javascript')
<! Styles >
<link rel ="stylesheet"href ="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" />
<link rel ="stylesheet"href ="{{ asset('public/css/all.min.css') }}" />
</head>
<body>
<div id ="app" class ="container-fluid">
<nav class ="navbar navbar-expand-lg navbar-light shadow-sm" style ="background:#ebc7df;">
<div class ="container-fluid">
<a class ="navbar-brand" href ="{{ route('frontend') }}">