Laravel: Bắt đầu
- Giới thiệu
- Tạo các lớp mô hình
- Các quy ước về mô hình hùng hồn
- Truy xuất mô hình
- Truy xuất Mô hình Đơn lẻ / Tổng hợp
- Chèn & Cập nhật Mô hình
- Xóa mô hình
- Nhân rộng mô hình
- Phạm vi truy vấn
- So sánh các mô hình
- Sự kiện
Giới thiệu
Laravel tích hợp Eloquent, một trình ánh xạ quan hệ đối tượng (ORM) làm cho việc tương tác với cơ sở dữ liệu của bạn trở nên thú vị hơn. Khi sử dụng Eloquent, mỗi bảng cơ sở dữ liệu sẽ có một "Model" tương ứng được sử dụng để tương tác với bảng đó. Ngoài việc truy xuất các bản ghi từ bảng cơ sở dữ liệu, Eloquent cho phép bạn chèn, cập nhật và xóa các bản ghi khỏi bảng.
Trước khi bắt đầu, hãy đảm bảo định cấu hình kết nối cơ sở dữ liệu trong
config/database.php
tệp cấu hình ứng dụng của bạn . Để biết thêm thông tin về cách định cấu hình cơ sở dữ liệu của bạn, hãy xem tài liệu cấu hình cơ sở dữ liệu.
Tạo lớp Model
Để bắt đầu, hãy tạo một model Eloquent. Model thường nằm trong thư mục app\Models
và mở rộng từ lớp Illuminate\Database\Eloquent\Model
. Bạn có thể sử dụng lệnh Artisan make:model
để tạo một model mới.
Ví dụ:
php artisan make:model Flight
Nếu bạn muốn tạo database migration khi tạo model, bạn có thể sử dụng tùy chọn --migration
hoặc -m
.
Ví dụ:
php artisan make:model Flight --migration
Bạn có thể tạo nhiều loại lớp khác nhau khi tạo model, chẳng hạn như factory, seeder hay controller. Ngoài ra, các tùy chọn này có thể được kết hợp để tạo nhiều lớp cùng một lúc.
Ví dụ:
# tạo model và lớp FlightFactory
php artisan make:model Flight --factory
php artisan make:model Flight -f
# tạo model và lớp FlightSeeder
php artisan make:model Flight --seed
php artisan make:model Flight -s
# tạo model và lớp FlightController
php artisan make:model Flight --controller
php artisan make:model Flight -c
# tạo model và các migration, factory, seeder, controller
php artisan make:model Flight -mfsc
Quy ước về model Eloquent
Model được tạo bằng lệnh make:model
sẽ được đặt trong thư mục app/Models
. Hãy xét một lớp model cơ bản sau đây:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
Tên bảng
Ở ví dụ trên, bạn có thể nhận thấy rằng ta đã không cho Eloquent biết bảng cơ sở dữ liệu nào tương ứng với model Flight
của ta. Theo quy ước thì tên số nhiều của lớp sẽ được sử dụng làm tên bảng trừ khi một tên khác ta chỉ định. Vì vậy, trong trường hợp này, Eloquent sẽ giả sử model Flight
lưu trữ các bản ghi trong bảng flights
, còn model AirTrafficController
chẳng hạn sẽ lưu trữ các bản ghi trong bảng air_traffic_controllers
.
Nếu bảng tương ứng của model không phù hợp với quy ước này, thì ta có thể chỉ định tên bảng của model theo cách thủ công bằng cách tạo thuộc tính $table
trên model.
Ví dụ:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $table = 'my_flights';
}
Khóa chính (Primary Key - PK)
Eloquent cũng sẽ giả định rằng bảng cơ sở dữ liệu tương ứng của mỗi model có một cột khóa chính được đặt tên id
. Nếu cần, bạn có thể tạo thuộc tính protected $primaryKey
model để chỉ định một cột khác đóng vai trò là khóa chính của model.
Ví dụ:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $primaryKey = 'flight_id';
}
Ngoài ra, Eloquent giả định rằng khóa chính là một giá trị số nguyên tăng dần, có nghĩa là Eloquent sẽ tự động chuyển giá trị khóa chính thành một số nguyên. Nếu bạn muốn sử dụng khóa chính không tăng hoặc không phải số, bạn phải tạo thuộc tính public $incrementing
và đặt giá trị thành false
.
Ví dụ:
<?php
class Flight extends Model
{
public $incrementing = false;
}
Nếu khóa chính của model không phải là số nguyên, bạn cần đặt thuộc tính protected $keyType
thành string
.
Ví dụ:
<?php
class Flight extends Model
{
protected $keyType = 'string';
}
Khóa chính đặt trên nhiều cột
Eloquent yêu cầu mỗi model phải có ít nhất một "ID" nhận dạng duy nhất có thể dùng làm khóa chính. Nếu khóa chính đặt trên nhiều cột thì sẽ không được Eloquent hỗ trợ. Tuy nhiên, bạn có thể tự do thêm vào bảng các chỉ mục duy nhất trên nhiều cột.
Timestamps
Theo mặc định thì Eloquent mong muốn có các cột created_at
và updated_at
ở trong bảng. Eloquent sẽ tự động đặt các giá trị cho các cột này khi model được tạo hoặc cập nhật. Nếu bạn không muốn các cột này được quản lý tự động bởi Eloquent, thì bạn nên đặt thuộc tính $timestamps
thành false
.
Ví dụ:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
public $timestamps = false;
}
Nếu bạn cần tùy chỉnh định dạng timestamps thì bạn hãy đặt giá trị cho thuộc tính $dateFormat
. Thuộc tính này sẽ xác định cách các thuộc tính ngày tháng được lưu trữ trong cơ sở dữ liệu cũng như định dạng của chúng khi model được tuần tự hóa thành một mảng hoặc JSON:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $dateFormat = 'U';
}
Nếu bạn cần tùy chỉnh tên của các cột được sử dụng để lưu trữ dấu thời gian, thì bạn có thể định nghĩa các hằng CREATED_AT
và UPDATED_AT
trên model như sau:
<?php
class Flight extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'updated_date';
}
Kết nối cơ sở dữ liệu
Theo mặc định, tất cả các model Eloquent sẽ sử dụng kết nối cơ sở dữ liệu mặc định được cấu hình cho ứng dụng của bạn. Nếu bạn muốn chỉ định một kết nối khác sẽ được sử dụng khi tương tác với một model cụ thể thì bạn định nghĩa thuộc tính $connection
như sau:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $connection = 'sqlite';
}
Giá trị thuộc tính mặc định
Theo mặc định thì khi một model mới được tạo sẽ không chứa bất kỳ giá trị thuộc tính nào. Nếu bạn muốn tạo các giá trị mặc định cho một số thuộc tính của model thì bạn có thể sử dụng thuộc tính $attributes
như sau:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $attributes = [
'delayed' => false,
];
}
Truy xuất model
Khi bạn đã tạo được model thì bạn có thể bắt đầu truy xuất dữ liệu từ cơ sở dữ liệu. Bạn có thể coi mỗi model Eloquent như là một trình tạo truy vấn (query builder) cho phép bạn truy vấn các bảng cơ sở dữ liệu được liên kết với model. Phương thức all của model sẽ truy xuất tất cả các bản ghi từ bảng cơ sở dữ liệu liên quan.
Ví dụ:
use App\Models\Flight;
foreach (Flight::all() as $flight) {
echo $flight->name;
}
Xây dựng các truy vấn
Phương thức Eloquent all sẽ trả về tất cả các kết quả trong bảng của model. Tuy nhiên, vì mỗi model Eloquent đóng vai trò như một query builder, nên bạn có thể thêm các ràng buộc bổ sung vào các truy vấn và sau đó gọi phương thức get để truy xuất kết quả.
Ví dụ:
$flights = Flight::where('active', 1)
->orderBy('name')
->take(10)
->get();
Vì model Eloquent là trình tạo truy vấn (query builder), nên bạn nên xem lại tất cả các phương thức được cung cấp bởi trình tạo truy vấn của Laravel. Bạn có thể sử dụng bất kỳ phương thức nào trong số những phương thức này khi viết các truy vấn Eloquent.
Làm mới model
Bạn có thể làm mới model bằng cách sử dụng các phương thức fresh
và refresh
. Phương thức fresh
truy xuất lại model từ cơ sở dữ liệu.
Ví dụ:
$flight = Flight::where('number', 'FR 900')->first();
$freshFlight = $flight->fresh();
Phương thức refresh
sẽ làm mới lại model. Ngoài ra, tất cả các quan hệ đã tải của nó cũng sẽ được làm mới.
Ví dụ:
$flight = Flight::where('number', 'FR 900')->first();
$flight->number = 'FR 456';
$flight->refresh();
$flight->number; // "FR 900"
Collection
Các phương thức Eloquent như all
và get
truy xuất nhiều bản ghi từ cơ sở dữ liệu. Tuy nhiên, các phương thức này không trả về một mảng PHP thuần túy. Thay vào đó, các phương thức này sẽ trả về một thể hiện của lớp Illuminate\Database\Eloquent\Collection
.
Lớp Collection
mở rộng từ lớp cơ sở Illuminate\Support\Collection, lớp này cung cấp nhiều phương thức hữu ích để tương tác với dữ liệu.
Ví dụ như phương thức reject
có thể được sử dụng để xóa các model khỏi collection dựa trên kết quả của một lần gọi:
$flights = Flight::where('destination', 'Paris')->get();
$flights = $flights->reject(function ($flight) {
return $flight->cancelled;
});
Ngoài ra, lớp Eloquent Collection còn cung cấp một số phương thức bổ sung dành riêng cho việc tương tác với các model Eloquent.
Vì tất cả các bộ sưu tập của Laravel đều triển khai các giao diện có thể lặp lại của PHP, nên bạn có thể lặp lại các bộ sưu tập như thể chúng là một mảng.
Ví dụ:
foreach ($flights as $flight) {
echo $flight->name;
}
Phương thức chunk và chunkById
Ứng dụng của bạn có thể hết bộ nhớ nếu bạn cố gắng tải hàng chục nghìn bản ghi Eloquent thông qua các phương thức all
hoặc get
. Vì vậy, thay vì sử dụng các phương thức này thì bạn có thể sử dụng phương thức chunk
để xử lý số lượng lớn các model được hiệu quả hơn.
Phương thức chunk
sẽ lấy một tập hợp con của các model rồi truyền chúng tới closure (bao đóng - hàm) để xử lý. Vì chỉ một phần hiện tại của các model Eloquent được truy xuất tại một thời điểm, nên phương thức chunk
sẽ giảm đáng kể mức sử dụng bộ nhớ khi làm việc với một số lượng lớn các model.
Ví dụ:
use App\Models\Flight;
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
Đối số đầu tiên được truyền cho chunk
là số lượng bản ghi bạn muốn nhận trên mỗi "đoạn". Bao đóng sẽ được gọi cho mỗi đoạn được truy xuất từ cơ sở dữ liệu. Một truy vấn cơ sở dữ liệu sẽ được thực hiện để truy xuất từng đoạn bản ghi được chuyển đến bao đóng.
Nếu bạn đang lọc các kết quả của phương thức chunk
dựa trên một cột mà bạn cũng sẽ cập nhật trong khi lặp lại các kết quả, thì bạn nên sử dụng phương thức chunkById
bởi vì nếu sử dụng chunk
trong tình huống này có thể dẫn đến kết quả không mong muốn và không nhất quán.
Phương thức chunkById
sẽ luôn truy xuất model có cột id
lớn hơn model cuối cùng trong đoạn trước:
Flight::where('departed', true)
->chunkById(200, function ($flights) {
$flights->each->update(['departed' => false]);
}, $column = 'id');
Phương thức cursor
Tương tự như phương thức chunk
, phương thức cursor
có thể được sử dụng để giảm đáng kể mức tiêu thụ bộ nhớ của ứng dụng khi lấy được hàng chục nghìn bản ghi.
cursor
sẽ chỉ thực hiện một truy vấn cơ sở dữ liệu duy nhất; tuy nhiên, các model Eloquent riêng lẻ sẽ không bị phân rã cho đến khi chúng thực sự được lặp lại. Do đó, chỉ có một model Eloquent được lưu trong bộ nhớ tại bất kỳ thời điểm nào trong khi lặp qua con trỏ. cursor
sử dụng trình tạo PHP để triển khai chức năng này:
use App\Models\Flight;
foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) {
//
}
cursor
sẽ trả về một thể hiện Illuminate\Support\LazyCollection
. LazyCollection cho phép bạn sử dụng nhiều phương thức có sẵn trong khi chỉ tải một model duy nhất vào bộ nhớ tại một thời điểm.
Ví dụ:
use App\Models\User;
$users = User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
zzzTruy vấn con nâng cao
Lựa chọn truy vấn con
Eloquent cũng cung cấp hỗ trợ truy vấn con nâng cao, cho phép bạn lấy thông tin từ các bảng liên quan trong một truy vấn duy nhất. Ví dụ, hãy tưởng tượng rằng chúng ta có một bảng các chuyến bay destinations
và một bảng các flights
điểm đến. Các flights
bảng chứa một arrived_at
cột mà chỉ khi chuyến bay đến địa điểm đến.
Sử dụng chức năng truy vấn phụ có sẵn cho phương thức select
và trình tạo truy vấn addSelect
, chúng tôi có thể chọn tất cả destinations
và tên của chuyến bay đã đến điểm đến đó gần đây nhất bằng cách sử dụng một truy vấn:
use App\Models\Destination;
use App\Models\Flight;
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderByDesc('arrived_at')
->limit(1)
])->get();
Đặt hàng truy vấn con
Ngoài ra, orderBy
chức năng của trình tạo truy vấn hỗ trợ các truy vấn con. Tiếp tục sử dụng ví dụ về chuyến bay của chúng tôi, chúng tôi có thể sử dụng chức năng này để sắp xếp tất cả các điểm đến dựa trên thời điểm chuyến bay cuối cùng đến điểm đến đó. Một lần nữa, điều này có thể được thực hiện trong khi thực hiện một truy vấn cơ sở dữ liệu duy nhất:
return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderByDesc('arrived_at')
->limit(1)
)->get();
Truy xuất Mô hình Đơn lẻ / Tổng hợp
Ngoài lấy tất cả các hồ sơ phù hợp với một truy vấn cụ thể, bạn cũng có thể lấy hồ sơ đơn sử dụng find
, first
hoặc firstWhere
phương pháp. Thay vì trả về một tập hợp các mô hình, các phương thức này trả về một cá thể mô hình duy nhất:
use App\Models\Flight;
// Retrieve a model by its primary key...
$flight = Flight::find(1);
// Retrieve the first model matching the query constraints...
$flight = Flight::where('active', 1)->first();
// Alternative to retrieving the first model matching the query constraints...
$flight = Flight::firstWhere('active', 1);
Đôi khi bạn có thể muốn lấy kết quả đầu tiên của một truy vấn hoặc thực hiện một số hành động khác nếu không tìm thấy kết quả nào. Các firstOr
phương pháp sẽ trả lại kết quả phù hợp đầu tiên truy vấn hoặc, nếu không có kết quả được tìm thấy, thực hiện việc đóng cửa nhất định. Giá trị được trả về bởi bao đóng sẽ được coi là kết quả của firstOr
phương thức:
$model = Flight::where('legs', '>', 3)->firstOr(function () {
// ...
});
Không tìm thấy ngoại lệ
Đôi khi bạn có thể muốn đưa ra một ngoại lệ nếu không tìm thấy một mô hình. Điều này đặc biệt hữu ích trong các tuyến đường hoặc bộ điều khiển. Các phương thức findOrFail
và firstOrFail
sẽ truy xuất kết quả đầu tiên của truy vấn; tuy nhiên, nếu không tìm thấy kết quả nào, một Illuminate\Database\Eloquent\ModelNotFoundException
sẽ được ném ra:
$flight = Flight::findOrFail(1);
$flight = Flight::where('legs', '>', 3)->firstOrFail();
Nếu ModelNotFoundException
không bắt được, một phản hồi HTTP 404 sẽ tự động được gửi lại cho máy khách:
use App\Models\Flight;
Route::get('/api/flights/{id}', function ($id) {
return Flight::findOrFail($id);
});
Lấy hoặc tạo mô hình
Các firstOrCreate
phương pháp sẽ cố gắng xác định vị trí một kỷ lục cơ sở dữ liệu bằng cách sử dụng cặp cột / giá trị nhất định. Nếu không thể tìm thấy mô hình trong cơ sở dữ liệu, một bản ghi sẽ được chèn với các thuộc tính do hợp nhất đối số mảng đầu tiên với đối số mảng thứ hai tùy chọn:
Các firstOrNew
phương pháp, như firstOrCreate
, sẽ cố gắng xác định vị trí một kỷ lục trong cơ sở dữ liệu phù hợp với các thuộc tính nhất định. Tuy nhiên, nếu một mô hình không được tìm thấy, một phiên bản mô hình mới sẽ được trả về. Lưu ý rằng mô hình được trả về firstOrNew
vẫn chưa được lưu vào cơ sở dữ liệu. Bạn sẽ cần phải gọi save
phương thức theo cách thủ công để duy trì nó:
use App\Models\Flight;
// Retrieve flight by name or create it if it doesn't exist...
$flight = Flight::firstOrCreate([
'name' => 'London to Paris'
]);
// Retrieve flight by name or create it with the name, delayed, and arrival_time attributes...
$flight = Flight::firstOrCreate(
['name' => 'London to Paris'],
['delayed' => 1, 'arrival_time' => '11:30']
);
// Retrieve flight by name or instantiate a new Flight instance...
$flight = Flight::firstOrNew([
'name' => 'London to Paris'
]);
// Retrieve flight by name or instantiate with the name, delayed, and arrival_time attributes...
$flight = Flight::firstOrNew(
['name' => 'Tokyo to Sydney'],
['delayed' => 1, 'arrival_time' => '11:30']
);
Lấy tổng hợp
Khi tương tác với các mô hình hùng hồn, bạn cũng có thể sử dụng count
, sum
, max
, và các phương pháp tổng hợp được cung cấp bởi các Laravel xây dựng truy vấn . Như bạn có thể mong đợi, các phương thức này trả về một giá trị vô hướng thay vì một phiên bản mô hình Eloquent:
$count = Flight::where('active', 1)->count();
$max = Flight::where('active', 1)->max('price');
Chèn & Cập nhật Mô hình
Chèn
Tất nhiên, khi sử dụng Eloquent, chúng ta không chỉ cần lấy các mô hình từ cơ sở dữ liệu. Chúng tôi cũng cần phải chèn các bản ghi mới. Rất may, Eloquent làm cho nó trở nên đơn giản. Để chèn một bản ghi mới vào cơ sở dữ liệu, bạn nên khởi tạo một phiên bản mô hình mới và thiết lập các thuộc tính trên mô hình. Sau đó, gọi save
phương thức trên cá thể mô hình:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Flight;
use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* Store a new flight in the database.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// Validate the request...
$flight = new Flight;
$flight->name = $request->name;
$flight->save();
}
}
Trong ví dụ này, chúng tôi gán name
trường từ yêu cầu HTTP đến cho name
thuộc tính của App\Models\Flight
cá thể mô hình. Khi chúng ta gọi save
phương thức, một bản ghi sẽ được chèn vào cơ sở dữ liệu. Dấu thời gian created_at
và của mô hình updated_at
sẽ tự động được đặt khi save
phương thức được gọi, vì vậy không cần đặt chúng theo cách thủ công.
Ngoài ra, bạn có thể sử dụng create
phương pháp này để "lưu" một mô hình mới bằng cách sử dụng một câu lệnh PHP. Phiên bản mô hình được chèn sẽ được trả lại cho bạn theo create
phương thức:
use App\Models\Flight;
$flight = Flight::create([
'name' => 'London to Paris',
]);
Tuy nhiên, trước khi sử dụng create
phương thức, bạn sẽ cần chỉ định một fillable
hoặc thuộc guarded
tính trên lớp mô hình của mình. Các thuộc tính này là bắt buộc vì tất cả các mô hình Eloquent được bảo vệ khỏi các lỗ hổng phân công hàng loạt theo mặc định. Để tìm hiểu thêm về bài tập khối lượng, mời các bạn tham khảo tài liệu bài tập khối lượng lớn .
Cập nhật
Các save
phương pháp cũng có thể được sử dụng để mô hình cập nhật đã tồn tại trong cơ sở dữ liệu. Để cập nhật một mô hình, bạn nên truy xuất mô hình đó và đặt bất kỳ thuộc tính nào bạn muốn cập nhật. Sau đó, bạn nên gọi save
phương thức của mô hình . Một lần nữa, updated_at
dấu thời gian sẽ tự động được cập nhật, vì vậy không cần phải đặt giá trị của nó theo cách thủ công:
use App\Models\Flight;
$flight = Flight::find(1);
$flight->name = 'Paris to London';
$flight->save();
Cập nhật hàng loạt
Cập nhật cũng có thể được thực hiện đối với các mô hình phù hợp với một truy vấn nhất định. Trong ví dụ này, tất cả các chuyến bay được active
và có một destination
số San Diego
sẽ được đánh dấu là bị trì hoãn:
Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);
Các update
phương pháp dự đoán một mảng của các cặp cột và giá trị đại diện cho các cột cần được cập nhật.
Khi phát hành một bản cập nhật hàng loạt qua hùng hồn, những
saving
,saved
,updating
, vàupdated
các sự kiện mô hình sẽ không được sa thải vì các mô hình được cập nhật. Điều này là do các mô hình không bao giờ thực sự được truy xuất khi phát hành một bản cập nhật hàng loạt.
Kiểm tra các thay đổi thuộc tính
Hùng hồn cung cấp isDirty
, isClean
và wasChanged
các phương pháp để kiểm tra trạng thái nội tại của mô hình của bạn và xác định cách thuộc tính của nó đã thay đổi từ khi mô hình được lấy ra ban đầu.
Các isDirty
phương pháp xác định nếu có các thuộc tính của mô hình đã được thay đổi kể từ khi mô hình đã được lấy ra. Bạn có thể chuyển một tên thuộc tính cụ thể cho isDirty
phương thức để xác định xem một thuộc tính cụ thể có bị bẩn hay không. Điều isClean
này sẽ xác định xem một thuộc tính vẫn không thay đổi kể từ khi mô hình được truy xuất. Phương thức này cũng chấp nhận một đối số thuộc tính tùy chọn:
use App\Models\User;
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->save();
$user->isDirty(); // false
$user->isClean(); // true
Các wasChanged
phương pháp xác định nếu có các thuộc tính đã được thay đổi khi mô hình được lưu cuối cùng trong chu kỳ yêu cầu hiện tại. Nếu cần, bạn có thể chuyển một tên thuộc tính để xem liệu một thuộc tính cụ thể có bị thay đổi hay không:
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->save();
$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged('first_name'); // false
Các getOriginal
phương thức trả về một mảng chứa các thuộc tính ban đầu của mô hình không phụ thuộc bất kỳ thay đổi mô hình vì nó đã được lấy ra. Nếu cần, bạn có thể chuyển một tên thuộc tính cụ thể để nhận giá trị ban đầu của một thuộc tính cụ thể:
$user = User::find(1);
$user->name; // John
$user->email; // john@example.com
$user->name = "Jack";
$user->name; // Jack
$user->getOriginal('name'); // John
$user->getOriginal(); // Array of original attributes...
Phân công hàng loạt
Bạn có thể sử dụng create
phương pháp này để "lưu" một mô hình mới bằng cách sử dụng một câu lệnh PHP. Phiên bản mô hình được chèn sẽ được trả lại cho bạn theo phương thức:
use App\Models\Flight;
$flight = Flight::create([
'name' => 'London to Paris',
]);
Tuy nhiên, trước khi sử dụng create
phương thức, bạn sẽ cần chỉ định một fillable
hoặc thuộc guarded
tính trên lớp mô hình của mình. Các thuộc tính này là bắt buộc vì tất cả các mô hình Eloquent được bảo vệ khỏi các lỗ hổng phân công hàng loạt theo mặc định.
Lỗ hổng phân công hàng loạt xảy ra khi người dùng chuyển một trường yêu cầu HTTP không mong muốn và trường đó thay đổi một cột trong cơ sở dữ liệu của bạn mà bạn không mong đợi. Ví dụ: một người dùng độc hại có thể gửi một is_admin
tham số thông qua một yêu cầu HTTP, sau đó được chuyển đến create
phương thức của mô hình của bạn , cho phép người dùng tự báo cáo cho quản trị viên.
Vì vậy, để bắt đầu, bạn nên xác định thuộc tính mô hình nào bạn muốn để có thể gán hàng loạt. Bạn có thể làm điều này bằng cách sử dụng thuộc $fillable
tính trên mô hình. Ví dụ: hãy làm cho name
thuộc tính của Flight
khối lượng mô hình của chúng ta có thể gán được:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}
Khi bạn đã chỉ định thuộc tính nào có thể gán hàng loạt, bạn có thể sử dụng create
phương pháp này để chèn một bản ghi mới vào cơ sở dữ liệu. Các create
phương thức trả về trường hợp mô hình mới được tạo ra:
$flight = Flight::create(['name' => 'London to Paris']);
Nếu bạn đã có một phiên bản mô hình, bạn có thể sử dụng fill
phương thức để điền vào nó một mảng thuộc tính:
$flight->fill(['name' => 'Amsterdam to Frankfurt']);
Chuyển nhượng hàng loạt & các cột JSON
Khi gán các cột JSON, khóa có thể gán khối lượng của mỗi cột phải được chỉ định trong $fillable
mảng của mô hình của bạn . Để bảo mật, Laravel không hỗ trợ cập nhật các thuộc tính JSON lồng nhau khi sử dụng thuộc guarded
tính:
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'options->enabled',
];
Cho phép phân công hàng loạt
Nếu bạn muốn gán hàng loạt các thuộc tính của mình, bạn có thể xác định thuộc tính của mô hình $guarded
là một mảng trống. Nếu bạn chọn để unguard mô hình của bạn, bạn nên chăm sóc đặc biệt để luôn tay nghề các mảng truyền cho hùng biện của fill
, create
và update
phương pháp:
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
Cảnh báo
Đôi khi, bạn có thể cần cập nhật một mô hình hiện có hoặc tạo một mô hình mới nếu không có mô hình phù hợp nào tồn tại. Giống như firstOrCreate
phương thức, updateOrCreate
phương thức vẫn tồn tại mô hình, vì vậy không cần phải gọi save
phương thức theo cách thủ công .
Trong ví dụ dưới đây, nếu một chuyến bay tồn tại với departure
vị trí của Oakland
và destination
vị trí của San Diego
, các cột price
và của nó discounted
sẽ được cập nhật. Nếu không có chuyến bay nào như vậy tồn tại, một chuyến bay mới sẽ được tạo với các thuộc tính là kết quả của việc hợp nhất mảng đối số đầu tiên với mảng đối số thứ hai:
$flight = Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);
Nếu bạn muốn thực hiện nhiều "cảnh báo" trong một truy vấn, thì bạn nên sử dụng upsert
phương pháp này để thay thế. Đối số đầu tiên của phương thức bao gồm các giá trị để chèn hoặc cập nhật, trong khi đối số thứ hai liệt kê (các) cột xác định duy nhất các bản ghi trong bảng được liên kết. Đối số thứ ba và cuối cùng của phương thức là một mảng các cột cần được cập nhật nếu một bản ghi phù hợp đã tồn tại trong cơ sở dữ liệu. Các upsert
phương pháp sẽ tự động đặt created_at
và updated_at
timestamps nếu timestamps được bật trên mô hình:
Flight::upsert([
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);
Tất cả các hệ thống cơ sở dữ liệu ngoại trừ SQL Server yêu cầu các cột trong đối số thứ hai được cung cấp cho
upsert
phương thức phải có chỉ mục "chính" hoặc "duy nhất".
Xóa mô hình
Để xóa một mô hình, bạn có thể gọi delete
phương thức trên phiên bản mô hình:
use App\Models\Flight;
$flight = Flight::find(1);
$flight->delete();
Bạn có thể gọi truncate
phương thức để xóa tất cả các bản ghi cơ sở dữ liệu liên quan của mô hình. Các truncate
hoạt động cũng sẽ thiết lập lại bất kỳ ID tự động incrementing trên bàn liên quan của mô hình:
Flight::truncate();
Xóa một mô hình hiện có bằng khóa chính của nó
Trong ví dụ trên, chúng tôi đang truy xuất mô hình từ cơ sở dữ liệu trước khi gọi delete
phương thức. Tuy nhiên, nếu bạn biết khóa chính của mô hình, bạn có thể xóa mô hình mà không cần truy xuất rõ ràng bằng cách gọi destroy
phương thức. Ngoài việc chấp nhận một khóa chính, destroy
phương thức sẽ chấp nhận nhiều khóa chính, một mảng khóa chính hoặc một tập hợp các khóa chính:
Flight::destroy(1);
Flight::destroy(1, 2, 3);
Flight::destroy([1, 2, 3]);
Flight::destroy(collect([1, 2, 3]));
Các
destroy
phương pháp tải mỗi mô hình độc lập và gọidelete
phương pháp sao chodeleting
vàdeleted
sự kiện được gửi đi đúng cho mỗi mô hình.
Xóa mô hình bằng truy vấn
Tất nhiên, bạn có thể tạo một truy vấn Eloquent để xóa tất cả các mô hình phù hợp với tiêu chí truy vấn của bạn. Trong ví dụ này, chúng tôi sẽ xóa tất cả các chuyến bay được đánh dấu là không hoạt động. Giống như cập nhật hàng loạt, xóa hàng loạt sẽ không gửi các sự kiện mô hình cho các mô hình bị xóa:
$deletedRows = Flight::where('active', 0)->delete();
Khi thực hiện câu lệnh xóa hàng loạt qua Eloquent, các sự kiện
deleting
vàdeleted
mô hình sẽ không được gửi cho các mô hình đã xóa. Điều này là do các mô hình không bao giờ thực sự được truy xuất khi thực hiện câu lệnh xóa.
Xóa mềm
Ngoài việc thực sự xóa các bản ghi khỏi cơ sở dữ liệu của bạn, Eloquent cũng có thể thực hiện các mô hình "xóa mềm". Khi các mô hình bị xóa mềm, chúng không thực sự bị xóa khỏi cơ sở dữ liệu của bạn. Thay vào đó, một deleted_at
thuộc tính được đặt trên mô hình cho biết ngày và giờ tại đó mô hình bị "xóa". Để bật tính năng xóa mềm cho một mô hình, hãy thêm Illuminate\Database\Eloquent\SoftDeletes
đặc điểm vào mô hình:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Flight extends Model
{
use SoftDeletes;
}
Các
SoftDeletes
đặc điểm sẽ tự động castdeleted_at
thuộc tính cho mộtDateTime
/Carbon
Ví dụ cho bạn.
Bạn cũng nên thêm deleted_at
cột vào bảng cơ sở dữ liệu của mình. Trình tạo lược đồ Laravel chứa một phương thức trợ giúp để tạo cột này:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Facades\Schema;
Schema::table('flights', function (Blueprint $table) {
$table->softDeletes();
});
Schema::table('flights', function (Blueprint $table) {
$table->dropSoftDeletes();
});
Bây giờ, khi bạn gọi delete
phương thức trên mô hình, deleted_at
cột sẽ được đặt thành ngày và giờ hiện tại. Tuy nhiên, bản ghi cơ sở dữ liệu của mô hình sẽ được để lại trong bảng. Khi truy vấn một mô hình sử dụng tính năng xóa mềm, các mô hình đã xóa mềm sẽ tự động bị loại trừ khỏi tất cả các kết quả truy vấn.
Để xác định xem một phiên bản mô hình nhất định đã bị xóa mềm hay chưa, bạn có thể sử dụng trashed
phương pháp:
if ($flight->trashed()) {
//
}
Khôi phục các mô hình đã xóa mềm
Đôi khi bạn có thể muốn "hủy xóa" một mô hình đã xóa mềm. Để khôi phục một mô hình đã xóa mềm, bạn có thể gọi restore
phương thức trên một phiên bản mô hình. Các restore
phương pháp sẽ thiết lập của mô hình deleted_at
cột để null
:
$flight->restore();
Bạn cũng có thể sử dụng restore
phương pháp này trong một truy vấn để khôi phục nhiều mô hình. Một lần nữa, giống như các hoạt động "hàng loạt" khác, thao tác này sẽ không gửi bất kỳ sự kiện mô hình nào cho các mô hình được khôi phục:
Flight::withTrashed()
->where('airline_id', 1)
->restore();
Các restore
phương pháp cũng có thể được sử dụng khi xây dựng mối quan hệ truy vấn:
$flight->history()->restore();
Xóa vĩnh viễn các mô hình
Đôi khi bạn có thể cần thực sự xóa một mô hình khỏi cơ sở dữ liệu của mình. Bạn có thể sử dụng forceDelete
phương pháp để xóa vĩnh viễn một mô hình đã xóa mềm khỏi bảng cơ sở dữ liệu:
$flight->forceDelete();
Bạn cũng có thể sử dụng forceDelete
phương pháp này khi xây dựng các truy vấn mối quan hệ hùng hồn:
$flight->history()->forceDelete();
Truy vấn các mô hình đã xóa mềm
Bao gồm các mô hình đã xóa mềm
Như đã lưu ý ở trên, các mô hình đã xóa mềm sẽ tự động bị loại trừ khỏi kết quả truy vấn. Tuy nhiên, bạn có thể buộc các mô hình đã xóa mềm được đưa vào kết quả của truy vấn bằng cách gọi withTrashed
phương thức trên truy vấn:
use App\Models\Flight;
$flights = Flight::withTrashed()
->where('account_id', 1)
->get();
Các withTrashed
phương pháp cũng có thể được gọi khi xây dựng một mối quan hệ truy vấn:
$flight->history()->withTrashed()->get();
Chỉ truy xuất các mô hình đã xóa mềm
Các onlyTrashed
phương pháp sẽ lấy chỉ mô hình xóa mềm:
$flights = Flight::onlyTrashed()
->where('airline_id', 1)
->get();
Nhân rộng mô hình
Bạn có thể tạo một bản sao chưa lưu của một phiên bản mô hình hiện có bằng cách sử dụng replicate
phương pháp này. Phương pháp này đặc biệt hữu ích khi bạn có các phiên bản mô hình chia sẻ nhiều thuộc tính giống nhau:
use App\Models\Address;
$shipping = Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();
Phạm vi truy vấn
Phạm vi toàn cầu
Phạm vi toàn cục cho phép bạn thêm các ràng buộc vào tất cả các truy vấn cho một mô hình nhất định. Chức năng xóa mềm của riêng Laravel sử dụng phạm vi toàn cục để chỉ truy xuất các mô hình "không bị xóa" từ cơ sở dữ liệu. Viết phạm vi toàn cục của riêng bạn có thể cung cấp một cách thuận tiện, dễ dàng để đảm bảo mọi truy vấn cho một mô hình nhất định đều nhận được những ràng buộc nhất định.
Viết phạm vi toàn cầu
Viết phạm vi toàn cầu rất đơn giản. Đầu tiên, xác định một lớp thực thi Illuminate\Database\Eloquent\Scope
giao diện. Laravel không có một vị trí thông thường mà bạn nên đặt các lớp phạm vi, vì vậy bạn có thể tự do đặt lớp này trong bất kỳ thư mục nào bạn muốn.
Các Scope
giao diện đòi hỏi bạn phải thực hiện một phương pháp: apply
. Các apply
phương pháp có thể thêm where
những hạn chế hoặc loại khác của các điều khoản với truy vấn khi cần thiết:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AncientScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('created_at', '<', now()->subYears(2000));
}
}
Nếu phạm vi toàn cầu của bạn đang thêm các cột vào mệnh đề chọn của truy vấn, bạn nên sử dụng
addSelect
phương pháp này thay vìselect
. Điều này sẽ ngăn việc vô tình thay thế mệnh đề lựa chọn hiện có của truy vấn.
Áp dụng phạm vi toàn cầu
Để gán phạm vi toàn cục cho một mô hình, bạn nên ghi đè booted
phương thức của mô hình và gọi addGlobalScope
phương thức của mô hình . Các addGlobalScope
phương pháp chấp nhận một thể hiện của phạm vi của bạn như là đối số duy nhất của nó:
<?php
namespace App\Models;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope(new AncientScope);
}
}
Sau khi thêm phạm vi trong ví dụ trên vào App\Models\User
mô hình, một lệnh gọi User::all()
phương thức sẽ thực hiện truy vấn SQL sau:
select * from `users` where `created_at` < 0021-02-18 00:00:00
Phạm vi toàn cầu ẩn danh
Eloquent cũng cho phép bạn xác định phạm vi toàn cục bằng cách sử dụng các bao đóng, điều này đặc biệt hữu ích cho các phạm vi đơn giản không đảm bảo một lớp riêng của chúng. Khi xác định phạm vi toàn cục bằng cách sử dụng bao đóng, bạn nên cung cấp tên phạm vi mà bạn chọn làm đối số đầu tiên cho addGlobalScope
phương thức:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope('ancient', function (Builder $builder) {
$builder->where('created_at', '<', now()->subYears(2000));
});
}
}
Xóa phạm vi toàn cầu
Nếu bạn muốn xóa phạm vi toàn cục cho một truy vấn nhất định, bạn có thể sử dụng withoutGlobalScope
phương pháp này. Phương thức này chấp nhận tên lớp của phạm vi toàn cục làm đối số duy nhất của nó:
User::withoutGlobalScope(AncientScope::class)->get();
Hoặc, nếu bạn đã xác định phạm vi toàn cầu bằng cách sử dụng bao đóng, bạn nên chuyển tên chuỗi mà bạn đã gán cho phạm vi toàn cầu:
User::withoutGlobalScope('ancient')->get();
Nếu bạn muốn loại bỏ một số hoặc thậm chí tất cả các phạm vi toàn cục của truy vấn, bạn có thể sử dụng withoutGlobalScopes
phương pháp:
// Remove all of the global scopes...
User::withoutGlobalScopes()->get();
// Remove some of the global scopes...
User::withoutGlobalScopes([
FirstScope::class, SecondScope::class
])->get();
Phạm vi địa phương
Phạm vi cục bộ cho phép bạn xác định các bộ ràng buộc truy vấn phổ biến mà bạn có thể dễ dàng sử dụng lại trong toàn bộ ứng dụng của mình. Ví dụ: bạn có thể cần thường xuyên truy xuất tất cả người dùng được coi là "phổ biến". Để xác định phạm vi, hãy đặt trước một phương thức Eloquent model với scope
.
Phạm vi phải luôn trả về một phiên bản trình tạo truy vấn:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include popular users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
/**
* Scope a query to only include active users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive($query)
{
return $query->where('active', 1);
}
}
Sử dụng phạm vi cục bộ
Khi phạm vi đã được xác định, bạn có thể gọi các phương thức phạm vi khi truy vấn mô hình. Tuy nhiên, bạn không nên bao gồm scope
tiền tố khi gọi phương thức. Bạn thậm chí có thể chuỗi các cuộc gọi đến các phạm vi khác nhau:
use App\Models\User;
$users = User::popular()->active()->orderBy('created_at')->get();
Việc kết hợp nhiều phạm vi mô hình Eloquent thông qua or
toán tử truy vấn có thể yêu cầu sử dụng các bao đóng để đạt được nhóm logic chính xác :
$users = User::popular()->orWhere(function (Builder $query) {
$query->active();
})->get();
Tuy nhiên, vì điều này có thể phức tạp, Laravel cung cấp một orWhere
phương thức "bậc cao" cho phép bạn kết nối các phạm vi chuỗi với nhau một cách trôi chảy mà không cần sử dụng các bao đóng:
$users = App\Models\User::popular()->orWhere->active()->get();
Phạm vi động
Đôi khi bạn có thể muốn xác định một phạm vi chấp nhận các tham số. Để bắt đầu, chỉ cần thêm các tham số bổ sung của bạn vào chữ ký của phương thức phạm vi của bạn. Tham số phạm vi phải được xác định sau $query
tham số:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $type
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
}
Khi các đối số mong đợi đã được thêm vào chữ ký của phương thức phạm vi của bạn, bạn có thể chuyển các đối số khi gọi phạm vi:
$users = User::ofType('admin')->get();
So sánh các mô hình
Đôi khi bạn có thể cần phải xác định xem hai mô hình có "giống nhau" hay không. Các phương pháp is
và isNot
có thể được sử dụng để nhanh chóng xác minh hai mô hình có cùng khóa chính, bảng và kết nối cơ sở dữ liệu hay không:
if ($post->is($anotherPost)) {
//
}
if ($post->isNot($anotherPost)) {
//
}
Các is
và isNot
phương pháp này cũng có sẵn khi sử dụng belongsTo
, hasOne
, morphTo
, và morphOne
các mối quan hệ . Phương pháp này đặc biệt hữu ích khi bạn muốn so sánh một mô hình có liên quan mà không đưa ra một truy vấn để truy xuất mô hình đó:
if ($post->author()->is($user)) {
//
}
Sự kiện
Mô hình hùng hồn cử một số sự kiện, cho phép bạn để móc vào những khoảnh khắc sau trong vòng đời của một mô hình: retrieved
, creating
, created
, updating
, updated
, saving
, saved
, deleting
, deleted
, restoring
, restored
, và replicating
.
Sự retrieved
kiện sẽ gửi khi một mô hình hiện có được truy xuất từ cơ sở dữ liệu. Khi một mô hình mới được lưu lần đầu tiên, các sự kiện creating
và created
sẽ gửi đi. Các sự kiện updating
/ updated
sẽ gửi đi khi một mô hình hiện có được sửa đổi và save
phương thức được gọi. Các sự kiện saving
/ saved
sẽ gửi đi khi một mô hình được tạo hoặc cập nhật - ngay cả khi các thuộc tính của mô hình không bị thay đổi.
Để bắt đầu lắng nghe các sự kiện mô hình, hãy xác định một thuộc $dispatchesEvents
tính trên mô hình Eloquent của bạn. Thuộc tính này ánh xạ các điểm khác nhau trong vòng đời của mô hình Eloquent cho các lớp sự kiện của riêng bạn . Mỗi lớp sự kiện mô hình sẽ nhận được một thể hiện của mô hình bị ảnh hưởng thông qua phương thức khởi tạo của nó:
<?php
namespace App\Models;
use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The event map for the model.
*
* @var array
*/
protected $dispatchesEvents = [
'saved' => UserSaved::class,
'deleted' => UserDeleted::class,
];
}
Sau khi xác định và lập bản đồ các sự kiện Eloquent của bạn, bạn có thể sử dụng trình nghe sự kiện để xử lý các sự kiện.
Khi phát hành một bản cập nhật tin đại chúng hoặc truy vấn xóa qua hùng hồn, những
saved
,updated
,deleting
, vàdeleted
các sự kiện mô hình sẽ không được gửi đi cho các mô hình bị ảnh hưởng. Điều này là do các mô hình không bao giờ thực sự được truy xuất khi thực hiện cập nhật hoặc xóa hàng loạt.
Sử dụng Closures
Thay vì sử dụng các lớp sự kiện tùy chỉnh, bạn có thể đăng ký các bao đóng thực thi khi các sự kiện mô hình khác nhau được gửi đi. Thông thường, bạn nên đăng ký các lần đóng này trong booted
phương thức của mô hình của bạn:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::created(function ($user) {
//
});
}
}
Nếu cần, bạn có thể sử dụng trình nghe sự kiện ẩn danh có thể xếp hàng đợi khi đăng ký các sự kiện mô hình. Điều này sẽ hướng dẫn Laravel thực thi trình xử lý sự kiện mô hình trong nền bằng cách sử dụng hàng đợi ứng dụng của bạn :
use function Illuminate\Events\queueable;
static::created(queueable(function ($user) {
//
}));
Quan sát viên
Xác định người quan sát
Nếu bạn đang nghe nhiều sự kiện trên một mô hình nhất định, bạn có thể sử dụng các quan sát viên để nhóm tất cả những người nghe của bạn thành một lớp duy nhất. Các lớp trình quan sát có tên phương thức phản ánh các sự kiện Eloquent mà bạn muốn lắng nghe. Mỗi phương thức này nhận mô hình bị ảnh hưởng làm đối số duy nhất của chúng. Lệnh make:observer
Artisan là cách dễ nhất để tạo một lớp quan sát viên mới:
php artisan make:observer UserObserver --model=User
Lệnh này sẽ đặt trình quan sát mới trong App/Observers
thư mục của bạn . Nếu thư mục này không tồn tại, Artisan sẽ tạo nó cho bạn. Người quan sát mới của bạn sẽ trông giống như sau:
<?php
namespace App\Observers;
use App\Models\User;
class UserObserver
{
/**
* Handle the User "created" event.
*
* @param \App\Models\User $user
* @return void
*/
public function created(User $user)
{
//
}
/**
* Handle the User "updated" event.
*
* @param \App\Models\User $user
* @return void
*/
public function updated(User $user)
{
//
}
/**
* Handle the User "deleted" event.
*
* @param \App\Models\User $user
* @return void
*/
public function deleted(User $user)
{
//
}
/**
* Handle the User "forceDeleted" event.
*
* @param \App\Models\User $user
* @return void
*/
public function forceDeleted(User $user)
{
//
}
}
Để đăng ký một quan sát viên, bạn cần gọi observe
phương thức trên mô hình mà bạn muốn quan sát. Bạn có thể đăng ký quan sát viên theo boot
phương thức của App\Providers\EventServiceProvider
nhà cung cấp dịch vụ ứng dụng của bạn :
use App\Models\User;
use App\Observers\UserObserver;
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
Sự kiện tắt tiếng
Đôi khi, bạn có thể cần tạm thời "tắt tiếng" tất cả các sự kiện do mô hình kích hoạt. Bạn có thể đạt được điều này bằng cách sử dụng withoutEvents
phương pháp này. Các withoutEvents
phương pháp chấp nhận một kết thúc như là đối số duy nhất của nó. Bất kỳ mã nào được thực thi trong lần đóng này sẽ không gửi các sự kiện mô hình. Ví dụ: ví dụ sau sẽ tìm nạp và xóa một App\Models\User
cá thể mà không gửi bất kỳ sự kiện mô hình nào. Bất kỳ giá trị nào được trả về bởi quá trình đóng sẽ được trả về theo withoutEvents
phương thức:
use App\Models\User;
$user = User::withoutEvents(function () use () {
User::findOrFail(1)->delete();
return User::find(2);
});
Lưu một mô hình duy nhất không có sự kiện
Đôi khi bạn có thể muốn "lưu" một mô hình nhất định mà không cần cử đi bất kỳ sự kiện nào. Bạn có thể thực hiện điều này bằng cách sử dụng saveQuietly
phương pháp:
$user = User::findOrFail(1);
$user->name = 'Victoria Faith';
$user->saveQuietly();