Tạo bởi Trần Văn Điêp|
Học Laravel

[Video] Lập trình Laravel - Truyền dữ liệu từ Controller qua View - Ví dụ hiển thị danh sách sinh viên trong Laravel Phần 3

Lập trình Laravel - Truyền dữ liệu từ Controller qua View - Ví dụ hiển thị danh sách sinh viên trong Laravel Phần 3

Mở bài

Việc xây dựng giao diện hiển thị dữ liệu là nhiệm vụ cốt lõi của bất kỳ ứng dụng web nào. Trong hệ sinh thái Laravel, việc truyền dữ liệu từ Controller qua View trong Laravel là kỹ năng nền tảng giúp bạn biến những con số, bản ghi hay logic xử lý thành giao diện thân thiện với người dùng. Ở phần 3 này, chúng ta sẽ tập trung vào ví dụ thực tế: hiển thị danh sách sinh viên — một module nhỏ nhưng đầy đủ các khái niệm cần thiết như route, controller, model, migration, Eloquent ORM, Blade template, pagination, search và xử lý lỗi.

Bài viết hướng dẫn từng bước — từ thiết lập database, tạo model & migration, viết controller lấy dữ liệu với Eloquent, truyền dữ liệu sang view rồi render bằng Blade — kèm theo các kỹ thuật nâng cao như route model binding, resource controller, query scope, caching, và tối ưu hiển thị. Mục tiêu là giúp bạn không chỉ biết cách truyền dữ liệu từ Controller qua View trong Laravel mà còn hiểu khi nào nên dùng phương pháp nào để ứng dụng vừa hiệu quả vừa dễ bảo trì.


Chuẩn bị: cấu hình dự án và mô hình dữ liệu sinh viên

Trước khi xuống tay code, bạn cần chuẩn bị môi trường và cấu trúc dữ liệu cho module quản lý sinh viên.

1. Tạo dự án và cấu hình database

  • Tạo project Laravel mới (nếu chưa có):

composer create-project laravel/laravel student-manager cd student-manager
  • Cấu hình file .env:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=student_db DB_USERNAME=root DB_PASSWORD=
  • Chạy php artisan migrate sau khi tạo migration.

2. Tạo model và migration cho Student

php artisan make:model Student -m

Trong migration (database/migrations/xxxx_create_students_table.php), định nghĩa các cột cơ bản:

Schema::create('students', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->integer('age')->nullable(); $table->string('major')->nullable(); $table->timestamps(); });

Chạy:

php artisan migrate

Khi đã có database và bảng students, bạn sẵn sàng thực hành cách truyền dữ liệu từ Controller qua View trong Laravel để hiển thị danh sách sinh viên.


Định nghĩa route và resource controller: điểm khởi đầu của luồng dữ liệu

Để tổ chức mã nguồn theo chuẩn RESTful, Laravel cung cấp Route::resource() giúp sinh ra đầy đủ route cho CRUD. Đây là bước đầu để điều hướng request đến controller và từ đó truyền dữ liệu tới view.

Khai báo route

Mở routes/web.php và thêm:

use App\Http\Controllers\StudentController; Route::resource('students', StudentController::class); Route::get('/', function () { return redirect()->route('students.index'); });

Route::resource('students', ...) sẽ tạo 7 route chuẩn: index, create, store, show, edit, update, destroy. Route students.index (GET /students) là nơi bạn sẽ lấy dữ liệu và truyền sang view hiển thị danh sách.

Tạo controller resource

Tạo controller:

php artisan make:controller StudentController --resource

Trong StudentController, phương thức index() sẽ chịu trách nhiệm lấy danh sách sinh viên bằng Eloquent và trả view. Đây chính là nơi thực hiện hành động truyền dữ liệu từ Controller qua View trong Laravel.


Lấy dữ liệu bằng Eloquent và truyền sang View

Eloquent là ORM mạnh mẽ của Laravel, giúp bạn thao tác database bằng model một cách trực quan. Ở đây, ta sẽ dùng Eloquent để query danh sách sinh viên và truyền kết quả sang view.

Ví dụ phương thức index trong StudentController

