12/08/2018, 14:40

Tìm hiểu Laravel từ số 0 (P4)

Ở phần 3 chúng ta đã đi đến phần Migration, và tạo Model. Trong phần 4 này tôi sẽ tiếp tục với các phần sau : Eloquent Mass Assignment Mutators Tiếp tục với việc sử dụng Eloquent để thao tác với model, chúng ta sẽ đi sâu thêm một chút và những chức năng mà nó cung cấp. Ta vẫn dùng ...

Ở phần 3 chúng ta đã đi đến phần Migration, và tạo Model. Trong phần 4 này tôi sẽ tiếp tục với các phần sau :

  • Eloquent
  • Mass Assignment
  • Mutators

Tiếp tục với việc sử dụng Eloquent để thao tác với model, chúng ta sẽ đi sâu thêm một chút và những chức năng mà nó cung cấp. Ta vẫn dùng tinker để giao tiếp :

php artisan tinker

Đầu tiên ta sẽ tạo thêm một bài article đơn giản nữa.

// Tạo mới một bài
>>> $article = new AppArticle;
>>> $article->title = 'Second title here';
>>> $article->body = 'Anybody care ?';
>>> $article->published_at = CarbonCarbon::now();
>>> $article->save();

// Xem tất cả các bài article đang có :
>>> AppArticle::all()->toArray();
=> [
       [
           "id"           => "1",
           "title"        => "I am a title of blog",
           "body"         => "And i am a content of above title",
           "created_at"   => "2017-01-03 07:36:58",
           "updated_at"   => "2017-01-03 09:13:00",
           "published_at" => "2017-01-03 10:03:42"
       ],
       [
           "id"           => "2",
           "title"        => "Second title here",
           "body"         => "Anybody care ?",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 09:35:46",
           "published_at" => "2017-02-03 09:35:46"
       ]
   ]

Nhưng nếu lấy theo all() ra tất cả thì sẽ rất nhiều, nên nếu chỉ muốn lấy ra một bài nào đó mà bạn đã biết id của nó thì có thể dùng find() và truyền vào cho nó id của bài mà bạn cần tìm như sau :

>>> AppArticle::find(2)->toArray();
=> [
           "id"           => "2",
           "title"        => "Second title here",
           "body"         => "Anybody care ?",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 09:35:46",
           "published_at" => "2017-02-03 09:35:46"
   ]

Bạn cũng có thể hoàn toàn chỉ định điều kiện tìm kiếm để lọc những bài mà mình mong muốn bằng cách sử dụng where() :

>>> AppArticle::where('id', '>', 1)->get()->toArray();
=> [
       [
           "id"           => "2",
           "title"        => "Second title here",
           "body"         => "Anybody care ?",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 09:35:46",
           "published_at" => "2017-02-03 09:35:46"
       ]
   ] 

Tiếp theo nếu bạn muốn biết có bao nhiêu bài đang có hoặc bao nhiêu bài thỏa mãn điều kiện chỉ định thì có thể dùng count() :

// Đếm tất cả bài có trong DB
>>> AppArticle::count();
=> 2
// Kết hợp với where() để đếm số bài thỏa mãn điều kiện
>>> AppArticle::where('id', '>', 1)->count();
=> 1

Kế đến, bạn muốn cập nhật nội dung của một bài nào đó thì sẽ cần lấy ra bài đó trước rồi thiết lập các giá trị cần thay đổi và cuối cùng là gọi save() để áp dụng những thay đổi đó :

// Lấy ra bài cần update
>>> $article = AppArticle::find(2);
=>  {
           "id"           => "2",
           "title"        => "Second title here",
           "body"         => "Anybody care ?",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 09:35:46",
           "published_at" => "2017-02-03 09:35:46"
   }
 // Thay đổi những nội dung mong muốn 
