Eloquent ORM
<a name="introduction"></a> ## ทำความรู้จักก่อน
Eloquent ORM คือการที่เราจำลองตารางเป็นคลาสแล้ว เรียกใช้งานเป็นชื่อของตาราง นั้นเลยทำให้เข้าใจการพัฒนารวดเร็วขึ้น เข้าใจง่ายขึ้น ที่เรียกว่า Eloquent เพราะตัวมันมีความเรียบง่าย สามารถเข้าใจว่าจะใช้ได้ยังไงทันที ถ้าเคยเขียน php แบบ oop มาก่อน
<a name="basic-usage"></a> ## การใช้งานเบื้องต้น
เริ่มต้นด้วยการสร้าง moedel ไว้ที่โฟลเดอร์ app/models
ตัวอย่างการสร้าง model
1 class User extends Eloquent {}
ถ้าคลาสนี้จะไม่ใช้ตารางตามชื่อ model เราก็สามารถใช้ตัวแปร table ในการกำหนดชื่อตารางที่เราจะใช้ เหมือนในตัวอย่าง
1 class User extends Eloquent {
2
3 protected $table = 'my_users';
4
5 }
หมายเหตุ: Eloquent จะถือว่าคอลัมน์
idเป็นคีย์หลักเสมอ เราสามารถใช้ตัวแปรprimaryKeyเพื่อกำหนดคีย์หลักได้เอง และเช่นเดียวกัน เราสามารถใช้ตัวแปรconnectionเพื่อกำหนดฐานข้อมูลที่เราจะใช้ใน model นี้
ถ้าในตารางของเรามีคอลัมน์ที่ชื่อ updated_at กับ created_at จะถูกใช้ในการเก็บเวลาที่ข้อมูลในแถวนี้ถูกเพิ่มหรือแก้ไข. ถ้าเราไม่ต้องการเพียงแค่ตั้งค่าตัวแปร $timestamps ให้เป็น false
การคิวรี่โดยใช้ eoloquent
ค้นหาข้อมูลทั้งหมดจากตาราง user
1 $users = User::all(); //
ค้นหาตามเงื่อนไข
ค้นหาโดยค่า id เท่ากับ 1
1 $user = User::find(1); //
แสดงค่าในคอลัมน์ออกมา
1 var_dump($user->name); //
Note: ทุกคำสั่งที่ใช้ใน query builder สามารถใช้กับ eloquent ได้เช่นกัน
การคิวรี่แล้วส่งต่อ
บางเวลาเมื่อค้นหาเเล้วไม่เจอเราต้องการให้เกิดหน้าแสดงข้อผิดพลาดขึ้นมา สามารถใช้ฟังก์ชัน findOrFail เหมือนในตัวอย่างเลยครับ ถ้าค้นไม่เจอเราจะส่งไปหน้า 404 ทันที
1 $model = User::findOrFail(1);
2
3 $model = User::where('votes', '>', 100)->firstOrFail();
อยากจะสร้างการแสดงข้อผิดพลาดโดยที่เรากำหนดเองก็สามารถทำตามตัวอย่างเลยครับ สมมุติเราจะสร้างฟังก์ชัน ModelNotFoundExceptionเราก็เรียกตัวคลาสหลักเข้ามาก่อน
1 use Illuminate\Database\Eloquent\ModelNotFoundException;
2
3 App::error(function(ModelNotFoundException $e)
4 {
5 return Response::make('Not Found', 404);
6 });
ตัวอย่างการคิวรี่แบบหลายเงื่อนไข
1 $users = User::where('votes', '>', 100)->take(10)->get();
2
3 foreach ($users as $user)
4 {
5 var_dump($user->name);
6 }
** การคำนวนแบบต่างๆ **
1 $count = User::where('votes', '>', 100)->count();
ถ้าเราอยากเขียนคำสั่งคิวรี่ ขึ้นมาใช้เองก็ต้องใช้ฟังก์ชัน whereRaw
1 $users = User::whereRaw('age > ? and votes = 100', array(25))->get();
<a name="mass-assignment"></a> ## การส่งค่าอาเรย์ลงฐานข้อมูล
เราสามารถส่ง ค่าจำนวนมากอย่างเช่น อาเรย์ ลงฐานข้อมูลได้ง่ายๆ แต่ต้องใช้ตัวแปร<br />
fillable เพื่อกำหนดว่าคอลัมน์ไหนที่สามารถใส่อาเรย์ได้ <br />
guarded เพื่อกำหนดว่าคอลัมน์ไหนใส่อาเรย์ลงไปไม่ได้
ตัวอย่างการกำหนดค่า fillable
1 class User extends Eloquent {
2
3 protected $fillable = array('first_name', 'last_name', 'email');
4
5 }
ตัวอย่างการตั้งค่าตัวแปร guard
1 class User extends Eloquent {
2
3 protected $guarded = array('id', 'password');
4
5 }
ต้วอย่างคอลัมน์ id and password เราจะไม่อนุญาติให้ทำการใส่ค่าที่มาในรูปแบบอาเรย์ลงไป
การป้องกันไม่ให้ทำการเพิ่มข้อมูลเป็นอาเรย์
1 protected $guarded = array('*');
<br /><br /><br /><br /><br /><br /> #### การเพิ่มข้อมูลพร้อมตรวจสอบ
สร้าง user ใหม่
1 $user = User::create(array('name' => 'John'));
รับค่ามาใส่ตามคอลัมน์ จะอัพเดทถ้ามีค่าอยู่แล้ว ถ้าไม่มีจะสร้างใหม่
1 $user = User::firstOrCreate(array('name' => 'John'));
ตรวจสอบว่ามีค่าไหม.
1 $user = User::firstOrNew(array('name' => 'John'));
<a name="insert-update-delete"></a> ## เพิ่ม, ลบ, แก้ไข
ตัวอย่างการแก้ไขข้อมูลแบบไม่ใช้ namespace
1 $user = new User;
2
3 $user->name = 'John';
4
5 $user->save();
หมายเหตุ: โดยเริ่มต้น laravel จะทำการเพิ่มค่าคีย์หลักให้อัตโนมัติ ถ้าเราไม่ต้องการก็ตั้งค่าตัวแปร
incrementingใน model ให้เป็นfalse.
เราสามารถใช้คำสั่ง create เพื่อสร้างข้อมูลใหม่ได้ แต่ก่อนหน้านั้นต้องกำหนดตัวแปร fillable หรือ guarded ไม่งั้นเพิ่มไม่ได้ติด error
การสร้างข้อมูลใหม่
1 $user = User::create(array('name' => 'John'));
<br /><br /><br /><br /> ตัวอย่างการแก้ไขข้อมูล
1 $user = User::find(1);
2
3 $user->email = 'john@foo.com';
4
5 $user->save();
บางเวลาเราต้องบันทึกค่าในตารางที่อ้างอิงกัน เราจะใช้คำสั่ง push
บันทึกค่าพร้อมกับบันทึกลงตารางที่มีการเชื่อมกันอยู่
1 $user->push();
ตัวอย่างการลบข้อมูล
1 $user = User::find(1);
2
3 $user->delete();
ลบโดยกำหนด id เป็นเงื่อนไข
1 User::destroy(1);
2
3 User::destroy(1, 2, 3);
ตัวอย่างการลบแบบมีเงื่อนไข:
1 $affectedRows = User::where('votes', '>', 100)->delete();
ถ้าเราต้องการแก้ไขเฉพาะคอลัมน์ที่ใช้บันทึกเวลา เราจะใช้คำสั่ง touch
ตัวอย่างการใช้งาน
1 $user->touch();
<br /><br />
<a name="soft-deleting"></a>
## การกำหนดว่าข้อมูลนี้ถูกลบเเล้ว
เราสร้างตัวแปร $softdelete เพื่อบอก model ว่าไม่ต้องลบจริง เหมือนกับเราเอาไปเก็บไว้ในถังขยะก่อน ยังไม่ได้เอาไปเผาทิ้งจริงๆ
1 class User extends Eloquent {
2
3 protected $softDelete = true;
4
5 }
แล้วก็เพิ่มคอลัมน์ deleted_at ลงในตาราง เพื่อกำหนดว่าข้อมูลแถวนี้ถูกลบแล้วหรือยัง
เมื่อเราเรียกคำสั่ง delete กับ model นี้คอลัมน์ deleted_at จะถูกเพิ่มค่าให้เป็นวันเวลาที่เราลบ เมื่อเราค้นหาข้อมูลโดยใช้ model นี้ข้อมูลแถวที่เราทำการ
ลบจะไม่ถูกดึงขึ้นมา
ตัวอย่างการค้นหา โดยรวมแถวที่ถูกตั้งค่าว่าลบแล้ว
1 $users = User::withTrashed()->where('account_id', 1)->get();
ตัวอย่างการค้นหา โดยค้นหาเฉพาะแถวที่ถูกตั้งค่าว่าลบแล้ว
1 $users = User::onlyTrashed()->where('account_id', 1)->get();
ถ้าต้องการยกเลิกการลบ ใช้คำสั่ง restore ได้เลยครับ
1 $user->restore();
หรือจะเรียกคืนเฉพาะแถวก็ตามตัวอย่างนี้เลย
1 User::withTrashed()->where('account_id', 1)->restore();
ฟังก์ชัน restore สามารถใช้กับความสัมพันธ์ได้ด้วย
1 $user->posts()->restore();
ถ้าต้องการลบข้อมูลจริงๆ ก็ใช้คำสั่ง forceDelete
1 $user->forceDelete();
คำสัง forceDelete ก็สามารถใช้กับความสัมพันธ์ก็ได้
1 $user->posts()->forceDelete();
ฟังก์ชัน trashed ใช้ในการตรวจว่าโมเดลนี้มีการตั้งค่า softdelete ไว้ไหม
1 if ($user->trashed())
2 {
3 //
4 }
<a name="timestamps"></a> ## Timestamps การบันทึกเวลา
โดยค่าเริ่มต้น laravel ใช้คอลัมน์ created_at และ updated_at ในตารางของเราโดยอัตโนมัติ.
ตัวอย่างการยกเลิกการเก็บเวลาในการจัดการข้อมูล
1 class User extends Eloquent {
2
3 protected $table = 'users';
4
5 public $timestamps = false;
6
7 }
ฟังก์ชัน freshTimestampใช้ในการกำหนดรูปแบบวันเวลาที่เราจะเก็บ
ตัวอย่างการใช้งาน
1 class User extends Eloquent {
2
3 public function freshTimestamp()
4 {
5 return time();
6 }
7
8 }
<br /><br /> <a name="query-scopes"></a> ## Query Scopes
เราใช้คำนำหน้าฟังก์ชันว่า scope เพื่อทำการสร้างฟังก์ชันที่ใช้คิวรี่แบบเฉพาะของเราเอง:
ตัวอย่างการใช้งาน scope
1 class User extends Eloquent {
2
3 public function scopePopular($query)
4 {
5 return $query->where('votes', '>', 100);
6 }
7
8 }
การใช้งานคิวรี่ที่มาจาการใช้คำสั่ง scope
1 $users = User::popular()->orderBy('created_at')->get();
<a name="relationships"></a> ## ความสัมพันธ์
การจัดการความสัมพันธ์ตารางใน laravel มี 4 รูปแบบ
- 1 ต่อ 1
- 1 ต่อ กลุ่ม
- กลุ่ม ต่อ กลุ่ม
- ความสัมพันธ์แบบซับซ้อน
<br /><br /><br /><br /><br /><br /><br /> <a name="one-to-one"></a> ### 1 ต่อ 1
ตัวอย่างความสัมพันธ์แบบ 1 ต่อ 1 ผู้ใช้งานมีโทรศัพท์ได้เเค่เครื่องเดียว
ตัวอย่างความสัมพันธ์แบบ 1 ต่อ 1
1 class User extends Eloquent {
2
3 public function phone()
4 {
5 return $this->hasOne('Phone');
6 }
7
8 }
เราใช้ฟังก์ชันเป็นตัวกำหนดตารางที่เราจะเชื่อมด้วย ตัวอย่างข้างล่างการค้นหาโทรศัพท์ของผู้ใช้งานที่มี id เท่ากับ 1
1 $phone = User::find(1)->phone;
ถ้าเขียนเป็น php ธรรมดาก็จะได้เเบบนี้ครับ
1 select * from users where id = 1
2
3 select * from phones where user_id = 1
โดยค่าเริ่มต้นเเล้ว Eloquent จะใช้คอลัมน์ user_id ในตาราง Phone เป็น คีย์เชื่อม ถ้าเราไม่เอา จะเอาชื่อที่เราตั้งเองก็ใช้ตัวแปร hasOne เป็นตัวแก้ดังตัวอย่าง
1 return $this->hasOne('Phone', 'custom_key');
ในการเชื่อมโมเดลสิ่งที่สำคัญคือการตั้งค่าความสัมพันธ์ให้ตรงกันใน Phone model เราก็จะใช้ฟังก์ชัน belongsTo ในการเชื่อมกลับไปยัง User
ตัวอย่างการเชื่อมกลับไปยัง User Model
1 class Phone extends Eloquent {
2
3 public function user()
4 {
5 return $this->belongsTo('User');
6 }
7
8 }
เหมือนกับข้างบนครับ เราไม่เอา user_id เป็นคีย์เชื่อมก็ต้องกำหนดด้วย ตามตัวอย่าง
1 class Phone extends Eloquent {
2
3 public function user()
4 {
5 return $this->belongsTo('User', 'custom_key');
6 }
7
8 }
<a name="one-to-many"></a> ### 1 ต่อ กลุ่ม
ความสัมพันธ์แบบ 1 ต่อ กลุ่ม มีตัวอย่างคือ 1 โพสมีได้หลาย ความคิดเห็น ตัวอย่างการใช้ hasMany
1 class Post extends Eloquent {
2
3 public function comments()
4 {
5 return $this->hasMany('Comment');
6 }
7
8 }
ตัวอย่างการค้นหาตารางที่เชื่อมกันอยู่
1 $comments = Post::find(1)->comments;
ตัวอย่างการค้นหาแบบหลายเงื่อนไขครับ ดังตัวอย่าง เราจะค้นหาความคิดเห็นที่มี title ชื่อ foo โดยเอาค่าเเรกที่เจอก่อน
1 $comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();
อีกครั้ง อย่าลืมเชื่อมกลับไปยังตารางที่เชื่อมมานะครับ
<br /><br /><br /><br /> ดูตัวอย่างอีกครั้ง
1 class Comment extends Eloquent {
2
3 public function post()
4 {
5 return $this->belongsTo('Post');
6 }
7
8 }
<a name="many-to-many"></a> ### กลุ่ม ต่อ กลุ่ม
กลุ่มต่อกลุ่ม จะเป็นความสัมพันธ์ที่ยุ่งยากพอสมควรเลยครับ เรามีตัวอย่างคือ ผู้ใช้งานมีสิทธิการใช้งานได้หลายสิทธิ์ ทั้งเรียกดู,ลบ,แก้ไข,เพิ่ม แล้วแต่ละสิทธิ์ก็ถูกใช้ได้ในหลายผู้ใช้งาน เราต้องมี 3 ตาราง users, roles, กับ role_user. ตาราง role_userจะเก็บ user_id กับ role_id เพื่อบอกว่า ผู้ใช้งานคนนี้มีสิทธิทำอะไรได้บ้าง
laravel ใช้ฟังก์ชัน belongsToMany ในการเชื่อมความสัมพันธ์:
1 class User extends Eloquent {
2
3 public function roles()
4 {
5 return $this->belongsToMany('Role');
6 }
7
8 }
ตอนนี้เราสามารถตรวจได้เเล้วว่าผู้ใช้งานหมายเลข 1 มีสิทธิทำอะไรได้บ้าง
1 $roles = User::find(1)->roles;
ถ้าเราต้องการใช้ชื่อตาราง ตามใจเราก็สามารถทำได้โดยการ ส่งพารามิเตอร์ไป ดังตัวอย่างครับ
1 return $this->belongsToMany('Role', 'userroles');
หรือจะเปลี่ยนไปจนถึงชื่อคอลัมน์เลยก็ได้ แต่ต้องส่งชื่อ คอลัมน์ที่เราตั้งเองไปบอก model ด้วย
1 return $this->belongsToMany('Role', 'userroles', 'user_id', 'foo_id');
อย่าลืมเชื่อมความสัมพันธ์กลับมาด้วยนะครับ
1 class Role extends Eloquent {
2
3 public function users()
4 {
5 return $this->belongsToMany('User');
6 }
7
8 }
<br /><br /> <a name="polymorphic-relations"></a> ### ความสัมพันธ์ที่ยุ่งยากมากขึ้น เพื่อช่วยให้เข้าใจได้ง่ายขึ้นจะมีตัวอย่างมาให้ดูกันครับ ตัวอย่างโครงสร้างตาราง
1 staff
2 id - integer
3 name - string
4
5 orders
6 id - integer
7 price - integer
8
9 photos
10 id - integer
11 path - string
12 imageable_id - integer
13 imageable_type - string
มันพิเศษตรงที่คอลัมน์ imageable_id กับ imageable_type ของตาราง photos ที่เราจะใช้เก็บคีย์ที่ใช้เชื่อมตาราง photo เข้ากับตาราง staff หรือ order ใช้เก็บคีย์เชื่อมร่วมกันได้ โดยใช้คอลัมน์ เมื่อเรากำหนดคีย์เชื่อมและชื่อของตารางที่เชื่อมไป ORM จะทำการตรวจสอบโดยใช้คอลัมน์ที่ imageable_type ในการหาว่าคีย์นี้เป็นของตารางไหน โดยเราต้องตั้งชื่อฟังก์ชันว่า imageable เราต้องประกาศ model แบบนี้ครับ
<br /><br /><br /><br /><br /><br />
1 class Photo extends Eloquent {
2
3 public function imageable()
4 {
5 return $this->morphTo();
6 }
7
8 }
ฟ class Staff extends Eloquent {
1 public function photos()
2 {
3 return $this->morphMany('Photo', 'imageable');
4 }
5
6 }
7
8 class Order extends Eloquent {
9
10 public function photos()
11 {
12 return $this->morphMany('Photo', 'imageable');
13 }
14
15 }
ตอนนี้เราสามารถใช้ id ของ staff หรือ order มาค้นหารูปภาพได้ <br /><br /> ตัวอย่าง
1 $staff = Staff::find(1);
2
3 foreach ($staff->photos as $photo)
4 {
5 //
6 }
ความพิเศษจริง ๆอยู่ที่เมื่อเราใช้ Photo model ในการค้นครับ
ตัวอย่าง
1 $photo = Photo::find(1);
2
3 $imageable = $photo->imageable;
ความสัมพันธ์ที่ชื่อ imageable บน model Photo จะส่งข้อมูลของทั้ง Staff และ Order หรือตารางใดตารางหนึ่ง ขึ้นอยู่กับค่าที่เราใช้ค้นหาจะไปตรงกับ model ไหน
<a name="many-to-many-polymorphic-relations"></a> ### การใช้ความสัมพันธ์แบบซับซ้อนในแบบ many to many
โมเดล Post และ โมเดล Video ต่างมีความสัมพันธ์แบบ many to many กับโมเดล Tag มาดูโครงสร้างตารางเพื่อความเข้าใจง่ายกันดีกว่าครับ
1 posts
2 id - integer
3 name - string
4
5 videos
6 id - integer
7 name - string
8
9 tags
10 id - integer
11 name - string
12
13 taggables
14 tag_id - integer
15 taggable_id - integer
16 taggable_type - string
ต่อไปเรามาตั้งค่าความสัมพันธ์ให้โมเดลกันครับ โมเดล Post และ Video จะใช้ความสัมพันธ์แบบ morphToMany กับโมเดล tags
1 class Post extends Eloquent {
2
3 public function tags()
4 {
5 return $this->morphToMany('Tag', 'taggable');
6 }
7
8 }
ในโมเดล Tag เราจะเชื่อมกับโมเดลทั้งสอง โดยใช้ morphByMany ผ่านทางตาราง taggable ความเรียบง่ายของ laravel ทำให้ความสัมพันธ์ ที่แสนจะน่าปวดหัวง่ายขึ้น
1 class Tag extends Eloquent {
2
3 public function posts()
4 {
5 return $this->morphedByMany('Post', 'taggable');
6 }
7
8 public function videos()
9 {
10 return $this->morphedByMany('Video', 'taggable');
11 }
12
13 }
ปล. การเรียกใช้ก็เหมือนกับ morphMany ด้านบนเลยครับ
<a name="querying-relations"></a> ## การคิวรี่โดยใช้ความสัมพันธ์เป็นเงื่อนไข
เราสามารถจำกัดผลการค้นหาด้วยฟังก์ชัน has
ค้นหาโดยจำกัดเฉพาะความสัมพันธ์
1 $posts = Post::has('comments')->get();
เลือกข้อมูลของตาราง post โดยเอาเฉพาะที่มี comment
1 $posts = Post::has('comments', '>=', 3)->get();
เลือก post ที่มี comment มากกว่าหรือเท่ากับ 3 <br /><br /><br /><br /><br /><br /><br /><br /> <a name="dynamic-properties"></a> ### การค้นหาแบบยืดหยุ่น
Eloquent ทำให้เราสามารถค้นหาแบบต่อเนื่องโดย พยายามให้เราจำกัดขอบเขตการค้นหาให้ได้ลึกลงที่สุดเพื่อให้ได้เฉพาะข้อมูลที่ต้องการจริงๆ และพลิกแพลงรูปแบบของฟังก์ชันได้มากมาย ดังตัวอย่าง
1 class Phone extends Eloquent {
2
3 public function user()
4 {
5 return $this->belongsTo('User');
6 }
7
8 }
9
10 $phone = Phone::find(1);
แทนที่เราจะทำแบบข้างบน ซึ่งจะทำให้เราได้ค่าที่ไม่ต้องการออกมามาก เราก็เปลี่ยนมาใช้แบบข้างล่าง เราสามารถเข้าถึง อีเมล์ ของผู้ใช้งาน คนแรกได้เลย
1 echo $phone->user()->first()->email;
หรือจะให้สั้นได้อีก ก็ทำตามนี้เลยครับ
1 echo $phone->user->email;
<a name="eager-loading"></a> ## Eager Loading
Eager loading มีเพื่อแก้ปัญหาการคิวรี่แบบ N + 1 ตัวอย่างคือ, ผู้เเต่งหนึ่งคนสามารถแต่งหนังสือได้หลายๆ เล่ม ความสัมพันธ์จะออกมาแบบนี้
1 class Book extends Eloquent {
2
3 public function author()
4 {
5 return $this->belongsTo('Author');
6 }
7
8 }
แล้วการคิวรี้ที่มีปัญหาก็ประมาณนี้
1 foreach (Book::all() as $book)
2 {
3 echo $book->author->name;
4 }
1 คิวรี้ จะทำการดึงค่าหนังสือทั้งหมดจากตาราง, แล้วการคิวรี่ครั้งต่อไปก็จะทำเหมือนกัน. ถ้ามีหนังสือ 25 เล่ม,จะมีการคิวรี่ถึง 26 ครั้ง คือเราใช้ข้อมูลทั้งหมดของตารางหนังสือไปค้นหาผูแต่ง 1 ผู้แต่งก็จะไปดึงหนังสือทั้งหมดของเขาออกมา
1 select * from books
2
3 select * from authors where id = ?
นึกถึงเรามีข้อมูลเริ่มต้น 1000 แถว ปัญหานี้ส่วนใหญ่จะเกิดขึ้นกับความสัมพันธ์แบบ hasMany เพราะเราต้องนำทั้งหมดไปค้นหาต่อแล้วแต่ละแถวจะได้ผลลัพท์ออกมาหลายๆ แถวจำนวนผลการค้นหาที่มหาศาลจะทำให้การคิวรี่ช้ามากแต่ ซึงถ้าข้อมูลตั้งต้นยังมากกว่านี้ลงไปแต่งคิวรี่เองโดยใช้ Fluent Query Builder แต่ถ้ายังจะใช้ Eloquent ก็ยัง
โชคดีที่ laravel มีฟังก์ชัน with ใช้ในการทำให้เร็วขึ้น
1 foreach (Book::with('author')->get() as $book)
2 {
3 echo $book->author->name;
4 }
sql ที่เกิดขึ้นจะมีหน้าตาแบบนี้ครับ เริ่มจากค้นหาหนังสือทั้หมดก่อนแล้ว ค่อยเอา id ที่ได้ไปค้นต่อในตาราง authors เราเปลี่ยนไปใช้ in แทน
1 select * from books
2
3 select * from authors where id in (1, 2, 3, 4, 5, ...)
จะทำให้เว็บของเราโหลดเร็วขึ้นอย่างมากเลยครับ
ตัวอย่าง การใช้ eager loading ในกรณีตารางมีการเชื่อมกับอีกหลายตาราง
1 $books = Book::with('author', 'publisher')->get();
จะใช้การทำ eager load กับคอลัมน์อื่นได้
1 $books = Book::with('author.contacts')->get();
In the example above, the author relationship will be eager loaded, and the author’s contacts relation will also be loaded.
Eager Load Constraints
บางเวลาเราต้องการเฉพาะบางคอลัม์จาการทำ eager loading แล้วใส่เงื่อนไขเข้าไปอีก สามารถกำหนดได้ดัังนี้ครับ:
1 $users = User::with(array('posts' => function($query)
2 {
3 $query->where('title', 'like', '%first%');
4 }))->get();
Lazy Eager Loading
เราสามารถใช้การทำ eager loading ไปยังตารางที่เชื่อมกันได้เหมือนในตัวอย่างครับ เราเข้าไปค้นต่อไปในตาราง publisher ที่เชื่อมกับตาราง author อีก
1 $books = Book::all();
2
3 $books->load('author', 'publisher');
<a name="inserting-related-models"></a> ## การบันทึกข้อมูลแบบมีความสัมพันธ์
สมมุตอเราจะเพิ่มความคิดเห็นลงบทความนี้แล้วเราก็ต้องนำ id ของบทความที่เราโพสความคิดเห็นใส่ไปมาใส่ในความคิดเห็นด้วย
ตัวอย่างการเก็บข้อมูลที่ต้องมีความสัมพันธ์
1 $comment = new Comment(array('message' => 'A new comment.'));
2
3 $post = Post::find(1);
4
5 $comment = $post->comments()->save($comment);
ในตัวอย่างคอลัมน์post_id จะถูกใส่ค่าให้อัติโนมัติ
<br /><br />
### การจัดการฟอเรี้ยนคีย์
เมื่อเราจะทำการแก้ไขข้อมูลที่มีความสัมพันธ์แบบ กลุ่มต่อหนึ่ง เราต้องใช้ฟังก์ชัน associate ในการเพิ่มค่าคีย์เชื่อมไปยังตารางที่มีความสัมพันธ์อยู่ด้วย
1 $account = Account::find(10);
2
3 $user->account()->associate($account);
4
5 $user->save();
การเพิมข้อมูลแบบกลุ่มต่อกลุ่ม (Many To Many)
ตัวอย่างคือเราจะทำการเพิ่มความสามารถให้ผู้เราต้อง laravel มีฟังก์ชัน attach มาให้ใช้เเล้ว
การเพิ่มข้อมูลแบบกลุ่มต่อกลุ่ม
1 $user = User::find(1);
2
3 $user->roles()->attach(1);
ตัวอย่างข้างล่าง เราจะทำการเพิ่มข้อมูลไปยังตารางที่ใช้เชื่อม สามารถส่งเป็นอาเรย์ก็ได้:
1 $user->roles()->attach(1, array('expires' => $expires));
เมื่อเพิ่มแล้วก็ลบได้ ฟังก์ชัน detach ใช้ลบค่าในตารางที่ใช้เชื่อม
1 $user->roles()->detach(1);
เราสามารถใช้ฟังก์ชัน syncเมทอด เพื่อการเพิ่มค่าไปยังตารางที่เชื่อมอยู่ด้วยได้ ในขณะที่เพิ่มลงในตารางหลัก
ตัวอย่างการใช้ sync กับความสัมพันธ์แบบกลุ่มต่อกลุ่ม
1 $user->roles()->sync(array(1, 2, 3));
Aตัวอย่างการใช้ sync กับตารางกลาง
1 $user->roles()->sync(array(1 => array('expires' => true)));
การใช้เมทอด save เพื่อทำการเพิ่มข้อมูลงตารางที่เชื่อมกันอยู่
1 $role = new Role(array('name' => 'Editor'));
2
3 User::find(1)->roles()->save($role);
ในตัวอย่างเราสร้าง Role model แล้วแนบไปกับ User model. แล้วยังสามารถแนบอาเรย์เข้าไปได้อีก
1 User::find(1)->roles()->save($role, array('expires' => $expires));
<a name="touching-parent-timestamps"></a> ## การแก้ไขคอลัมน์ที่เก็บเวลาในตารางที้่่เชื่อมด้วย
ตัวอย่าง เมื่อเราแก้ไขข้อมูลในตาราง Comment เราต้องการแก้ไขข้อมูลในตาราง Post ในแถวที่เชื่อมกันด้วย laravel เตรียมฟังก์ชัน touch มาให้เเล้ว วิธีการใช้งานในตัวอย่างเลยครับ
1 class Comment extends Eloquent {
2
3 protected $touches = array('post');
4
5 public function post()
6 {
7 return $this->belongsTo('Post');
8 }
9
10 }
ตอนนี้ถ้าเราทำการแก้ไขข้อมูลในตาราง Comment, คอลัมน์ updated_at ข้อมูลในตาราง Postที่เชื่อมด้วยก็จะถูกแก้ไขด้วย
<a name="working-with-pivot-table"></a> ## การจัดการตารางที่ใช้เชื่อม
laravel เตรียมฟังก์ชัน pivot มาให้เราใช้ในการจัดการข้อมูลของตารางที่ใช้เชื่อมตรงกลางระหว่างสองตาราง ดังตัวอย่างเลยครับ
1 $user = User::find(1);
2
3 foreach ($user->roles as $role)
4 {
5 echo $role->pivot->created_at;
6 }
คลาส Role model จะดึงค่าออกมาจากตารางกลาง โดยใช้ฟังก์ชันpivot โดยอัติโนมัติ
โดยค่าเริ่มต้นแล้วค่าที่ได้จาก ตารางที่เป็นตัวเชื่อมจะมีค่าเดียวที่ใช้อ้างอิงไปยัง อีกตารางคือ id เท่านั้น แต่ถ้าเราต้องการเพิ่ม ก็ต้องเพิ่มไปตอนที่กำหนดความสัมพันธ์แบบในตัวอย่าง
1 return $this->belongsToMany('Role')->withPivot('foo', 'bar');
ตอนนี้ตัวแปร foo กับ bar จะถูกใช้กับฟังก์ชัน pivot ในการจัดการตาราง Role
และถ้าเราต้องการ คอลัมน์ created_at กับ updated_at เพื่อใช้กำหนดเวลา laravel มีฟังก์ชัน withTimestamps ซึ่งเราต้องกำหนดตอนประกาศความสัมพันธ์ครับ
1 return $this->belongsToMany('Role')->withTimestamps();
ต่อมาถ้าเราต้องการลบข้อมูลในตารางในตารางกลาง เพื่อความถูกต้องของข้อมูลเราจะใช้ฟังก์ชัน detachนะครับ
ตัวอย่างการใช้งาน
1 User::find(1)->roles()->detach();
เราจะทำการแก้ไขไม่ให้ผู้ใช้งานหมายเลข 1 มีสิทธิในการทำอะไรเลย
<a name="has-many-through"></a> ### Has Many Through
ใช้อำนวยความสะดวก ในการเข้าถึงโมเดลที่มีความสัมพันธ์กัน แต่ต้องเรียกผ่านโมเดลอีกหลายตัว ยกตัวอย่าง โมเดล Country มีความสัมพันธ์แบบ one to many กับโมเดล Posts เช่เดียวกับโมเดล Users โครงสร้างตารางของทั้งสามโมเดลจะเป็นแบบนี้
1 countries
2 id - integer
3 name - string
4
5 users
6 id - integer
7 country_id - integer
8 name - string
9
10 posts
11 id - integer
12 user_id - integer
13 title - string
<br /><br /><br />
จะเห็นว่าตาราง posts จะไม่ได้เก็บ country_id ด้วยความสามารถของความสัมพันธ์แบบ hasManyThrough จะทำการเชื่อมต่อ อัติโนมัติให้ทำ เราสามารถเรียก ใช้งานโมเดล post ได้ โดยการประกาศ ฟังก์ชันดังตัวอย่าง
1 class Country extends Eloquent {
2
3 public function posts()
4 {
5 return $this->hasManyThrough('Post', 'User');
6 }
7
8 }
ตัวอย่างนี้ก็เป็นการอนุญาตให้เรา กำหนดฟอเรี้ยนคีย์ได้
1 class Country extends Eloquent {
2
3 public function posts()
4 {
5 return $this->hasManyThrough('Post', 'User', 'country_id', 'user_id');
6 }
7
8 }
<a name="collections"></a> ## Collections
ข้อมูลที่เป็นผลลัพท์ของการค้นหานั้นจะกลับออกมาเป็น อาเรย์ eloquent อำนวนความสะดวกให้เราโดยมีฟังกชัน contains ให้ในการตรวจสอบข้อมูล
ตรวจว่าในผลลัพท์ที่ได้มามีข้อมูลที่มีคีย์หลัก เป็น 2 ไหม
1 $roles = User::find(1)->roles;
2
3 if ($roles->contains(2))
4 {
5 //
6 }
เพื่อความสบายของเรายิ่งขึ้นไปอีกเมื่อค้นเสร็จก็เอาเฉพาะค่า role แปลงเป็นอาเรย์ หรือ json เสร็จสรรพเลย
1 $roles = User::find(1)->roles->toArray();
2
3 $roles = User::find(1)->roles->toJson();
แทนที่จะใช้การทำ foreach แบบปกติเหมือนเดิม eloquent มีฟังก์ชัน each กับ filter มาให้ <br /><br /> การใช้งาน each และ filter
1 $roles = $user->roles->each(function($role)
2 {
3
4 });
5
6 $roles = $user->roles->filter(function($role){});
เพิ่มการ Callback
1 $roles = User::find(1)->roles;
2
3 $roles->each(function($role)
4 {
5 //
6 });
เรียงลำดับค่าที่อยู่ในอาเรย์ด้วยฟังก์ชัน sortby
1 $roles = $roles->sortBy(function($role)
2 {
3 return $role->created_at;
4 });
บางครั้งเราต้องการเปลียนแปลงค่าทั้งออปเจคเลย eloquent ก็มีฟังก์ชัน newCollection ให้ใช้ในการเขียนทับ
ตัวอย่างการใช้งาน
1 class User extends Eloquent {
2
3 public function newCollection(array $models = array())
4 {
5 return new CustomCollection($models);
6 }
7
8 }
<br /><br /> <a name="accessors-and-mutators"></a> ## Accessors & Mutators
บางเวลาเราต้องการ จัดรูปแบบข้อมูลให้อยู่ในรูปแบบที่เราต้องการ ก่อนจะบันทึกหรือดึงมาใช้ eloquent เตรียมฟังก์ชัน getFooAttribute แต่การตั้งชื่อฟังก์ชันคำเริ่มต้นของคำที่เป็นชื่อของคอลัมน์ ต้องขึ้นต้นด้วยตัวพิมพ์ใหญ่ ในกรณีที่มีเครื่องหมาย _ มาคั่น คำหลังจากนั้นก็ต้องขึ้นต้นด้วยตัวพิมพ์ใหญ่ครับ
ตัวอย่าง
1 class User extends Eloquent {
2
3 public function getFirstNameAttribute($value)
4 {
5 return ucfirst($value);
6 }
7
8 }
ในตัวอย่างเราทำการสร้าง accessor ของคอลัมน์ first_name ทีนี้ค่าที่เราส่งเข้าฟังก์ชันนี้ก็จะถูกส่งไปเก็บถูกที่ละครับ
การสร้างฟังก์ชัน Mutator ก็คล้ายๆ กัน
ตัวอย่าง
1 class User extends Eloquent {
2
3 public function setFirstNameAttribute($value)
4 {
5 $this->attributes['first_name'] = strtolower($value);
6 }
7
8 }
<br /><br /><br /><br /><br /> <a name="date-mutators"></a> ## Date Mutators
โดยค่าเริ่มต้นเเล้ว Eloquent จะทำการตั้งค่าให้คอลัมน์ created_at, updated_at, และ deleted_at ตามค่าเบื้องต้นของ php.ini อยู่เเล้วนะครับ
แต่ถ้าเราต้องการแก้ไขหรือเรียกใช้งานแบบไม่อยากเข้าไปยุ่งตรงๆ ก็สามารถใช้ฟังก์ชัน getDates แบบในตัวอย่างเลยครับ
1 public function getDates()
2 {
3 return array('created_at');
4 }
ข้างในเราสามารถจัดการก่อนเอาไปใช้ได้เลย และ laravel ก็มีคลาสจัดการ วันเวลาที่มีฟังก์ชันหลากหลายมากอย่าง Carbon มาให้ใช้ด้วย แต่ต้องไปประกาศชื่อย่อในไฟล์ app.php ก่อนนะครับ โดยค่าเริ่มต้นเเล้วไม่มี
<a name="model-events"></a> ## Model Events
Eloquent เตรียมฟังก์ชันที่คอยดักจับเหตุการณ์ต่างๆ มาให้เราดังนี้ครับ creating, created, updating, updated, saving, saved, deleting, deleted. แต่ถ้าค่าที่ส่งกลับมาเป็น false เหตุการณ์ creating, updating, หรือ saving จะถูกยกเลิก
การยกเลิกการแก้ไขข้อมูล
1 User::creating(function($user)
2 {
3 if ( ! $user->isValid()) return false;
4 });
การที่เราจะสร้างฟังก์ชัน์ในการจัดการเหตุการณ์ของ model ต้องประกาศฟังชัน boot ก่อนนะครับ
การประกาศฟังก์ชัน boot
1 class User extends Eloquent {
2
3 public static function boot()
4 {
5 parent::boot();
6
7 // Setup event bindings...
8 }
9
10 }
<a name="model-observers"></a> ## Model Observers
Eloquent มีคลาสชื่อ Observer ในการสร้างฟังก์ชันที่ใช้จัดการเหตุการณ์ ฟังก์ชันcreating, updating, saving ก็ตั้งตามเหตุการณ์ที่จะให้ฟังก์ชันนั้นจัดการครับ ตัวอย่าง
1 class UserObserver {
2
3 public function saving($model)
4 {
5 //
6 }
7
8 public function saved($model)
9 {
10 //
11 }
12
13 }
แล้วเราก็ต้องประกาศโดยใช้ฟังชัน observe แบบตัวอย่าง
1 User::observe(new UserObserver);
<a name="converting-to-arrays-or-json"></a> ## การแปลงค่าเป็น Arrays หรือ JSON
การแปลงผลลัพทที่ค้นมาให้กลายเป็น array
1 $user = User::with('roles')->first();
2
3 return $user->toArray();
4
5 return User::all()->toArray();
การแปลงผลลัพธ์ให้กลายเป็น json
1 return User::find(1)->toJson();
<br /><br /><br /> การใช้งาน Eloquent จากใน route เลย
1 Route::get('users', function()
2 {
3 return User::all();
4 });
บางเวลาาเราไม่อยากให้บางคอลัมน์ถุกเรียกไปพร้อมกับ toJson หรือ toArray เราก็ใช้ตัวแปร hidden ในการนั้น
ต้วอย่างการใช้งาน
1 class User extends Eloquent {
2
3 protected $hidden = array('password');
4
5 }