public function index(Request $request) { $query = Student::query(); // Tìm kiếm theo tên hoặc email if ($search = $request->input('search')) { $query->where('name', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%"); } // Sắp xếp theo cột (mặc định theo created_at) $sort = $request->input('sort', 'created_at'); $direction = $request->input('dir', 'desc'); $students = $query->orderBy($sort, $direction)->paginate(10)->withQueryString(); // Truyền dữ liệu từ Controller qua View trong Laravel return view('students.index', compact('students', 'search', 'sort', 'direction')); }

Giải thích:

  • Student::query() tạo builder để thêm điều kiện linh hoạt.

  • paginate(10) giúp chia trang; kết quả trả về sẽ là collection trang hóa.

  • withQueryString() giữ các tham số search/sort khi chuyển trang.

  • compact() là cách ngắn gọn để truyền dữ liệu từ Controller qua View trong Laravel.

Lợi ích

  • View nhận data dạng $students đã có thông tin phân trang.

  • Controller giữ logic xử lý, view chỉ lo hiển thị — tôn trọng nguyên tắc separation of concerns.


Thiết kế Blade view để hiển thị danh sách sinh viên

Sau khi Controller truyền $students sang view, nhiệm vụ view (Blade template) là render bảng dữ liệu, xử lý pagination và hiển thị các control tìm kiếm/sort.

File resources/views/students/index.blade.php

@extends('layouts.app') @section('content') <div class="container"> <h1>Danh sách sinh viên</h1> <form method="GET" action="{{ route('students.index') }}" class="mb-3"> <input type="text" name="search" value="{{ $search ?? '' }}" placeholder="Tìm kiếm tên hoặc email"> <button type="submit">Tìm</button> </form> <table class="table"> <thead> <tr> <th><a href="{{ route('students.index', array_merge(request()->all(), ['sort' => 'id', 'dir' => $direction === 'asc' ? 'desc' : 'asc'])) }}">ID</a></th> <th><a href="{{ route('students.index', array_merge(request()->all(), ['sort' => 'name', 'dir' => $direction === 'asc' ? 'desc' : 'asc'])) }}">Tên</a></th> <th>Email</th> <th>Tuổi</th> <th>Ngành</th> <th>Hành động</th> </tr> </thead> <tbody> @forelse($students as $s) <tr> <td>{{ $s->id }}</td> <td>{{ $s->name }}</td> <td>{{ $s->email }}</td> <td>{{ $s->age ?? '-' }}</td> <td>{{ $s->major ?? '-' }}</td> <td> <a href="{{ route('students.edit', $s) }}">Sửa</a> <form action="{{ route('students.destroy', $s) }}" method="POST" style="display:inline;"> @csrf @method('DELETE') <button type="submit" onclick="return confirm('Bạn có chắc muốn xóa?')">Xóa</button> </form> </td> </tr> @empty <tr><td colspan="6">Không có sinh viên</td></tr> @endforelse </tbody> </table> {{ $students->links() }} </div> @endsection

Điều bạn cần lưu ý:

  • Blade directive @forelse hữu dụng khi collection có thể rỗng.

  • {{ $students->links() }} hiển thị pagination controls.

  • Các link sắp xếp dùng request()->all() để giữ filter hiện tại.

Đây là một minh chứng trực quan cho việc truyền dữ liệu từ Controller qua View trong Laravel: controller cung cấp $students, view sử dụng để render giao diện.


Tìm kiếm, sắp xếp và query scope: mở rộng khả năng hiển thị

Để module linh hoạt hơn, ta nên tách logic tìm kiếm/sort vào model hoặc scope. Điều này làm controller gọn hơn và tái sử dụng dễ dàng.

Thêm query scope trong model Student

Trong app/Models/Student.php:

public function scopeSearch($query, $term) { if ($term) { $term = "%{$term}%"; $query->where('name', 'like', $term) ->orWhere('email', 'like', $term); } return $query; }

Sử dụng scope trong controller

$query = Student::query()->search($request->input('search'));

Lợi ích:

  • Tách concerns: model chịu trách nhiệm phần query đặc thù.

  • Dễ test: bạn có thể test scope độc lập.

  • Giúp việc truyền dữ liệu từ Controller qua View trong Laravel trở nên rõ ràng hơn bởi controller chỉ orchestration.


Route model binding và named routes: tối ưu cú pháp và bảo mật

Laravel hỗ trợ route model binding tự động, rất tiện cho các route show, edit, update, destroy.

Ví dụ route và controller edit

Route resource đã tự động khai báo /students/{student}/edit. Trong controller:

public function edit(Student $student) { // Laravel đã tự nạp instance thông qua route model binding return view('students.edit', compact('student')); }

Khi dùng route model binding, bạn tránh phải gọi Student::findOrFail($id) — code ngắn gọn và an toàn hơn.

Named routes

Sử dụng route('students.index'), route('students.edit', $student) thay vì hardcode URL để dễ refactor và tránh lỗi khi đổi cấu trúc route.


Phân trang, caching và tối ưu hiệu suất

Danh sách có thể lớn, vì vậy pagination và caching là cần thiết.

Pagination

Sử dụng paginate(10) trên query và {{ $students->links() }} trong view giúp hiển thị từng trang, giảm tải memory.

Cache

Lưu kết quả query phổ biến:

$students = Cache::remember('students_page_'.$page.'_search_'.md5($search), 60, function() use ($query) { return $query->orderBy(...)->paginate(10); });

Cache giúp giảm truy vấn DB cho các trang phổ biến, nhưng cần invalidate khi có cập nhật (store, update, destroy).

Indexing DB

Đảm bảo cột tìm kiếm như name, email có index để tăng tốc LIKE queries hoặc dùng fulltext nếu cần.


Validation, mass assignment và an toàn dữ liệu

Khi truyền dữ liệu từ view về controller (store/update), cần validate và tránh mass assignment nguy hiểm.

Validation

Trong store() / update():

$validated = $request->validate([ 'name' => 'required|max:255', 'email' => 'required|email|unique:students,email,'.$student->id ?? 'NULL', 'age' => 'nullable|integer|min:0', 'major' => 'nullable|string|max:255', ]);

Mass assignment

Trong Student model, khai báo $fillable:

protected $fillable = ['name','email','age','major'];

Tránh dùng $guarded = [] nếu bạn không kiểm soát input.

XSS protection

Blade {{ }} tự escape dữ liệu. Nếu muốn render HTML an toàn, dùng @{!! $var !!} chỉ khi bạn chắc chắn nội dung đã được sanitize.


UX nâng cao: AJAX, live search và các cải thiện giao diện

Để trải nghiệm người dùng mượt mà, bạn có thể:

  • Thêm AJAX cho delete/edit để không reload toàn trang.

  • Implement live search (typeahead) bằng fetch/Axios gọi API route trả JSON.

  • Dùng Blade components cho bảng, pagination controls, alert messages.

  • Support CSV export/import để quản lý danh sách lớn.

Những cải tiến này vẫn dựa trên cơ chế truyền dữ liệu từ Controller qua View trong Laravel: controller có thể trả JSON cho frontend JS hoặc view cho render server-side.


Kiểm thử cho module danh sách sinh viên

Viết test đảm bảo module hoạt động ổn định:

Feature test cho index

public function test_students_index_shows_list() { Student::factory()->count(15)->create(); $response = $this->get(route('students.index')); $response->assertStatus(200); $response->assertSeeText('Danh sách sinh viên'); $response->assertViewHas('students'); }

Test tìm kiếm và phân trang

Tạo dữ liệu cụ thể và assert rằng filter trả về đúng bản ghi.

Testing giúp đảm bảo rằng việc truyền dữ liệu từ Controller qua View trong Laravel không bị phá vỡ khi refactor.


Tổng kết và best practices

Bài học chính:

  • Luồng chuẩn: Route → Controller → Model (Eloquent) → View (Blade).

  • Controller là nơi bạn lấy dữ liệu và truyền dữ liệu từ Controller qua View trong Laravel; view chỉ hiển thị.

  • Dùng Route::resource() và route model binding để giữ code sạch, an toàn.

  • Tách query logic vào model scope để tái sử dụng và dễ kiểm thử.

  • Áp dụng pagination, cache và indexing để tối ưu hiệu suất.

  • Luôn validate input, sử dụng $fillable và escape output để bảo mật.

Danh sách tóm tắt các thủ thuật:

  1. Dùng compact()/with()/mảng để truyền dữ liệu sang view.

  2. Sử dụng query scope cho tìm kiếm.

  3. Cache các trang phổ biến.

  4. Viết unit & feature tests cho tất cả các luồng.

  5. Dùng Blade components để tái sử dụng UI.


Kết luận

Trong phần 3 này, bạn đã đi sâu vào ví dụ hiển thị danh sách sinh viên để thực hành cách truyền dữ liệu từ Controller qua View trong Laravel — từ việc định nghĩa route, dùng resource controller, truy vấn Eloquent, đến thiết kế Blade view, xử lý tìm kiếm, sắp xếp, phân trang và tối ưu hiệu suất. Đây là một module mẫu mà bạn có thể mở rộng thành chức năng quản trị thực thụ: thêm create/edit/delete, phân quyền, export/import và tích hợp frontend hiện đại.

Hãy áp dụng các best practices đã nêu: tách logic, dùng query scope, validate input, cache khi cần và luôn viết test. Khi bạn thành thục việc truyền dữ liệu từ Controller qua View trong Laravel, việc xây dựng các tính năng phức tạp hơn — như dashboards, báo cáo, hay API cho SPA — sẽ trở nên đơn giản và đáng tin cậy hơn. Bắt tay thực hành ngay: cài project, seed dữ liệu, viết controller và view — rồi thử từng biến thể (AJAX, API, export) để nắm thật chắc kỹ năng này. Chúc bạn phát triển module quản lý sinh viên chuyên nghiệp và mở rộng ứng dụng Laravel hiệu quả!

Phản hồi từ học viên

5

Tổng 0 đánh giá

Đăng nhập để làm bài kiểm tra

Chưa có kết quả nào trước đó