>>> $article->body = 'I changed this body';
=> "I changed this body"
// Gọi hàm save() để lưu những thay đổi
>>> $article->save();
=> true
// Kiểm tra lại kết quả bạn sẽ thấy những nội dung đã thay đổi và giá trị updated_at cũng tự động được cập nhật mà không cần phải làm gì
>>> AppArticle::find(2)->toArray();
=> [
           "id"           => "2",
           "title"        => "Second title here",
           "body"         => "I changed this body",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 09:55:23",
           "published_at" => "2017-02-03 09:35:46"
   ]

Ngoài ra, bạn cũng có thể trực tiếp dùng hàm update() để thực hiện những sự thay đổi cho model. Nó nhận vào một mảng các cặp key - là tên các cột và value - là giá trị mới sẽ thay thế cho các giá trị cũ. Bạn có thể kết hợp với where() để chỉ thay đổi những bài nhất định thỏa điều kiện nào đó :

>>> AppArticle::where('id', '=', 2)->update(['title' => 'I changed this too']);
>>> AppArticle::find(2)->toArray();
=> [
           "id"           => "2",
           "title"        => "I changed this too",
           "body"         => "I changed this body",
           "created_at"   => "2017-02-03 09:35:46",
           "updated_at"   => "2017-02-03 10:05:18",
           "published_at" => "2017-02-03 09:35:46"
   ]

Đối với xóa cũng tương tự như khi cập nhật, bạn sẽ cần lấy ra bài cần xóa trước sau đó gọi đến delete() để loại bỏ bài viết khỏi DB :

>>> $article = AppArticle::find(2);
>>> $article->delete();
>>> AppArticle::all()->toArray();
=> [
       [
           "id"           => "1",
           "title"        => "I am a title of blog",
           "body"         => "And i am a content of above title",
           "created_at"   => "2017-01-03 07:36:58",
           "updated_at"   => "2017-01-03 09:13:00",
           "published_at" => "2017-01-03 10:03:42"
       ]
   ]

Và đương nhiên bạn cũng có thể dùng where() để lọc ra những cái cần loại bỏ rồi mới gọi hàm delete() :

>>>$deletedRows = AppArticle::where('id', '=', 2)->delete();

Riêng với xóa bạn có thể dùng thêm hàm destroy() mà đã biết một hoặc nhiều key chính của các bài muốn xóa. Nó nhận vào 1 giá trị đơn hoặc 1 loạt giá trị cách nhau bằng dấu phẩy hoặc là một mảng :

>>>AppArticle::destroy(2);
>>>AppArticle::destroy([1, 2]);
>>>AppArticle::destroy(1, 2);

Trên đây là những chức năng cơ bản nhất mà Eloquent có thể làm được, và nếu bạn muốn tìm hiểu sâu hơn nữa thì có thể ghé đây để tham khảo.

Đây là chức năng của Eloquent cho phép chúng ta có thể tạo ra một model mới chỉ trong một dòng khai báo mà không cần phải chỉ định từng giá trị cho từng cột. Thường thì những giá trị đó sẽ nhận về từ request từ phía user. Giả sử bạn tạo một bài article thứ 3 với nội dung như sau :

// Đây chính là Mass Assignment
>>> AppArticle::create(['title' => 'Third article', 'body' => 'Mass Assignment body here', 'published_at' => CarbonCarbon::now()]);
// Bạn sẽ nhận được ngoại lệ ném ra dạng như này
IlluminateDatabaseEloquentMassAssignmentException with message 'title'

Với Mass Assignment bạn cần chỉ định những cột nào cho phép được sử dụng trong nó bằng cách khai báo trước chúng vào trong biến $$illable, điều này đảm bảo cho việc an toàn cho DB của bạn. Vì bạn sẽ không thể biết được user sẽ đưa vào những giá trị như nào, và chúng là có hại hay là không :

<?php namespace App;
// app/Article.php
 
use IlluminateDatabaseEloquentModel;
 
class Article extends Model {
     
    protected $fillable = ['title', 'body', 'published_at'];
     // như trên là bạn đã cho phép 3 trường trên sẽ được khai báo trong Mass Assignment, những trường khác mà
     // có sử dụng thì sẽ bị báo lỗi ngoại lệ như phía trên
}

