[Bài đọc] Insert và Update model

3. Làm việc với Cơ sở dữ liệu

Insert

Để thêm một bản ghi mới vào cơ sở dữ liệu, đơn giản hãy tạo một model instance mới, thiết lập các thuộc tính vào model, sau đó gọi phương thức save: 

<?php
namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller
{
    /**
     * Create a new flight instance.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...

 
        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();
    }
}

Ở ví dụ này, chúng ta có thể gán tham số name từ HTTP request vào thuộc tính name của model App\Flight. Khi gọi phương thức save, một bản ghi sẽ được thêm vào cơ sở dữ liệu. Timestamps created_at và updated_at sẽ tự động được tạo khi phương thức save được gọi, và bạn không cần thay đổi thủ công giá trị này.

Updates

Phương thức save cũng được dùng để cập nhật model đã tồn tại trong cơ sở dữ liệu. Để cập nhật model, bạn cần lấy nó ra, thiết đặt các thuộc tính bạn muốn, cuối cùng gọi phương thức save. Một lần nữa, timestamp updated_at sẽ tự động được cập nhật, và bạn cũng không cần thay đổi thủ công giá trị này. 

$flight = App\Flight::find(1);

$flight->name = 'New Flight Name';

$flight->save();

Mass Updates

Cập nhật cũng có thể được thực hiện cho nhiều model mà thỏa mã một điều kiện truy vấn. Ở ví dụ này, tất cả flight mà được active và destination ở San Diego sẽ được đánh dấu là delayed:

App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]); 

Phương thức update nhận một mảng các cặp cột và giá trị tương ứng với các cột được cập nhật

Lưu ý: Khi thực hiện một mass update bằng Eloquent, sự kiện saved và updated sẽ không được phát sinh khi model được cập nhật. Vì các model chưa bao giờ được lấy khi sử dụng mass update.

Mass Assignment

Bạn cũng có thể sử dụng phương thức create để thêm vào một model mới. Một Model instance được thêm vào sẽ được trả lại. Tuy nhiên, để làm được điều này, bạn cần phải chỉ định thuộc tính fillable hoặc guarded từng model, để Eloquent model được bảo vệ trước mass-assignment.

Lỗi bảo mật mass-assignment xảy ra khi một user truyền vào một tham số HTTP không mong muốn trong request, tham số này có thể làm thay đổi một cột trong cơ sở dữ liệu mà bạn không ngờ tới. Ví dụ, một user xấu có thể gửi một tham số is_admin qua HTTP request và khi giá trị này được truyền vào phương thức create của model, sẽ cho phép user thay đổi để biến thành một admin.

Vì thế, để bắt đầu, bạn cần khai báo thuộc tính mà bạn muốn cho phép mass-assignment. Bạn có thể thiết lập qua thuộc tính $fillable. Ví dụ, hãy làm cho thuộc tính name của model Flight có thể sử dụng qua mass assignable:

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

Sau đó sử dụng phương thức create để thêm một bản ghi mới vào cơ sở dữ liệu. Phương thức này trả về một model instance đã thêm:

$flight = App\Flight::create(['name' => 'Flight 10']);

Nếu bạn đã có một model instance, bạn có thể sử dụng phương thức fill để gắn nó với một mảng các thuộc tính:

$flight->fill(['name' => 'Flight 22']);

Thuộc tính Guarding

Trong khi $fillable dùng để lưu danh sách các thuộc tính được phép mass assignable, ngược lại bạn có thể sử dụng $guarded. Thuộc tính $guarded để lưu các thuộc tính mà không được mass assignable. Vì thế các thuộc tính khác không lưu trong $guarded sẽ được mass assignable. Vì vậy, $guarded như một black list. Tất nhiên, bạn nên sử dụng một trong hai $fillable hoặc $guarded, chứ không được dùng cả hai. Trong ví dụ dưới, tất cả các thuộc tính sẽ được mass assignable ngoại trừ price: 

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['price'];
}

Nếu bạn muốn tất cả các thuộc tính được mass assignable, bạn định nghĩa thuộc tính $guarded là một mảng rỗng:

/**
 * The attributes that aren't mass assignable.
 *
 * @var array
 */
protected $guarded = [];

Các phương thức tạo khác 

firstOrCreate/ firstOrNew

Có hai phương thức khác bạn có thể sử dụng để tạo model bằng cách mass assigning các thuộc tính: firstOrCreate và firstOrNew. Phương thức firstOrCreate sẽ tìm kiếm trong cơ sở dữ liệu cặp cột/giá trị truyền vào. Nếu model không được tìm thấy trong cơ sở dữ liệu, một một bản ghi sẽ được thêm vào với các thuộc tính được truyền vào.

Phương thức firstOrNew giống như firstOrCreate sẽ tìm bản ghi trong cơ sở dữ liệu khớp với các thuộc tính truyền vào. Tuy nhiên, nếu model không được tìm thấy, một model instance mới sẽ được trả về. Chú ý là model được trả về bởi firstOrNew không vẫn chưa được lưu vào cơ sở dữ liệu. Bạn cần gọi phương thức save để lưu nó lại:

// Retrieve flight by name, or create it if it doesn't exist...

$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);


// Retrieve flight by name, or create it with the name and delayed attributes...

$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'], ['delayed' => 1]
);


// Retrieve by name, or instantiate...

$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);


// Retrieve by name, or instantiate with the name and delayed attributes...

$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

updateOrCreate

Khi bạn muốn cập nhật một model đã tồn tại hoặc tạo một model mới sử dụng phương thức updateOrCreate. Giống như phương thức firstOrCreate, phương thức updateOrCreate tự động cập nhật dữ liệu, vì vậy không cần gọi phương thức save:

// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.

$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

Leave a Reply

Your email address will not be published. Required fields are marked *