ปัจจุบัน Eloquent ของ Laravel Framework ยังไม่รองรับการบันทึกข้อมูลที่มี Primary Key แบบหลาย Columns ได้ ผมได้ค้นหาจากอินเตอร์เน็ต และพบว่ามีคนที่แนะนำแนวทางแก้ไข โดยใช้วิธีการ Overide method save ของ Eloquent ขึ้นมาแทน ซึ่งผมได้ทดลองใช้แล้วสามารถทำงานได้อย่างถูกต้อง จึงขอแนะนำการนำ Method save ที่ถูกปรับปรุงมาเขียนเป็น Base Class ของ Model ดังตัวอย่าง
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
| <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use DB;
class BaseModel extends Model
{
public function save(array $options = []) {
if( ! is_array($this->getKeyName()))
{
return parent::save($options);
}
// Fire Event for others to hook
if($this->fireModelEvent('saving') === false) return false;
// Prepare query for inserting or updating
$query = $this->newQueryWithoutScopes();
// Perform Update
if ($this->exists)
{
if (count($this->getDirty()) > 0)
{
// Fire Event for others to hook
if ($this->fireModelEvent('updating') === false)
{
return false;
}
// Touch the timestamps
if ($this->timestamps)
{
$this->updateTimestamps();
}
//
// START FIX
//
// Convert primary key into an array if it's a single value
$primary = (count($this->getKeyName()) > 1) ? $this->getKeyName() : [$this->getKeyName()];
// Fetch the primary key(s) values before any changes
$unique = array_intersect_key($this->original, array_flip($primary));
// Fetch the primary key(s) values after any changes
$unique = !empty($unique) ? $unique : array_intersect_key($this->getAttributes(), array_flip($primary));
// Fetch the element of the array if the array contains only a single element
//$unique = (count($unique) <> 1) ? $unique : reset($unique);
// Apply SQL logic
$query->where($unique);
//
// END FIX
//
// Update the records
$query->update($this->getDirty());
// Fire an event for hooking into
$this->fireModelEvent('updated', false);
}
}
// Insert
else
{
// Fire an event for hooking into
if ($this->fireModelEvent('creating') === false) return false;
// Touch the timestamps
if($this->timestamps)
{
$this->updateTimestamps();
}
// Retrieve the attributes
$attributes = $this->attributes;
if ($this->incrementing && !is_array($this->getKeyName()))
{
$this->insertAndSetId($query, $attributes);
}
else
{
$query->insert($attributes);
}
// Set exists to true in case someone tries to update it during an event
$this->exists = true;
// Fire an event for hooking into
$this->fireModelEvent('created', false);
}
// Fires an event
$this->fireModelEvent('saved', false);
// Sync
$this->original = $this->attributes;
// Touches all relations
if (array_get($options, 'touch', true)) $this->touchOwners();
return true;
}
}
|
โดยการนำเอา BaseModel นี้ไปใช้ในรูปแบบการ Extend Model Class ดังต่อไปนี้
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\BaseModel;
class MyTable extends BaseModel
{
protected $table = 'MyTable';
protected $primaryKey = ['MY_KEY_COLUMN_1', 'MY_KEY_COLUMN_2', 'MY_KEY_COLUMN_3'];
public $incrementing = false;
public $timestamps = false;
}
|
และสามารถเรียกใช้งานได้เป็นปกติได้เลย เช่น
1
2
3
4
5
6
7
| $myTable = new MyTable;
$myTable->FIELD1 = 'Feild1_Value';
$myTable->FIELD2 = 'Field2_Value';
$myTable->MY_KEY_COLUMN1 = 'Key1_Value';
$myTable->MY_KEY_COLUMN2 = 'Key2_Value';
$myTable->MY_KEY_COLUMN3 = 'Key3_Value';
$myTable->save();
|
Credits
- ขอบคุณข้อมูล Method Save จากคคุณ tsilenzio ซึ่งได้ post ไว้ใน https://github.com/laravel/framework/issues/5517
Comments
Post a Comment