Đó là cách dùng fillable nhưng ngược lại với nó bạn cũng có thể khai báo những trường nào ko được phép tham gia vào Mass Assignment vào biến guarded. Đương nhiên tùy vào hoàn cảnh bạn có thể sử dụng một trong hai cách đó, ví dụ như bạn có rất nhiều trường cho phép nhưng chỉ có số ít trường không cho phép thì có lẽ $$uarded sẽ hợp lý hơn :

<?php namespace App;
// app/Article.php
 
use IlluminateDatabaseEloquentModel;
 
class Article extends Model {
     
    protected $guarded = ['published_at'];
    // như này là bạn đã không cho phép ngày publish của bài article được quyết định bởi user khi nó được đăng lên
}

Sau khi xong là bạn đã có thể dùng Mass Assignment để tạo mới model mà không gặp phải lỗi ngoại lệ nữa. Nhưng một lưu ý là khi thay đổi hay khai báo mới một trong 2 cách trên thì cần phải khởi động lại tinker thì nó mới có hiệu lực :

$ php artisan tinker

Trong Eloquent cung cấp một chức năng hữu ích mà có thể thay đổi được nội dung khi get hay set thuộc tính của model. Và phương thức thay đổi nội dung thuộc tính này là Mutators.

Get Mutators

Tên của phương thưc sẽ là dạng getXAttribute(), với X là tên của thuộc tính. Và cần phải chú ý là tên thuộc tính - X phải được ghi dưới dạng camels case dù tên trong bảng là dạng snake case. Ví dụ như phương thức lấy ra thông tin tiêu đề :

class Article extends Model
{
    ...
 
    public function getTitleAttribute($value)
    {
        // đổi thành chữ hoa
        return mb_strtoupper($value);
    }
 
}

Set Muators

Tên phương thức sẽ có dạng setYAttribute() , với Y là tên thuộc tính.

class Article extends Model
{
    ...
    public function setTitleAttribute($value)
    {
        // thay đổi thành chữ thường
        $this->attributes['title'] = mb_strtolower($value);
    }
}

Date Mutators

Trong Elocuent thì mặc định Date Mutators được sử dụng để biến đổi thuộc tính created_at, updated_at thành Carbon instance ( đây là lớp mở rộng DateTime của native PHP). Và để cho Eloquent biết thuộc tính nào sẽ sử dụng Date Mutators thì sẽ cần đưa tên của nó vào trong mảng $$ates trong Model của bạn.

class Article extends Model
{
    ...
    // Ví dụ ta thiết lập dùng date mutators cho thuộc tính published_at
    protected $dates = ['published_at'];
    ...
}

Và khi mà một thuộc tính được coi như là date thì bạn có thể set giá trị của nó là một UNIX timestamp, một chuỗi date (Y-m-d), hay chuỗi date-time, và tất nhiên có thể là một instance lớp DateTime hoặc Carbon. Và giá trị của date sẽ được tự động lưu đúng trong DB của bạn :

>>>$article = AppArticle::find(1);
>>>$article->published_at = Carbon::now();
>>>$article->save();

Rồi khi lấy ra thuộc tính mà chúng có được list trong mảng $$ates thì chúng sẽ được tự động được cast thành Carbon instances, và cho phép bạn có thể dùng được bất cứ hàm nào của lớp Carbon đối với thuộc tính của bạn :

$article = AppArticle::find(1);
return $article->published_at->getTimestamp();

Mặc định thì timestamps được format dạng 'Y-m-d H:i:s'. Nếu mà bạn cần custom nó thì có thể sử dụng $$ateFormat trong model của bạn. Nó quyết định thuộc tính date sẽ được lưu trong DB như thế nào :

<?php
namespace App;

use IlluminateDatabaseEloquentModel;

class Article extends Model
{
    ...
    // dạng UNIX timestamp
    protected $dateFormat = 'U';
    /*
     * hoặc dạng khác mà bạn muốn
     * protected $dateFormat = 'd.m.Y H:i:s';
    */
}

Nguồn : Laravel10.wordpress.com

0