Skip to content

Blog Công Nghệ

MENUMENU
  • Trang chủ
  • Giới Thiệu
  • Lập Trình
    • Lập Trình Website
      • Laravel
        • Phân Tích Dự Án
      • PHP
      • SQL
      • HTML
      • CSS
      • Javascipt
      • My Project
      • Wordpress
    • Luyện Skill
    • Lập trình winform
    • CSDL
    • Lập Trình Android
    • Trí tuệ nhân tạo
    • Khai Khoáng Dữ Liệu
    • Arduino
    • Khác
    • Đồ án
  • Phần Mềm
    • Powerpoint
    • Tool
  • Cuộc sống và Giải trí
    • Hợp âm
    • web5ngay - youtube
    • Công Giáo
    • Kỹ Năng Sống
    • Street Workout
  • Danh sách bài viết
  • Guide line
    • Guild line phỏng vấn
    • Guide lines Laravel
    • Guide line Module Frontend
  • Tóm tắt sách
  • Fanpage

Blog Công Nghệ

Nơi chia sẻ kiến thức

Kinh nghiệm laravel

4 Tháng Một, 2024 by admin
Lượt xem: 329

Contents

  • 1. SQL
    • 1.1. skip là OFFSET trong SQL
    • 1.2. take là LIMITtrong SQL
    • 1.3. orderBy là ORDER BY trong SQL
    • 1.4 join – left join
    • 1.5 Get Month, Year
    • 1.6 Like
    • 1.7 Query điều kiện lồng
    • 1.8 Cần query từ từ
  • 2. insert, update, delete, select dữ liệu
    • 2.1 insert
    • 2.2 Update
    • 2.3 Delete
    • 2.4 Select
    • 2.5 try catch bắt lỗi truy vẫn
    • 2.6 Xử lý lỗi khi sử dụng Eloquent
      • 2.6.1 Insert
    • 2.7 Tồn tại
    • 2.8 Get một col trong dữ liệu trả về
    • 2.9 Join bảng
    • 2.10 Validate Custom
  • 3. Sử dụng php
    • 3.1 Sử dụng class trong php
    • 3.2 Sử dụng PHP
    • 3.3 PHP & Javascript
  • 4. Model
  • 5. Truyền dữ liệu sang view
  • 6. Middleware
  • 7. Seeder – dữ liệu mẫu
    • 7.1 Cách tạo dữ liệu mẫu
    • 7.2 Insert dữ liệu kiểu date
    • 7.3 Sử dụng factory
      • Tạo factory
      • Định nghĩa file factory
      • Sử dụng trong seeder
  • 8. Migration
    • 8.1 Thứ tự tạo Migration
    • 8.3 Tạo bảng không bị lỗi khóa ngoại
    • 8.4 Câu lệnh nên dùng khi tạo migration
    • 8.5 Nội dung file migration
    • 8.6 Khóa chính là kiểu string
    • 8.7 Tạo Foreign Key cho database
  • 9. Kiểm tra dữ liệu bằng tinker
  • 10. Controller
    • 10.1 Request
    • 10.2 Upload file
  • 11. View
    • 11.1 Bỏ tham số vào href, action hoặc src
  • 12. Authentication
  • 13. Hàm chuyển kiểu Date
  • 14. Route
    • 14.1 Group
    • 14.2 Tạo Route Controller đi vào thêm một cấp thư mục
    • 14.3 Namespace route
    • 14.3 Middleware
  • 15. Kết nối với vuejs
    • 15.1 Thiết lệp webpack.mix.js
    • 15.2 Template kết nối vuejs
    • 15.3 install vue and vue router
    • 15.4 install mix
    • 15.5 app.js
    • 15.6 App.vue component
    • 15.7 Chạy lệnh “npm run watch”
    • 15.8 Lệnh build file ngôn ngữ của laravel sang vuejs
  • 16. Token Api sanctum
  • 17. Password Hash
  • 18. Run project
  • 19. Phân trang laravel
    • 19.1 Cần chỉnh sửa rồi mới paginate
  • 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
    • 23.1 Accessors
    • 23.2 Mutators
    • 23.3 Scope
      • 23.3.1 Global scope
      • 23.3.2 Local Scope
        • Sử dụng local scope với tham số:
    • 23.4 Relationship
      • 23.4.1 One has many
        • Ví dụ: Post và Comment
        • Ví dụ: MailTemplate và SendmailCvSetting
        • Sử dụng
  • 24. Gửi mail
  • 25. Resize image when upload
  • 26. Core anh Tân
    • 26.1 Tailwindcss backend không ăn nhập
    • 26.2 Lỗi Cannot set properties of undefined (setting ‘exclude’) webpack.frontend.mix
    • 26.2 Bỏ qua check console.log khi build
    • 26.3 Reset lại database
  • 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ì.

  1. 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.
  2. 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.
  3. 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:

  • Làm gì với một project mới, các lỗi thường gặp laravel. Link
  • Phân tích project blog. Link
  • Phân tích project website âm nhạc. Link

Related posts:

  1. Phân tích Project Website nghe nhạc làm từ Laravel của Sharecode.vn
  2. Request trong Laravel
  3. HTTP Responses trong Laravel như thế nào?
  4. Kinh nghiệm Codeigniter – Perfex CRM

Post navigation

Previous Post:

Migrations trong Laravel

Next Post:

Thiết kế giao diện quản trị admin nhanh với Laravel và thư viện Infyom

Trả lời Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Ẩn sidebar

Tìm kiếm

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages

Blog Công Nghệ

Bài viết mới

  • Master typescript
  • Sendmail trong Laravel sử dụng dịch vụ SES, SQS của Amazon
  • Install SSL in Nginx Ubuntu
  • Docker study
  • Bảo vệ: Hướng dẫn code bot Telegram easy game

Lượng truy cập

0074499
Visit Today : 95
Visit Yesterday : 178
This Month : 770
Who's Online : 4
© 2025 Blog Công Nghệ | WordPress Theme by Superbthemes