Kinh nghiệm laravel
Contents
- 1. SQL
- 2. insert, update, delete, select dữ liệu
- 3. Sử dụng php
- 4. Model
- 5. Truyền dữ liệu sang view
- 6. Middleware
- 7. Seeder – dữ liệu mẫu
- 8. Migration
- 9. Kiểm tra dữ liệu bằng tinker
- 10. Controller
- 11. View
- 12. Authentication
- 13. Hàm chuyển kiểu Date
- 14. Route
- 15. Kết nối với vuejs
- 16. Token Api sanctum
- 17. Password Hash
- 18. Run project
- 19. Phân trang laravel
- 20. Giữ giá trị ô input blade template – old input (Retrieving old input)
- 21. Validate số điện thoại
- 22. Thực tập – Replace content – keyword
- 23. Các khái niệm học thêm được
- 24. Gửi mail
- 25. Resize image when upload
- 26. Core anh Tân
- 27. Encrypt & Decrypt
- Khác
1. SQL
1.1. skip là OFFSET trong SQL
- Muốn bỏ qua 5 record đầu tiên thì sử dụng: skip(5)
$products = $art->products->skip(0)->take(10)->get(); //get first 10 rows $products = $art->products->skip(10)->take(10)->get(); //get next 10 rows
1.2. take là LIMITtrong SQL
- Muốn lấy 5 phần tử thì sử dụng: take(5)
$products = $art->products->skip(0)->take(10)->get(); //get first 10 rows $products = $art->products->skip(10)->take(10)->get(); //get next 10 rows
1.3. orderBy là ORDER BY trong SQL
Ví dụ: muốn sắp xếp tăng dần theo cột id
->orderBy('id', 'DESC');
1.4 join – left join
->leftJoin('task', 'task.id', '=', 'event.task_id')->select('event.*', 'event.id as eventID', 'event.description as eventDescription', 'task.*')
1.5 Get Month, Year
->whereYear('date', '=', $year)->whereMonth('date', $month)
1.6 Like
->where('name', 'like', '%abc%')
1.7 Query điều kiện lồng
DB::table('users')->where(function ($query) use ($activated) { $query->where('activated', '=', $activated); })->get(); /* 1. Viết một function trong where hoặc orWhere 2. Nếu cần sử dụng biến trong function sử dụng thêm từ khóa use sau đó là tên biến */
1.8 Cần query từ từ
$dataQuery = AnyEloquent::query(); $dataQuery->where(....); $dataQuery->orWhere(....); $dataQuery->get(); /* 1. Dùng eloquent trỏ đến phương thức query() 2. Sử dụng theo cấu trúc eloquent như bình thường */
2. insert, update, delete, select dữ liệu
2.1 insert
Sử dụng hàm save() để lưu vào CSDL.
public function themBoMon($request) { $kt = new BomonModel(); $kt->MaBoMon = $$request->maBoMon; $kt->TenBoMon = $$request->tenBoMon; $kt->save(); return true; }
2.2 Update
Lấy đối tượng đó ra, rồi update dữ liệu trường thay đổi. Sử dụng save() để lưu vào CSDL.
public function suaBoMon($maBM, $request) { $kt = BomonModel::where('MaBoMon', '=', $maBM)->first(); $kt->TenBoMon = $request->tenBoMon; $kt->save(); }
2.3 Delete
Sử dụng hàm delete() để xóa CSDL.
public function xoaBoMon($maBM) { $kt = new BomonModel(); $kt->where('MaBoMon', '=', $maBM)->delete(); }
2.4 Select
Khi Select dữ liệu nên chuyển sang dạng mảng để dễ xử lý, và khi trả về mảng bạn lưu ý phải thêm vị trí của phần tử cần lấy vì nó trả về mảng 2 chiều.
//sau khi select nhớ toArray $data = $this->user->where('email', '=', $email)->get()->toArray(); //láy tên của phần tử đầu tiên $khach->setData($data[0]["hoTen"],
Kết các bảng lại với nhau:
$kt = new CoVanModel(); $kq = $kt->join('bomon', 'bomon.MaBoMon', '=', 'CoVanHocTap.MaBoMon')->select('MaCV','HoTen_CV','SDT_CV','TenBoMon')->get()->toArray(); /* Kết bảng CoVanHocTap với Bảng bomon qua trường MaBoMon */
2.5 try catch bắt lỗi truy vẫn
try { //code return true; } catch(\Illuminate\Database\QueryException $ex){ //code return false; }
2.6 Xử lý lỗi khi sử dụng Eloquent
Nhiều khi Eloquent lỗi insert, update, dữ liệu. (như illegal offset type chẳng hạn). Có thể do bảng có 2 khóa chính,… Thay vì ngồi sửa thì hãy sử dụng lớp DB có sẵn của Laravel.
Đầu tiên import này vào
use Illuminate\Support\Facades\DB;
2.6.1 Insert
DB::table('users')->insert( ['email' => 'john@example.com', 'votes' => 0] );
Tham khảo thêm tại: https://laravel.com/docs/8.x/queries
2.7 Tồn tại
public function tonTai($maBm) { $kt = new BomonModel(); $kq = $kt->where('MaBoMon', '=', $maBm)->get()->count(); if($kq>0) return true; else return false; }
2.8 Get một col trong dữ liệu trả về
public function getIDByCode($code) { $item = Order::where("code", "=", $code)->get()->toArray(); if(count($item) > 0) return $item[0]["id"]; else return -1; }
2.9 Join bảng
public function getAllLopAndInfo() { $kt = new LopModel(); $kq = $kt->join('bomon', 'bomon.MaBoMon', '=', 'lop.MaBoMon')->join('covanhoctap', 'covanhoctap.MaCV', '=', 'lop.MaCV')->get()->toArray(); return $kq; } public function getAllThongTinLop() { $kt = new LopModel(); $kq = $kt->join('bomon', 'bomon.MaBoMon', '=', 'lop.MaBoMon')->join('covanhoctap', 'covanhoctap.MaCV', '=', 'lop.MaCV')->select('MaLop', 'TenLop', 'EmailLop', 'HoTen_CV', 'SDT_CV', 'Email_CV', 'TenBoMon')->get()->toArray(); return $kq; }
2.10 Validate Custom
$validation = Validator::make( $request->all(), [ 'title' => 'required|string|max:50', ], [ 'title.required' => trans('validation.required_custom', ['attribute' => trans('table.room.title')]), 'title.max' => trans('validation.max.string', ['attribute' => trans('table.room.title')]), ] ); $validation->after( //Check accept is_accept_policy function ($validation) use ($request) { if ($request->title === 'Test') { $validation->errors()->add('title', trans('validation.title_equal_test')); } } ); if ($validation->fails()) { return $this->jsonValidate($validation->errors()); }
3. Sử dụng php
3.1 Sử dụng class trong php
Tôi bị lỗi này suốt mấy tháng mà không tìm ra, giờ chia sẻ lại cho các bạn kinh nghiệm.
- Khi gọi thuộc tính của class thì đừng cho biến $ vào tên biến
$this->$thuocTinh; //sai $this->thuoctinh; //đúng
- Nếu không new ra đối tượng được khi khai báo biến thì hãy bỏ nó vào contructor
//không được class GuestController extends Controller { private $thongbao_table = new ThongBaoModel(); } //thì làm như thế này class GuestController extends Controller { private $thongbao_table; public function __construct() { $this->thongbao_table = new ThongBaoModel(); } }
3.2 Sử dụng PHP
- Tìm chuỗi trong chuỗi
strpos($chuoi, $tuCanTim) //syntax strpos(string, find, start) //string: Required. Specifies the string to search //find: Required. Specifies the string to find //start: Optional. Specifies where to begin the search. If start is a negative number, it counts from the end of the string. //Returns the position of the first occurrence of a string inside another string, //or FALSE if the string is not found. Note: String positions start at 0, and not 1.
- Constructor trong kế thừa: lớp con kế thừa lớp cha muốn sử dụng lại constructor của lớp cha phải thêm lệnh dưới.
public function __construct() { parent::__construct(); }
3.3 PHP & Javascript
//$info là biến của php //Cần đổ dữ liệu $info sang javascript làm như bên dưới @if( isset($info) ) <script> alert("{{ $info }}"); </script> @endif
4. Model
Các phần phải có trong model. Biến $fillable là các trường được phép chỉnh sửa dữ liệu.
class ThongBaoModel extends Model { protected $table = 'thong-bao'; protected $fillable = ['img', 'title', 'content', 'quote']; public $timestamps = false; }
Nếu bảng khóa chính không phải là id
- Thì thêm các thuộc tính sau vào model của bảng đó
protected $primaryKey = "MaBoMon"; //trường khóa chính protected $keyType = 'string'; //kieur dữ liệu của trường đó
5. Truyền dữ liệu sang view
Hãy sử dụng compact thì khi truyền sang tên biến sẽ không bị thay đổi tên. Tức là truyền qua tên nào thì ở view lấy tên đó xài luôn. Và nó có thể truyền nhiều biến nữa.
$ds = new DanhSachController(); $data = $ds->getDanhSach(); $bm = new BomonModel(); $boMon = $bm->getAllBoMon(); $lp = new LopModel(); $lop = $lp->getAllLop(); return view('admin.trang-chu')->with( compact('data', 'boMon', 'lop') );
6. Middleware
class AdminMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if($request->session()->has('user') && $request->session()->get('user') == 'admin') { return $next($request); } else return redirect("/2"); } }
Đăng ký Kernel
protected $routeMiddleware = [ //'auth' => \App\Http\Middleware\Authenticate::class, //'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, //'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class, //'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, //'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'admin' => \App\Http\Middleware\AdminMiddleware::class, ];
7. Seeder – dữ liệu mẫu
7.1 Cách tạo dữ liệu mẫu
Có bao nhiêu bảng thì tạo bấy nhiêu cái DB::table(”)->insert();
use DB; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('bomon')->insert([ array('MaBoMon'=>'BM01','TenBoMon'=>'Xây dựng'), array('MaBoMon'=>'BM02','TenBoMon'=>'Công nghệ thông tin'), array('MaBoMon'=>'BM03','TenBoMon'=>'Điện - Điện tử'), array('MaBoMon'=>'BM04','TenBoMon'=>'Cơ khí động lực'), ]); DB::table('user')->insert([ array('username'=>'admin','password'=>'123456') ]); } }
7.2 Insert dữ liệu kiểu date
DB::table('phieucham')->insert([ array('maPhieuCham' => '01', 'diem' => 10, 'ngayCham' => '2018-09-05', 'nhanXet' => 'Hoàn thành tốt, có trách nhiệm'), ]); // 'năm-tháng-ngày'
7.3 Sử dụng factory
Tạo factory
php artisan make:factory TenFactory // ví dụ php artisan make:factory PostFactory
Định nghĩa file factory
<?php /** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Post; use Faker\Generator as Faker; $factory->define(Post::class, function (Faker $faker) { return [ 'title' => $faker->sentence(3), 'content' => $faker->paragraphs(10, true), 'lead' => $faker->text(200), 'topic_id' => random_int(1, 20), 'author_id' => random_int(1, 20), ]; });
Sử dụng trong seeder
<?php use Illuminate\Database\Seeder; use App\Post; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { factory(Post::class, 20)->create(); } }
8. Migration
8.1 Thứ tự tạo Migration
Migration sẽ chạy theo thứ tự tạo, nên cái nào không có khóa ngoại tạo trước, cái nào có khóa ngoại tạo sau nha.
Nếu đã lỡ xa chân vào lỗi không thực hiện như trên thì.
- Xóa file migrate mà có khóa ngoại tạo trước đi migration không có khóa ngoại đi, tạo migration có khóa ngoại lại.
- Xóa toàn bộ bảng trong database
Mẹo xóa nhanh: php artisan migrate:reset
localhost/phpmyadmin => xóa 1,2 bảng nữa là ok. - Chạy php artisan migrate
Nếu vẫn chưa được chạy cmd: composer dump-autoload
8.3 Tạo bảng không bị lỗi khóa ngoại
Do khóa ngoại sẽ tham chiếu đến khóa chính. Nên bảng cần tham chiếu khóa chính nên thêm thuộc tính unique().
Schema::create('hocvi', function (Blueprint $table) { $table->bigInteger('maHocVi')->unique(); $table->string('tenHocVi'); $table->timestamps(); });
- Tạo khóa ngoại
public function up() { Schema::create('lop', function(Blueprint $table) { //$table->String('MaLop', 10)->unique(); //$table->String('TenLop', 70); //$table->String('EmailLop', 30); //$table->String('MaBoMon', 10); //$table->String('MaCV', 10); $table->foreign('MaBoMon')->references('MaBoMon')->on('bomon')->onDelete('cascade'); }); } //$table->foreign('CotBangHienTai')->references('CotBangForeign')->on('TenBangForeign')->onDelete('cascade');
8.4 Câu lệnh nên dùng khi tạo migration
Nên tạo bằng câu lệnh này để nó tạo luôn khai báo tên bảng
php artisan make:migration Ten_Migration --create=ten_bang
8.5 Nội dung file migration
- Function up
public function up() { Schema::create('lop', function(Blueprint $table) { $table->String('MaLop', 10)->unique(); $table->String('TenLop', 70); $table->String('EmailLop', 30); $table->String('MaBoMon', 10); $table->String('MaCV', 10); }); }
- Function down
public function down() { Schema::dropIfExists('lop'); }
Hàm Schema
- Tạo bảng
//tạo bảng Schema::create('categories', function (Blueprint $table) { // } //sửa bảng Schema::table('categories', function (Blueprint $table) { // } //đổi tên bảng Schema::rename('category', 'categories'); //Xóa bảng Schema::dropIfExists('categories');
8.6 Khóa chính là kiểu string
Nếu khóa chính là kiểu String thì phải khai báo độ dài cho khóa chính và cho cả các khóa ngoại tham chiếu tới nó.
8.7 Tạo Foreign Key cho database
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class AddForeignKeysToPostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('posts', function (Blueprint $table) { $table->unsignedBigInteger('topic_id')->index()->nullable(); $table->foreign('topic_id')->references('id')->on('topics'); $table->unsignedBigInteger('author_id')->index()->nullable(); $table->foreign('author_id')->references('id')->on('users'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropForeign(['topic_id']); $table->dropColumn('topic_id'); $table->dropForeign(['author_id']); $table->dropColumn('author_id'); }); } }
9. Kiểm tra dữ liệu bằng tinker
Ở thư mục gốc => cmd
php artisan tinker
Nhập câu lệnh và sẽ trả kết quả về cho bạn
10. Controller
10.1 Request
Request gửi tới nhưng bạn không muốn xử lý tại function đó mà muốn chuyển request đó sang funtion khác để xử lý thì làm như bên dưới nhé! Request bỏ zô một biến rồi truyền sang.
<?php public function veryComplexMethod(Request $request) { $data = $request->all(); return $this->veryComplexMethodProcessing($data); } public function veryComplexMethodProcessing($data) { //process data.... return $answer; }
10.2 Upload file
$fileName = ""; $fileSize = ""; if ($rq->hasFile('fileToUpload')) { $file = $rq->fileToUpload; //Lấy Tên files $fileName = $file->getClientOriginalName(); //Lấy kích cỡ của file đơn vị tính theo bytes $fileSize = $file->getSize(); } if($fileName != "" && $fileSize < 10485760) { $file = $rq->fileToUpload; $fileName = url("public/img/upload/".$fileName); $file->move("public/img/upload", $file->getClientOriginalName()); //tham số đầu tiên là đường dẫn thư mục server, lưu ý không sử dụng asset ở đây } else { //code }
Tham khảo thêm tại: https://www.techblog.vn/bai-19-upload-files-trong-laravel
11. View
11.1 Bỏ tham số vào href, action hoặc src
<form action=" {{ asset('thong-tin-can-bo') }}/{{ $email }}" method="post">
12. Authentication
Bài viết này https://agitech.com.vn/vn/bai-viet/website/77-lap-trinh-laravel-dang-nhap-va-phan-quyen có trình bày rõ về cách hoạt động và code của Authentication Laravel. Các bạn xem và tham khảo nó nhé.
13. Hàm chuyển kiểu Date
Ví dụ: Chuỗi “25122020” => “2020-12-25”
private function convertDate($date) { $date_return = substr($date,4,4); $date_return .= substr($date,2,2); $date_return .= substr($date,0,2); return date("Y-m-d", strtotime($date_return)); }
14. Route
14.1 Group
Route::group([ 'prefix' => 'bao-hiem-vien-phi', 'namespace'=>'Api' ], function () { Route::post('/add', 'BaoHiemVienPhiController@themBaoHiemVienPhi'); Route::post('/addPerson', 'BaoHiemVienPhiController@themNguoiDuocBaoHiemVienPhi'); Route::put('/edit', 'BaoHiemVienPhiController@editBaoHiemVienPhi'); Route::get('/cal-fee/{type}/{data}', 'BaoHiemVienPhiController@tinhPhi'); });
14.2 Tạo Route Controller đi vào thêm một cấp thư mục
Thêm vào namespace
Route::group([ 'prefix' => 'bao-hiem-vien-phi', 'namespace'=>'Api' ], function () { Route::post('/add', 'BaoHiemVienPhiController@themBaoHiemVienPhi'); Route::post('/addPerson', 'BaoHiemVienPhiController@themNguoiDuocBaoHiemVienPhi'); Route::put('/edit', 'BaoHiemVienPhiController@editBaoHiemVienPhi'); Route::get('/cal-fee/{type}/{data}', 'BaoHiemVienPhiController@tinhPhi'); });
14.3 Namespace route
Route::namespace('App\Http\Controllers\api')->group(function () { Route::group(['middleware' => 'auth:sanctum'], function() { Route::post('create-event', 'CalendarController@createEvent'); Route::delete('delete-event/{id}', 'CalendarController@deleteEvent'); Route::get('event/{date}', 'CalendarController@getEvent'); Route::get('event-single/{id}', 'CalendarController@getSingleEvent'); Route::post('update-event/{id}', 'CalendarController@updateEvent'); Route::post('create-task', 'TaskController@createTask'); Route::post('change-color-task/{id}', 'TaskController@updateColorTask'); Route::delete('delete-task/{id}', 'TaskController@deleteTask'); Route::get('task', 'TaskController@getAllTask'); }); Route::post('login', 'UserController@login'); });
14.3 Middleware
Route::group(['prefix'=>'admin', 'middleware' => 'admin'], function () { Route::get('home/{id?}', 'AdminController@getTrangChu'); });
15. Kết nối với vuejs
15.1 Thiết lệp webpack.mix.js
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js').vue() .sass('resources/css/app.scss', 'public/css');
15.2 Template kết nối vuejs
<!doctype html> <html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="{{ asset('/img/calendar_logo_icon.ico') }}"> <link rel="stylesheet" href="{{ asset('/css/reset.css') }}"> <link rel="stylesheet" href="{{ asset('/css/app.css') }}"> <!-- <link rel="stylesheet" href="./css/bootstrap.min.css"> --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" /> <title>Calendar</title> </head> <body> <div id="app"> </div> <script> window.Laravel = <?php echo json_encode([ 'csrfToken' => csrf_token(), ]); ?> </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="{{ mix('js/app.js') }}"></script> </body> </html>
15.3 install vue and vue router
npm install --save vue vue-router
15.4 install mix
npm install laravel-mix@latest --save-dev
15.5 app.js
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false; new Vue({ render: h => h(App) }).$mount('#app')
15.6 App.vue component
<template> <div> abc </div> </template> <script> export default { name: 'App' } </script>
15.7 Chạy lệnh “npm run watch”
Chạy lệnh:
npm run watch
Trường hợp gặp lỗi:
Cannot find module ‘webpack/lib/rules/DescriptionDataMatcherRulePlugin’ Require stack:
Hãy chạy lệnh dưới
npm update vue-loader // nếu chưa install chạy lệnh dưới npm i vue-loader
Nếu gặp lỗi hãy thay phần script ở file package.json:
// before "scripts": { "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "npm run development -- --watch", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, // after "scripts": { "dev": "npm run development", "development": "mix", "watch": "mix watch", "watch-poll": "mix watch -- --watch-options-poll=1000", "hot": "mix watch --hot", "prod": "npm run production", "production": "mix --production" },
15.8 Lệnh build file ngôn ngữ của laravel sang vuejs
php artisan vue-i18n:generate
16. Token Api sanctum
Tạo API và Authenticate nhanh chóng với package Laravel Sanctum
17. Password Hash
//import hash use Illuminate\Support\Facades\Hash; //hash Hash::make('chuoiPassword'); //check Hash::check('chuoiPassword', 'Chuoi hash lưu trong database')
18. Run project
Mặc định laravel sẽ run project ở cổng 8000.
Để run mặc định bạn chạy lệnh sau:
php artisan serve
Để thay đổi cổng theo ý muốn bạn sử dụng lệnh sau:
php artisan serve --port=... // ... thay thanh port (8001, 8002, ...)
19. Phân trang laravel
$membe = Member::->where('winner', 1)->orderBy('created_at', 'DESC')->paginate(10);
<div class="ot-pagination clearfix"> <div class="text-center"> <!-- Previous Page Link --> <a href="{{$memberExams->onFirstPage() ? 'javascript:void(0)' : $memberExams->previousPageUrl()}}" rel="prev"><strong class="prev active"></strong></a> <!-- Element Page Link --> @for($page = 1; $page <= $memberExams->lastPage(); $page++) @if(($memberExams->currentPage() == 1 && $page <= $memberExams->currentPage() + 4) || ($memberExams->currentPage() == 2 && $page <= $memberExams->currentPage() + 3) || (($memberExams->currentPage() == $memberExams->lastPage() || $memberExams->currentPage() == $memberExams->lastPage() - 1) && ($page - 3 >= 1 || $page - 4 >= 1)) || ($page >= $memberExams->currentPage() - 2 && $page <= $memberExams->currentPage() + 2)) <strong> <a href="{{$memberExams->url($page)}}" class="page-link {{$page == $memberExams->currentPage() ? 'active' : ''}}"> <span>{{$page}}</span> </a> </strong> @endif @endfor <!-- Next Page Link --> <a href="{{$memberExams->hasMorePages() ? $memberExams->nextPageUrl() : 'javascript:void(0)'}}" rel="next"><strong class="next active"></strong></a> </div> </div>
19.1 Cần chỉnh sửa rồi mới paginate
use Illuminate\Pagination\Paginator; use Illuminate\Support\Collection; use Illuminate\Pagination\LengthAwarePaginator;
$member = Member::->where('winner', 1)->orderBy('created_at', 'DESC')->get();
public function paginate($items, $perPage = 5, $page = null, $options = []) { $page = $page ?: (Paginator::resolveCurrentPage() ?: 1); $items = $items instanceof Collection ? $items : Collection::make($items); return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, ['path'=>url('thi-thu-nhan-qua')]); }
20. Giữ giá trị ô input blade template – old input (Retrieving old input)
<input type="text" name="username" value="{{ old('username') }}">
public function post(Request $request) { return back()->withInput( $request->only('username') ); }
Tham khảo: https://viblo.asia/p/tap-16-request-laravel-aWj534Y8K6m mục 8c
21. Validate số điện thoại
'phone' => ['required', 'max:191', 'regex:((09|03|07|08|05)+([0-9]{8})\b)'],
22. Thực tập – Replace content – keyword
//https://regex101.com/r/cD8nG4/1 $content = preg_replace( "/<a[\S\s]+?<\/a>(*SKIP)(*FAIL)|<img[\S\s]+?\>(*SKIP)(*FAIL)|($keyword)/i", $linkReplace, $content, $limit - $keywordLinkCount, $count );
23. Các khái niệm học thêm được
- soft-delete: thêm field deleted_at để khi xóa chỉ thay đổi trạng thái mà không xóa hẳn khỏi database
- Relationship:
– One to one: 1-1
– One to many: 1- n
n – 1 => 1 – n ((gọi là inverse relationship sử dụng belongTo) -
Accessors: định dạng dữ liệu lấy từ db trước khi sử dụng
- Mutators: định dạng dữ liệu trước khi cập nhật vào db.
- Query Scope – global scope: add 1 truy vấn vào tất cả các truy vấn.
VD: soft-delete thay vì lúc nào cũng -> where(‘deleted_at’, null) thì sử dụng global scope sẽ không cần phải thêm câu lệnh đó vào truy vấn mà nó tự động thêm vào.
23.1 Accessors
Giả sử, bảng User có field first_name và last_name.
Bên ngoài hiển thị cần hiển thị dạng full_name (first_name + space + last_name).
Trong Model User viết hàm như sau:
public function getFullNameAttribute() // get[property_name]Attribute { return $this->first_name . " " . $this->last_name; }
Khi cần sử dụng full_name, thì sử dụng nó như thuộc tính bình thường
$data = \App\Models\User::all(); foreach($data as $item) { echo $item->full_name . "<br />"; // get full_name như thuộc tính }
23.2 Mutators
Giả sử, bảng User có field first_name và last_name.
Khi insert hoặc update vào database thì in hoa first_name rồi mới insert vào.
Trong model User:
public function setCompanyNameAttribute($value) // camelCase => function set[property_name]Attribute { $this->attributes['company_name'] = strtoupper($value); }
Khi đó, insert và update như bình thường, nó sẽ apply function đó vào thuộc tính first_name.
$item = new \App\Models\User(); $item->first_name = "Do"; // => Database sẽ lưu => DO $item->last_name = "Hao"; $item->save();
23.3 Scope
23.3.1 Global scope
Apply cho toàn bộ query của eloquent.
Giả sử, bảng User có field role.
Khi truy vấn bạn muốn toàn bộ query không lấy giá trị null của role
Trong model User:
// nhớ import Builder use Illuminate\Database\Eloquent\Builder; ... protected static function booted() { static::addGlobalScope('filterRole', function (Builder $builder) { // filterRole => ten global scope $builder->whereNotNull('role'); // thay thành câu điều kiện cho toàn bộ truy vấn }); }
Nếu một truy vấn nào đó không muốn apply global scope vào
// Xóa một global scope User::withoutGlobalScope('role')->get(); // thay role thành tên global scope cần xóa // Xóa nhiều global scope // Xóa toàn bộ User::withoutGlobalScopes()->get(); // Xóa một vài global scope User::withoutGlobalScopes([ FirstScope::class, SecondScope::class ])->get();
23.3.2 Local Scope
Apply cho một query nào đó của eloquent.
Giả sử, bảng User có field role.
Câu truy vấn bạn muốn query lấy role >= 2 (Và câu điều kiện này sử dụng ở nhiều nơi)
Trong model User:
public function scopeActive($query) // scope[scopeName] { return $query->where('role', '>=', 2); }
Khi sử dụng.
$data = \App\Models\User::active()->get(); // gọi scopeName
Sử dụng local scope với tham số:
Giả sử bạn muốn truyền tham số để query role, có thể thay đổi linh hoạt hơn.
Trong User model:
public function scopeActive($query, $roleUp) // Thêm param sau $query để sử dụng { return $query->where('role', '>=', $roleUp); }
Khi sử dụng:
$data = \App\Models\User::active(3)->get(); // truyển param vào scopeName
23.4 Relationship
23.4.1 One has many
Lưu ý:
+ Relationship dựa trên tên model
+ Khóa ngoại được xác định bằng cách: ten_model_id (tên model dạng snakeCase).
+ Nếu khóa ngoại không như cấu trúc trên, sử dụng tham số thứ 2 sau hasOne để xác định khóa ngoại của bảng cần tham chiếu
+ Tương tự khóa chính là id, nếu khác sử dụng tham số thứ 2 để xác định id của bảng cần tham chiếu
Ví dụ: Post và Comment
Vd1: Bảng posts (Model: Post) và comments (Model: Comment).
Post hasOne Comment => function sẽ có s phía sau tên (tên function là tên model liên kết dạng snakeCase) comments
Comment belongTo => function sẽ không có s phía sau tên (tên function là tên model liên kết dạng snakeCase) post
Lưu ý: Relationship chỉ dựa vào tên model.
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * Get the comments for the blog post. */ public function comments() { return $this->hasMany('App\Comment'); } }
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model { /** * Get the post that owns the comment. */ public function post() { return $this->belongsTo('App\Post'); } }
Ví dụ: MailTemplate và SendmailCvSetting
Ví dụ 2: cho bảng có tên dài. Có bảng
mail_templates => Model: MailTemplate
và bảng
sendmail_cv_settings => Model: SendmailCvSetting
Lưu ý: Relationship chỉ dựa vào tên model.
MailTemplate hasOne SendmailCvSetting=> function sẽ có s phía sau tên (tên function là tên model liên kết dạng snakeCase) sendmailCvSettings
SendmailCvSetting belongTo => function sẽ không có s phía sau tên (tên function là tên model liên kết dạng snakeCase) mailTemplate
class MailTemplate extends BaseModel { //Declare table name protected $table = 'mail_templates'; use SoftDeletes; protected $fillable = ['id']; public function sendmailCvSettings() { return $this->hasMany(\App\Models\SendmailCvSetting::class, 'mail_template_id'); } }
class SendmailCvSetting extends BaseModel { //Declare table name protected $table = 'sendmail_cv_settings'; use SoftDeletes; protected $fillable = ['id']; public function mailTemplate() { return $this->belongsTo(\App\Models\MailTemplate::class); } }
Sử dụng
$sendmailCvData = SendmailCvSetting::query(); $sendmailCvData->with('mailTemplate'); // sử dụng with, param là tên model tham chiếu. //=> data khi query sẽ có mục relation chứa data tham chiếu.
24. Gửi mail
let param = { YOUR_EMAIL: 'your@gmail.com', YOUR_PASS: 'apppassword', ADDRESS_FROM_USER_SEE: 'your@gmail.com', NAME_USER_SEE: 'your name', TEMPLATE_MAIL: 'emails.create-job', // file blade trong resource/view SUBJECT_TEXT: 'Send mail from ....', EMAIL_SEND: [ 'abc@gmail.com' ] }; console.log('Cấu hình .env'); let data = ` MAIL_DRIVER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=YOUR_EMAIL MAIL_PASSWORD=YOUR_PASS MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=ADDRESS_FROM_USER_SEE MAIL_FROM_NAME="NAME_USER_SEE" `; data = data.replaceAll('YOUR_EMAIL', param.YOUR_EMAIL); data = data.replaceAll('YOUR_PASS', param.YOUR_PASS); data = data.replaceAll('ADDRESS_FROM_USER_SEE', param.ADDRESS_FROM_USER_SEE); data = data.replaceAll('NAME_USER_SEE', param.NAME_USER_SEE); console.log(data); console.log('Tại nơi cần xử lý gửi mail'); console.log('use Mail;'); data = ` Mail::send('TEMPLATE_MAIL', [ // 'name' => 'admin', // 'clientJob' => $clientJob, // 'clientUser' => $clientUser, // 'client' => $client, // 'dataJoin' => (object) $dataJoin // add variable vào để sử dụng trong view ], function($message) /* use ($clientJob, $clientUser) => Phần này khai báo các biến sử dụng cho function ở dưới*/ {` param.EMAIL_SEND.forEach( (item) => { data += ` $message->to('${item}')->subject('SUBJECT_TEXT');`; }); data += ` }); `; data = data.replaceAll('TEMPLATE_MAIL', param.TEMPLATE_MAIL); data = data.replaceAll('SUBJECT_TEXT', param.SUBJECT_TEXT); console.log(data);
Xem thêm: https://viblo.asia/p/huong-dan-gui-mail-voi-laravel-5-XQZkxZEbGwA
25. Resize image when upload
// $item->thumbnail: File upload gửi lên server $pathImage = 'uploads/cv-sample/images'; $resourceType = imagecreatefrompng($item->thumbnail); $sourceProperties = getimagesize($item->thumbnail); $sourceImageWidth = $sourceProperties[0]; $sourceImageHeight = $sourceProperties[1]; $newWidth = 224; $newHeight = 316; $imageLayer = ImageService::resizeImage($resourceType, $sourceImageWidth, $sourceImageHeight, $newWidth, $newHeight); imagepng($imageLayer, $pathImage . '/' . $newSample->id . '.png');
public static function resizeImage($resourceType, $image_width, $image_height, $resizeWidth, $resizeHeight) { // $resizeWidth = 100; // $resizeHeight = 100; $imageLayer = imagecreatetruecolor($resizeWidth, $resizeHeight); imagecopyresampled($imageLayer, $resourceType, 0, 0, 0, 0, $resizeWidth, $resizeHeight, $image_width, $image_height); return $imageLayer; } // hàm này t bỏ vô ImageService.php file
Tham khảo: https://www.devopsschool.com/blog/how-to-upload-and-resize-an-image-using-php/
26. Core anh Tân
26.1 Tailwindcss backend không ăn nhập
https://tailwindcss.com/docs/guides/laravel
// Run lệnh npm install -D tailwindcss postcss autoprefixer // sau đó npm run dev
26.2 Lỗi Cannot set properties of undefined (setting ‘exclude’) webpack.frontend.mix
1. Vào file webpack.frontend.mix 2. Change png|jpe?g|gif|webp => png|jpe?g|gif|webp|avif 3. Chạy lại thử
26.2 Bỏ qua check console.log khi build
Thêm dòng bên dưới ở trên console.log // eslint-disable-next-line no-console
26.3 Reset lại database
//==== Reset database ==== // 1. Backup db // 2. Migrate php artisan migrate // 3. Seeding php artisan db:seed // 4. delete table delete table generates, auth_clients // 5. import table từ db cũ import table generates cũ qua mới import table auth_clients cũ qua mới
27. Encrypt & Decrypt
use Illuminate\Support\Facades\Crypt; Crypt::encryptString($encryptKey); Crypt::decryptString($encryptKey);
Khác
Còn nhiều kinh nghiệm ở các bài viết khác: