Đã đến lúc giới thiệu một bảng cơ sở dữ liệu thứ hai và một mối quan hệ. Sau khi làm việc với Categories, giờ chúng ta sẽ xử lý Posts.
Chúng ta sẽ tạo một Eloquent Model cho Posts và định nghĩa mối quan hệ. Mỗi bài viết nên thuộc về một trong các danh mục. Cuối cùng, trên trang web, chúng ta sẽ tạo một liên kết để hiển thị bài viết theo danh mục đã chọn.
Tạo Model và Migration
Đầu tiên, hãy tạo một Model và Migration. Chúng ta có thể làm điều này với hai lệnh artisan, hoặc một lệnh "make:model" và cung cấp tùy chọn "-m", nghĩa là migration.
php artisan make:model Post -m
Bây giờ, chúng ta có thể điền vào migration. Ngoài các cột string và text thông thường, chúng ta cần một cột cho mối quan hệ với danh mục.
Laravel có cú pháp để tạo khóa ngoại. Có một số tùy chọn, nhưng tôi thích phương pháp "foreignId()" với "constrained()". Nó sẽ tạo cả cột cơ sở dữ liệu và khóa ngoại.
Tên của cột mối quan hệ nên có định dạng "xxxxx_id", trong đó "xxxxx" là dạng số ít của bảng quan hệ. Sau đó, bạn định nghĩa "constrained()", là một phương pháp ngắn hơn của Laravel cho "->references('id')->on('categories')".
database/migrations/xxx_create_posts_table.php:
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('text');
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
}
Chúng ta có thể chạy các migration.
php artisan migrate
Tôi đã thêm các bài viết thủ công và gán mỗi bài viết cho một danh mục khác nhau. Hiện tại, tôi đã làm thủ công vì chúng ta đang nói về việc lấy dữ liệu. Sau này, chúng ta sẽ nói về cách tạo nó.
Lấy Posts trong Controller
Chúng ta cần lấy các bài viết trong cùng HomeController với danh mục. Chúng ta có thể sử dụng phương thức all() trên Model Post hoặc lấy các bài viết mới nhất trước.
app/Http/Controllers/HomeController.php:
use App\Models\Post;
class HomeController extends Controller
{
public function index()
{
$allCategories = Category::all();
$posts = Post::orderBy('id', 'desc')->get();
return view('home', ['categories' => $allCategories]);
}
}
Cú pháp thay thế cho orderBy(): chúng ta có thể sử dụng một phương thức Eloquent gọi là latest().
app/Http/Controllers/HomeController.php:
use App\Models\Post;
class HomeController extends Controller
{
public function index()
{
$allCategories = Category::all();
$posts = Post::latest()->get();
return view('home', ['categories' => $allCategories]);
}
}
Và chúng ta cần truyền các bài viết đó đến View. Chúng ta có thể thêm các bài viết vào cùng một mảng.
return view('home', [
'categories' => $allCategories,
'posts' => $posts
]);
Nhưng có một cách ngắn hơn sử dụng hàm compact() của PHP, chỉ cần liệt kê các biến. Hàm này có thể được sử dụng nếu tên của các biến giống như các khóa của mảng, vì vậy chúng ta cần đổi tên biến allCategories thành categories.
app/Http/Controllers/HomeController.php:
class HomeController extends Controller
{
public function index()
{
$categories = Category::all();
$posts = Post::latest()->get();
return view('home', compact('categories', 'posts'));
}
}
Hiển thị Posts trong Blade
Bây giờ, hãy hiển thị các bài viết trong Blade. Cũng như, hãy làm một số dọn dẹp trực quan và xóa mã "Featured post" và phân trang với tìm kiếm và các widget bên từ Bootstrap theme vì chúng ta sẽ không có các tính năng đó trong bản demo của mình.
resources/views/home.blade.php:
Trên trang chủ, chúng ta có thể thấy các bài viết từ cơ sở dữ liệu.
Hiển thị Bài viết Theo Danh mục
Bây giờ, chúng ta sẽ thêm một liên kết để xem danh mục với các bài viết của nó. Liên kết sẽ có một Route đến trang chủ với một tham số. Có một số cách để thêm tham số, nhưng chúng ta sẽ sử dụng cách dễ nhất: với URL như /?category_id=XXXXX.
resources/views/home.blade.php:
Sau đó, trong Controller, chúng ta có thể lọc các bài viết bằng phương thức where() và lấy danh mục từ request bằng cách sử dụng trợ lý request().
app/Http/Controllers/HomeController.php:
class HomeController extends Controller
{
public function index()
{
$categories = Category::all();
$posts = Post::where('category_id', request('category_id'))->latest()->get();
return view('home', compact('categories', 'posts'));
}
}
Sau khi làm mới trang chủ, chúng ta thấy danh sách bài viết trống vì chúng ta không có tham số danh mục.
Nhưng nếu bạn nhấp vào một danh mục, các bài viết thuộc danh mục đó sẽ được hiển thị.
Sửa Hiển thị Tất cả Bài viết
Bây giờ, hãy sửa trang để hiển thị tất cả các danh mục khi không có danh mục nào được chọn. Đây sẽ là một ví dụ về mức độ mạnh mẽ của Eloquent.
Eloquent có phương thức when(), nhận điều kiện làm tham số đầu tiên. Nếu điều kiện là true, Eloquent sẽ thực thi hàm closure, tham số thứ hai của phương thức when().
app/Http/Controllers/HomeController.php:
class HomeController extends Controller
{
public function index()
{
$categories = Category::all();
$posts = Post::when(request('category_id'), function ($query) {
$query->where('category_id', request('category_id'));
})->latest()->get();
return view('home', compact('categories', 'posts'));
}
}
Cú pháp này có nghĩa là khi category_id từ request tồn tại, điều kiện where sẽ được thêm vào truy vấn.
Sau khi làm mới trang chủ, tất cả các bài viết đều được hiển thị, và khi danh mục được chọn, chỉ những bài viết thuộc danh mục đã chọn sẽ được hiển thị.
Bài trước: MVC: Model, Controller và View với Foreach
Bài tiếp: Route Parameters và Route Model Binding
Cập nhật thêm được vài kiến thức mới
Bài viết hữu ích.
Hữu ích
Cảm ơn Admin. Bài viết khá hay !
OK bạn, mình sẽ sắp xếp viết một bài về Extend Validation. Cảm ơn bạn đã quan tâm nhé.