W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
CodeIgniter支持實體類作為其數據庫層中的一等公民,同時使它們完全可選使用。它們通常用作存儲庫模式的一部分,但如果更適合您的需求,則可以直接與模型一起使用。
實體類的核心只是代表單個數據庫行的類。它具有表示數據庫列的類屬性,并提供了用于實現(xiàn)該行的業(yè)務邏輯的任何其他方法。但是,核心功能是它對如何持久化一無所知。這是模型或存儲庫類的責任。這樣,如果需要保存對象的方式發(fā)生任何變化,則無需更改在整個應用程序中使用該對象的方式。這樣就可以在快速原型制作階段使用JSON或XML文件存儲對象,然后在證明該概念行得通的情況下輕松地切換到數據庫。
讓我們來看一個非常簡單的用戶實體,以及如何使用它來使事情變得清晰。
假設您有一個users
具有以下架構的數據庫表:
id - integer
username - string
email - string
password - string
created_at - datetime
現(xiàn)在創(chuàng)建一個新的實體類。由于沒有默認位置可存儲這些類,并且它不適合現(xiàn)有的目錄結構,因此請在app / Entities處創(chuàng)建一個新目錄。在app / Entities / User.php中創(chuàng)建實體本身。
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
//
}
簡單地說,這就是您需要做的,盡管我們將在一分鐘內使它變得更加有用。
首先在app / Models / UserModel.php中創(chuàng)建模型,以便我們可以與之交互:
<?php namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
protected $table = 'users';
protected $allowedFields = [
'username', 'email', 'password'
];
protected $returnType = 'App\Entities\User';
protected $useTimestamps = true;
}
該模型將users
數據庫中的表用于其所有活動。我們將$allowedFields
屬性設置為包括我們希望外部類更改的所有字段。的id
,created_at
和updated_at
字段由類或數據庫中自動處理的,所以我們不希望改變這些。最后,我們將Entity類設置為$returnType
。這確保了模型上從數據庫返回行的所有方法都將返回我們的User Entity類的實例,而不是像通常那樣返回對象或數組。
現(xiàn)在所有部分都準備就緒,您將像其他任何類一樣使用Entity類:
$user = $userModel->find($id);
// Display
echo $user->username;
echo $user->email;
// Updating
unset($user->username);
if (! isset($user->username)
{
$user->username = 'something new';
}
$userModel->save($user);
// Create
$user = new \App\Entities\User();
$user->username = 'foo';
$user->email = 'foo@example.com';
$userModel->save($user);
您可能已經注意到,User類沒有為列設置任何屬性,但是您仍然可以像訪問它們一樣將其作為公共屬性來訪問它們?;?strong>CodeIgniterEntity為您解決了這一問題,并提供了使用isset()或unset()屬性檢查屬性的能力,并跟蹤自創(chuàng)建或拉出對象以來哪些列已更改從數據庫中。
當User傳遞給模型的save()方法時,它將自動負責讀取屬性并將對模型的$ allowedFields屬性中列出的列的所有更改保存。它還知道是創(chuàng)建新行還是更新現(xiàn)有行。
Entity類還提供一種方法,fill()
該方法允許您將鍵/值對的數組推入類并填充類屬性。數組中的任何屬性都將在實體上設置。但是,在通過模型進行保存時,實際上僅將$ allowedFields中的字段保存到數據庫中,因此您可以在實體上存儲其他數據,而不必擔心會錯誤地保存雜散字段。
$data = $this->request->getPost();
$user = new \App\Entities\User();
$user->fill($data);
$userModel->save($user);
您也可以在構造函數中傳遞數據,并且數據將在實例化過程中通過fill()方法傳遞。
$data = $this->request->getPost();
$user = new \App\Entities\User($data);
$userModel->save($user);
盡管上面的示例很方便,但它們并不能幫助您實施任何業(yè)務邏輯?;鶎嶓w類實現(xiàn)一些智能__get()
和__set()
方法,將檢查特別的方法和使用這些而不是直接使用屬性,讓你執(zhí)行你需要的任何業(yè)務邏輯或數據轉換。
這是一個更新的User實體,提供了一些如何使用它的示例:
<?php namespace App\Entities;
use CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
class User extends Entity
{
public function setPassword(string $pass)
{
$this->attributes['password'] = password_hash($pass, PASSWORD_BCRYPT);
return $this;
}
public function setCreatedAt(string $dateString)
{
$this->attributes['created_at'] = new Time($dateString, 'UTC');
return $this;
}
public function getCreatedAt(string $format = 'Y-m-d H:i:s')
{
// Convert to CodeIgniter\I18n\Time object
$this->attributes['created_at'] = $this->mutateDate($this->attributes['created_at']);
$timezone = $this->timezone ?? app_timezone();
$this->attributes['created_at']->setTimezone($timezone);
return $this->attributes['created_at']->format($format);
}
}
首先要注意的是我們添加的方法的名稱。對于每個類,該類都希望將snake_case列名轉換為PascalCase,并以set
或作為前綴get
。每當您使用直接語法(即$ user-> email)設置或檢索class屬性時,這些方法將被自動調用。除非您希望從其他類訪問它們,否則這些方法不需要是公共的。例如,created_at
將通過setCreatedAt()
和getCreatedAt()
方法訪問class屬性。
注解
這僅在嘗試從類外部訪問屬性時有效。該類內部的任何方法都必須直接調用setX()
和getX()
方法。
在該setPassword()
方法中,我們確保始終對密碼進行哈希處理。
在setCreatedAt()
我們將從模型接收的字符串轉換為DateTime對象時,請確保我們的時區(qū)為UTC,以便我們可以輕松地轉換查看器的當前時區(qū)。在中getCreatedAt()
,它將時間轉換為應用程序當前時區(qū)中的格式化字符串。
這些示例雖然相當簡單,但是卻表明使用Entity類可以提供一種非常靈活的方式來強制執(zhí)行業(yè)務邏輯并創(chuàng)建易于使用的對象。
// Auto-hash the password - both do the same thing
$user->password = 'my great password';
$user->setPassword('my great password');
在您的職業(yè)生涯中的很多時候,您都會遇到以下情況:應用程序的使用已發(fā)生更改,并且數據庫中的原始列名不再有意義?;蛘撸l(fā)現(xiàn)您的編碼風格更喜歡camelCase類屬性,但是您的數據庫模式需要snake_case名稱。使用Entity類的數據映射功能可以輕松處理這些情況。
例如,假設您擁有在整個應用程序中使用的簡化用戶實體:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
protected $attributes = [
'id' => null,
'name' => null, // Represents a username
'email' => null,
'password' => null,
'created_at' => null,
'updated_at' => null,
];
}
您的老板來找您,并說沒有人再使用用戶名,因此您將切換為僅使用電子郵件進行登錄。但是他們確實希望對應用程序進行一些個性化設置,因此他們希望您更改名稱字段以現(xiàn)在表示用戶的全名,而不是像現(xiàn)在這樣表示用戶名。為了使事情保持整潔并確保事情在數據庫中繼續(xù)有意義,您進行了一次遷移,以將名稱字段重命名為full_name以便清楚。
忽略此示例有多難為情,我們現(xiàn)在有兩個關于如何修復User類的選擇。我們可以將class屬性從修改$name
為$full_name
,但這需要在整個應用程序中進行更改。相反,我們可以簡單地full_name
將數據庫中的列映射到該$name
屬性,并通過Entity更改來完成:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
protected $attributes = [
'id' => null,
'name' => null, // Represents a username
'email' => null,
'password' => null,
'created_at' => null,
'updated_at' => null,
];
protected $datamap = [
'full_name' => 'name'
],
}
通過將新的數據庫名稱添加到$datamap
數組,我們可以告訴類應該通過其訪問數據庫列的類屬性。數組的鍵是數據庫中列的名稱,其中數組中的值是將其映射到的類屬性。
在此示例中,當模型full_name
在User類上設置字段時,它實際上將該值分配給該類的$name
屬性,因此可以通過進行設置和檢索$user->name
。同樣,該值仍可以通過原始值訪問$user->full_name
,因為模型需要該值來取回數據并將其保存到數據庫。但是,unset
并且isset
僅適用于映射的屬性$name
,不適用于原始名稱 full_name
。
默認情況下,實體類將轉換命名字段created_at,的updated_at,或deleted_at到 時間時,他們設置或獲取的實例。Time類以不變,本地化的方式提供了大量有用的方法。
您可以通過將名稱添加到options ['dates']數組來定義自動轉換的屬性:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
}
現(xiàn)在,當設置了這些屬性中的任何一個時,它們將使用應用程序的當前時區(qū)(如app / Config / App.php中的設置)轉換為Time實例:
$user = new \App\Entities\User();
// Converted to Time instance
$user->created_at = 'April 15, 2017 10:30:00';
// Can now use any Time methods:
echo $user->created_at->humanize();
echo $user->created_at->setTimezone('Europe/London')->toDateString();
您可以使用casts屬性指定將Entity中的屬性轉換為通用數據類型。此選項應該是一個數組,其中鍵是類屬性的名稱,而值是應強制轉換為的數據類型。投射僅在讀取值時影響。不會發(fā)生影響實體或數據庫中的永久值的轉換??梢詫傩詮娭妻D換為以下任何數據類型: integer,float,double,string,boolean,object,array,datetime和timestamp。在類型的開頭添加一個問號,以將屬性標記為可為空,即?string,?integer。
例如,如果您有一個具有is_banned屬性的User實體,則可以將其強制轉換為布爾值:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
protected $casts = [
'is_banned' => 'boolean',
'is_banned_nullable' => '?boolean'
],
}
數組/ Json強制轉換對于在其中存儲序列化數組或json的字段特別有用。轉換為:
當您讀取屬性值時。與可以將屬性轉換為的其余數據類型不同,它們是:
設置屬性時的值:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class User extends Entity
{
protected $casts => [
'options' => 'array',
'options_object' => 'json',
'options_array' => 'json-array'
];
}
$user = $userModel->find(15);
$options = $user->options;
$options['foo'] = 'bar';
$user->options = $options;
$userModel->save($user);
您可以檢查Entity屬性自創(chuàng)建以來是否已更改。唯一的參數是要檢查的屬性的名稱:
$user = new User();
$user->hasChanged('name'); // false
$user->name = 'Fred';
$user->hasChanged('name'); // true
或檢查整個實體是否有更改的值,請省略參數:
$user->hasChanged(); // true
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: