Khái niệm: View là một tầng logic trong mô hình MVC, mục đích của nó là tách phần hiển thị nội dung ra khỏi phần xử lý dữ liệu của PHP. Do đó, đúng với tiêu chuẩn thì View chỉ chịu trách nhiệm nhận dữ liệu đầu cuối và hiển thị ra giao diện. Tất cả view của Laravel sẽ mặc định lưu trong resources/views.
Ví dụđơn giản về một file view như sau:
<!-- View stored in resources/views/greeting.php --> <html>
<body>
<h1>Hello, <?php echo $name; ?></h1> </body>
</html>
Khi file đã được lưu tại resources/views/greetings.php, có thể sử dụng bằng cách gọi hàm view()để hiển thị:
Route::get('/', function (){
return view('greeting', ['name' => 'James']); });
Hàm view() nhận vào hai tham số. Tham số thứ nhất chính là tên của view, chỉ cần gọi tên, không cần thêm vào đuôi “.php”. Tham số thứ hai là một mảng để truyền dữ liệu đã “xử lý” vào view; nó là một mảng, với key là tên của biến sẽ sử dụng ở view và value là giá trị của biến đó. Như ví dụ trên, biến $name ở view được gán giá trị “James” ở route. Dĩ nhiên cũng có thể lưu file view và các thư mục con bên trong
resources/views. Ví dụ, nếu lưu view tại resources/views/admin/profile.php, có thể sử dụng view bằng cách:
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 24
Kiểm tra view có tồn tại hay không:
Có thể kiểm tra xem view có tồn tại hay không bằng cách dùng hàm exist() sau khi gọi hàm view() mà không có tham số, exist() sẽ trả về giá trị true nếu file view tồn tại và ngược lại:
if (view()->exists('emails.customer')) { //
}
Render view từ routes:
Gọi hàm view() trực tiếp từ route để render view mong muốn.
Route::get('/', function () {
return view('greeting', ['name' => 'James']); });
Render view từ Controller:
View cũng có thể render từ controller tương tự như cách render từ route, đó là return hàm view():
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests;
use App\Http\Controllers\Controller; class HelloController extends Controller {
/**
* Display a listing of the resource. *
* @return Response */
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 25
{
return view('greetings', ['name'=>'Thanh Thùy']); }
}
Dữ liệu của view
Truyền dữ liệu vào view: Như đã nói ở trên, tham số thứ hai của hàm
view() nhận vào một mảng với key và value, bạn có thể thêm vào mảng bao nhiêu cặp key=>value tùy ý để truyền dữ liệu từ route/controller sang view:
return view('greetings', [ 'name' => 'Victoria', 'job'=>'Developer, 'more_data'=> $data ]); Như vậy, tất cả xử lý sẽ tách khỏi view, làm gì đó với dữ liệu và có nó ở biến $data, bạn truyền vào view thông qua biến ‘more_data’ và view sẽ sử dụng biến này mà không xử lý gì thêm. Giá trị truyền vào view có thể có bất cứ kiểu dư liệu nào: Int, String, Array, Object,…
Chia sẻ dữ liệu với tất cả các view: Đôi khi, cần chia sẻ một thông tin cho tất cả các view sẽ hiển thị trên ứng dụng, ví dụ: hiển thị thông tin user đã đăng nhập lên thanh trạng thái của các trang backend chẳng hạn. Không muốn việc lặp đi lặp lại việc insert data trong hàm view có thể dùng hàm share() , gọi nó trong hàm boot() của một Laravel service provider bất kỳ.
<?php
namespace App\Providers;
class AppServiceProvider extends ServiceProvider {
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 26
* Bootstrap any application services. *
* @return void */
public function boot() {
view()->share('key', 'value'); }
/**
* Register the service provider. *
* @return void */
public function register() {
// }}
View và cách sử dụng Blade Template Blade rất đơn giản, nhưng lại là một templating engine đầy mạnh mẽ. Blade không giới hạn chúng ta sử dụng code PHP trong views. Tất cả các file Blade sẽđược dịch thành file code PHP và cache cho đến khi file Blade bị thay đổi; điều đó cũng có nghĩa là Blade tự làm tất cả những việc cần thiết để có thể chạy views cho ứng dụng của bạn. Các file view dùng cho Blade có phần tên đuôi file là .blade.php và được lưu trong thư mục resources/views.
Tạo file template đầu tiên: Không khác biệt file PHP bình thường, ngoại trừ có phần mở rộng .blade.php
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 27
<h1>Bài hướng dẫn cách dùng Blade trong Laravel</h1> <p><?php echo $name ?></p>
</div>
Vậy là đã có file blade, nhìn nó rất bình thường như bao file PHP khác. Khi chạy lần đầu, Blade sẽ dịch file này thành file PHP. Chúng ta có thể sử dụng file Blade như các file view khác bằng cách gọi hàm view():
Route::get('/example', function (){
return view('example', ['name' => 'James']); });
Người dùng chỉ cần gọi tên view là example mà không phải ghi rõ example.blade.php
Hiển thị dữ liệu trong Blade: Để hiển thị dữ liệu trong Blade, dùng cặp dấu {{ và }} bọc quanh biến dữ liệu truyền vào Blade:
Route::get('greeting', function (){
return view('welcome', ['name' => 'Samantha']); });
Để hiển thị nội dung của biến name chỉ cần thực hiện dòng lệnh sau:
p>{{ $name }}</p>
Cặp dấu ngoặc {{ và }} sẽ thực hiện echo ra thông tin. Đối với echo, bạn thường phải dùng strip_tags() và htmlentities() để lọc text xuất ra, tránh bị các lỗi XSS. Nhưng với Blade, cặp dấu xuất này cũng thực hiện việc bao gói dữ liệu xuất ra cho bạn, chúng ta không cần xử lý dữ liệu trước khi echo. Tương tự, để hiển thị dữ liệu từ mảng, object hay từ hàm trả về, ta cũng thực hiện tương tự:
<p>{{ foo('name') }}</p> <p>{{ bar['name'] }}</p> <p>{{ $object->name }}</p>
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 28
Hiển thị dữ liệu thô: Để có thể hiển thị dữ liệu dạng raw text, nghĩa là có thể xuất HTML, JS… thì phải dùng cặp dấu {!! và !!}. Nhưng cần chú ý sử dụng trong các trường hợp khác nhau. Ví dụ, không nên hiển thị comment từ người duyệt web bằng cặp dấu này, hacker có thể lợi dụng để thực hiện chèn mã độc lên website.
Hello, {!! $name !!}.
Dùng chung Blade template với các Javascript Framework: Rất nhiều Js framework cũng sử dụng {{ và }} để hiển thị nội dung lên trình duyệt, do đó khi code có khả năng bị “xung đột” với Blade. Bạn có thể dùng @{{ và }} để báo cho Blade biết đừng đụng vào, vị trí này cho Js, ví dụ:
<h1>Laravel</h1> Hello, @{{ name }}
Trong ví dụ này, khi dịch ra PHP, Blade sẽ xóa @ đi, và để nguyên nội dung {{ name }}lại, cho phép bạn xuất nội dung qua Js Framework. Echo dữ liệu nếu tồn tại: Đôi khi cần echo một biến, nhưng lại không chắc chắn biến đó đã được khởi tạo hay gán dữ liệu chưa, có thể biểu diễn biểu lệnh xuất dữ liệu trong một dòng PHP như sau:
{{ isset($name) ? $name : 'Default' }}
Tuy nhiên, Blade cung cấp lối viết tắt còn ngắn gọn hơn thế nữa:
{{ $name or 'Default' }}
Trong ví dụ trên, nếu $name tồn tại, giá trị của nó được hiển thị, ngược lại, nếu không tồn tại, từ “Default” sẽ hiển thị.
Cấu trúc điều khiển: Cũng giống như việc hiển thị dữ liệu bằng PHP thuần, chúng ta luôn cần dùng các cấu trúc điều khiển để kiểm tra, phù hợp với điều kiện nào thì hiển thị cái nào ra. Blade cung cấp các lối viết tắt ngắn gọn, súc tích mà vẫn giữ được sự quen thuộc với code PHP. Câu lệnh If: Với câu lệnh if, bạn có thể dùng các chỉ thị trong template
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 29
như @if , @else , @elseif , @endif. Các từ khóa chỉ thị này có ý nghĩa tương tự với lệnh dùng trong PHP.
@if (count($records) === 1) Tôi có 1 bản ghi!
@elseif (count($records) > 1) Tôi có nhiều bản ghi!
@else
Tôi không có bản ghi nào. @endif
Với câu lệnh @if chỉ có 1 điều kiện, Blade cung cấp lối viết tắt ngắn gọn @unless:
@unless (Auth::check())
Bạn chưa đăng nhập @endunless
Vòng lặp: Blade cung cấp các từ khóa chỉ thị tương ứng với các lệnh lặp trong PHP:
@for ($i = 0; $i < 10; $i++) Giá trị hiện tại là {{ $i }} @endfor
@foreach ($users as $user)
<p>Đây là user có mã {{ $user->id }}</p> @endforeach
@while (true)
<p>Tôi đang lặp mãi mãi :(</p> @endwhile
Nếu có nhu cầu hiển thị nội dung thay thế cho @foreach, khi duyệt gặp một mảng rỗng, null, Blade hỗ trợ cú pháp ngắn gọn sau:
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 30
<li>{{ $user->name }}</li> @empty
<p>Không có user nào!</p> @endforelse
Trong ví dụ trên, bạn thấy @forelse không có trong PHP. Blade sẽ thay chúng ta kiểm tra biến $users, nếu có dữ liệu sẽ thực hiện xuất qua vòng lặp foreach, nếu không có dữ liệu, sẽ chuyển qua xuất dữ liệu ở giữa @empty và @endforelse.
Layout và kế thừa temaplate: Với một trang web có rất nhiều trang khác nhau, chúng ta không thể liên tục tạo mới file template cho từng trang trong khi chúng chỉ khác về nội dung chứ bố cục tổng thể thì không thay đổi. Chúng ta không nên và cũng không thể copy lặp đi lặp lại cùng một đoạn code (DRY – Don’t Repeat Yourself), việc đó sẽ làm chúng ta rất mất thời gian để tạo ra cũng như bảo trì, nâng cấp các file template. Laravel 5 cung cấp cho chúng ta giải pháp đơn giản để tổ chức hệ thống file template theo layout gọn gàng, có cấu trúc, giúp giảm thiểu tối đa thời gian triển khai giao diện.
Định nghĩa một layout: Hai lợi ích chính của việc sử dụng Blade là kế
thừa template và chia phần template thành section. Để bắt đầu, hãy xem qua một ví dụ đơn giản. Đầu tiên, xem xét trang layout chính. Hầu hết các ứng dụng web đều duy trì layout cơ bản giống nhau trên nhiều trang, điều đó rất tiện cho chúng ta để định nghĩa layout này như một view Blade đã học ở trên:
<!-- Lưu tại resources/views/layouts/master.blade.php --> <html>
<head>
<title>App Name - @yield('title')</title> </head>
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 31 <body> @section('sidebar') <h3>Đây là sidebar chính.</h3> @show <div class="container"> @yield('content') </div> </body> </html>
Những file này chứa phần lớn code HTML. Tuy nhiên, chú ý vào hai từ khóa chỉ thị@section và @yield. Chỉ thị@section định nghĩa một mảnh/phần/đoạn nội dung, trong khi chỉ thị@yield dùng để hiển thị nội dung của một phần nhất định.
Bây giờ đã có một layout được định nghĩa cho ứng dụng của mình. Hãy tiếp tục định nghĩa các trang con kế thừa từ layout chính này. Mở rộng layout: Khi định nghĩa một trang con, bạn có thể sử dụng từ khóa chỉ thị@extends để chỉ định trang con nên kế thừa từ layout nào. Các view kế thừa từ Blade layout có thể chèn nội dung vào các section ở layout đã định nghĩa bằng @section. Như đã xem ví dụ ở trên, nội dung của section cũng sẽ hiển thị trong layout ở những nơi có dùng @yield:
<!-- Lưu tại resources/views/child.blade.php --> @extends('layouts.master')
@section('title', 'Tiêu đề trang') @section('sidebar')
@parent
<p>Đây là phần thêm vào bên dưới sidebar chính ở layout.</p> @endsection
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 32
@section('content')
<p>Đây là phần nội dung trong trang.</p> @endsection
Trong ví dụ này, section sidebar lợi dụng từ khóa chỉ thị @parent để nối thêm vào (đúng hơn là ghi đè) nội dung lên sidebar chính của layout. Chỉ thị@parent sẽ được thay thế bởi nội dung của layout khi view được render (biên dịch thành PHP rồi thành HTML).
Dĩ nhiên, cũng giống như PHP view, Blade view có thể được dùng đơn giản bằng cách return từ hàm view():
Route::get('blade', function () { return view('child');
});
Như vậy, layout Blade được tạo ra để các page khác nhau kế thừa và dùng lại. Chúng ta khi gọi view sử dụng thì gọi trực tiếp vào view của từng page mà không gọi vào layout.
Sự khác nhau giữa @yield và @section: Những điểm khác nhau giữa chúng và hiểu rõ để sử dụng chúng như thế nào cho phù hợp.
@yield: bản thân từ này đồng nghĩa với từ output, do đó dĩ nhiên nhiệm vụ của nó là xuất dữ liệu. Vậy chỉ nên dùng cho việc xuất những dữ liệu nhỏ. @section: Có nghĩa là phần, đoạn hay mảnh. Rõ ràng từ khóa này nhắm tới việc phân nhỏ layout ra thành từng đoạn nhỏ để các trang con ghi nội dung vào các vị trí đánh dấu.
Về mặt kỹ thuật, thật sự khi sử dụng @section, các trang con sẽ có thể ghi đè, hoặc ghi nối thêm nội dung bằng từ khóa @parent. Khi có từ khóa này, Blade sẽ lấy nội dung trong section của layout “chắp vào” trước nội dung của @section ở trang con. Còn khi sử dụng @yield , nội dung ở trang con sẽ
Sinh viên thực hiện: Nguyễn Linh – 12CNTT 33
luôn luôn ghi đè vào vị trí đánh dấu ở layout, mà không thể nối thêm dữ liệu ở layout vào như khi dùng @section.