模型定義,預設情況下,ThinkPHP的模型類是位於/Home/Model/目錄之下,模型類通常需要繼承系統的\Think\Model類或其子類,下面是一個Home\Model\UserModel類的定義:
檔案命名遵守UserModel.class.php的方式,跟控制器的命名一樣
<?phpnamespace Home\Model;use Think\Model;class UserModel extends Model {}
模型類的作用大多數情況是操作資料表的,如果按照系統的規範來命名模型類的話,大多數情況下是可以自動對應資料表,但你可以根據自己的需求來定製自己的資料表設定和操作。
首先我們需要在設定檔設定我們的資料庫連接資訊:
'DB_TYPE' => 'mysql', 'DB_HOST' => 'localhost', 'DB_NAME' => 'database', 'DB_USER' => 'username', 'DB_PWD' => 'password', 'DB_PORT' => '3306',
這些配置資訊還是在/Home/Conf/config.php檔案裡設定。
指定資料表首碼
指定標首碼,我們在第一課的配置項已經指定,以下的文字表示你可以靈活配置你的資料表。
protected $tablePrefix = 'top_';
如果資料庫的表沒有表首碼,使用Null 字元串代替
protected $tablePrefix = '';
指定資料表,此處的指定的資料表的不需要添加表首碼:
protected $tableName = 'user';
舉個例子說,比如說你的資料庫中有一個沒有表首碼的,名為users的資料表,可以用以下的兩種方法在模型中進行下面的定義:
第一,直接根據系統的規範來命名模型類來命名模型,比如說就命名為UsersModel那麼只需要在這個類裡面加上下面的設定就可以了:
protected $tablePrefix = '';
ThinkPHP系統就會自動定位到users表了。
第二種情況時,如果你的模型類沒有按照系統規範來命名,比如說不小心命名為UserModel,這種情況下可以同時指定表首碼和表明,比如:
protected $tablePrefix = '';protected $tableName = 'users';
或者你直接指定trueTableName:
protected $trueTableName = 'users';
既然模型通常是用來操作資料表,那麼我們來看看模型的基本CURD:
註:為了方便示範,我們在UserController中定義一個testDemo()方法用於示範
public function testDemo() { }
以下的代碼將會一段一段在這個方法裡示範,你可以通過訪問http://localhost:8999/index.php/Home/User/testDemo來看到實際效果。
添加紀錄
$user = M('User');$data['username'] = 'ThinkPHP';$data['email'] = 'ThinkPHP@gmail.com';$user->create($data);$record = $user->add();dump($record);
add()返回的是插入資料的id,對於不存在的表欄位,add()方法會自動過濾。
讀取紀錄
在ThinkPHP中讀取資料的方式很多,通常分為讀取資料、讀取資料集和讀取欄位值
$user = M('User');$record = $user->where('username="ThinkPHP"')->find();dump($record);
讀取欄位值
$user = M('User');$record = $user->where('id=3')->getField('username');dump($record);
預設情況下,當只有一個欄位的時候,返回滿足條件的資料表中的該欄位的第一行的值.如果getField()傳入多個欄位,傳回值將是一個關聯陣列:
$user = M('User');$record = $user->getField('username,email');dump($record);
這個數組總是以傳入的第一個第一個欄位為索引值的。如果修改為:
$user = M('User');$record = $user->getField('email,username');dump($record);
將上面的兩次代碼分別放到testDemo(),你就會看到不一樣的結果集。
用save()方法更新資料
$user = M('User');$data['username'] = 'ThinkPHPSave';$data['email'] = 'ThinkPHPSave@outlook.com';$record = $user->where('id=3')->save($data);dump($record);
這裡的$record返回的事1,表示成功更改。
當然,你也可以這樣:
$user = M('User');$user->username = 'ThinkPHP';$user->email = 'ThinkPHP@outlook.com';$record = $user->where('id=3')->save();dump($record);
日常開發的時候經常會遇到一些只更新某些欄位的情況,可以通過下面的方式來實現:
$user = M("User"); $record = $user->where('id=4')->setField('username','ThinkPHPChangeName');dump($record);
同時更新多個欄位,可以將資料以數組的形式傳給setField()方法:
$user = M('User');$data = array('username'=>'ThinkPHPChangeArray','email'=>'ThinkPHP@array.com');$record = $user-> where('id=6')->setField($data);dump($record);
ThinkPHP刪除資料使用delete方法,例如:
$user = M('User');$record = $user->where('id=3')->delete();dump($record);
或者你可以直接使用:
$record = $user->delete('1,2,5');dump($record);
這樣就達到了刪除主鍵1,2,5這三條紀錄了。
ActiveRecords
ThinkPHP實現了ActiveRecords模式的ORM模型,採用了非標準的ORM模型:表映射到類,記錄映射到對象。以下執行個體將使用ActiveRecords重現對資料表的CURD,看看ActiveRecords給我們帶來了什麼好處。
$user = M("User");$user->username = 'ThinkPHPWithActive';$user->email = 'ThinkPHPActive@gmail.com';$record = $user->add();dump($record);
讀取紀錄
AR最大的特點可能就是它的查詢模式了,模式簡單易用,因為更多情況下面查詢條件都是以主鍵或者某個關鍵的欄位。這種類型的查詢,ThinkPHP有著很好的支援。
比如說擷取主鍵為2的使用者資訊:
$user = M("User");$record = $user->find(2);dump($record);
直接不用where()查詢了,簡單友好吧。再比如:
$user = M("User");$record = $user->getByUsername("jelly");dump($record);
如果是查詢多條紀錄,使用以下方式:
$user = M("User");$record = $user->select('1,3,8');dump($record);
更新記錄
$user = M("User");$user->find(21);$user->username = 'TOPThinkChangeWithAR';$record = $user->save();dump($record);
刪除記錄
刪除單條紀錄
$user = M("User");$record = $user->delete(8);dump($record);
刪除多條紀錄
$user = M("User");$record = $user->delete('15,16');dump($record);// todo: 這裡的自動驗證和關聯模型 調試不出來。
自動完成
自動完成是ThinkPHP提供用來完成資料自動處理和過濾的方法,當使用create()方法建立資料對象的時候會觸發自動完成數機制。
因此,在ThinkPHP鼓勵使用create()方法來建立資料對象,因為這是一種更加安全的方式,直接通過add()或者save()方法實現資料寫入無法出發自動完成機制。
自動完成通常用來完成預設欄位寫入(比如新增時間戳記),安全欄位過濾(比如加密密碼)以及商務邏輯的自動處理等。可以通過模型類裡面通過$_auto屬性定義處理規則。下面示範如何自動完成新增時間戳記:
在UserModel中,聲明自動完成的定義數組$_auto :
protected $_auto = array ( array('created_at','date("Y-m-d H:i:s", time())',3,'function'), array('updated_at','date("Y-m-d H:i:s", time())',3,'function'), );
還有一種是理由auto()方法動態設定自動完成的機制,可以到官方文檔去看看
設定完成之後,我們在testDemo()方法中建立一條使用者資料:
$user = D('User');$data['username'] = "ThinkPHP";$data['email'] = "ThinkPHP@gmail.com";$user->create($data);$record = $user->add();dump($record);
測試,如果返回紀錄的id值,說明使用者紀錄建立成功。要驗證資料是否自動完成,你可以直接使用:
$user = D('User');$record = $user->find(id);dump($record);
自動驗證
自動驗證是ThinkPHP模型層提供的一種資料驗證方法,可以在使用create()建立資料對象的時候自動進行資料驗證。
資料驗證可以進行資料類型、商務規則、安全判斷等方面的驗證操作。
通常用於表單驗證
資料驗證有兩種方式:
靜態方式:在模型類裡面通過$_validate屬性定義驗證規則。
動態方式:使用模型類的validate()方法動態建立自動驗證規則。
無論是什麼方式,驗證規則的定義是統一的規則,定義格式為:
array(
array(驗證欄位1,驗證規則,錯誤提示,[驗證條件,附加規則,驗證時間]),
array(驗證欄位2,驗證規則,錯誤提示,[驗證條件,附加規則,驗證時間]),
......
);
下面以$_validate靜態方式舉例如何使用自動驗證:
在UserController中建立register()方法,對,幾乎每一個Web應用都需要實現使用者註冊這一步。
public function register() { $this->display(); }
對,就是這麼簡單,這個方法只是將相應的視圖檔案渲染出來。所以接下來我們建立對應的視圖檔案,也就是:./Application/Home/View/User/register.html
<extend name="Index/base" /><block name="main" ><form method="post" action="__URL__/registerValidate"> <div class="form-group"> <label for="exampleInputName">Name</label> <input type="text" name="username" class="form-control" id="exampleInputName" placeholder="Name"> </div> <div class="form-group"> <label for="exampleInputEmail">Email</label> <input type="email" name="email" class="form-control" id="exampleInputEmail" placeholder="Email"> </div> <button type="submit" class="btn btn-default">Submit</button></form></block>
上面就是一些HTML代碼和一點模板的知識,對於模板,我們後續會講到,但不管怎樣,現在我們訪問
http://localhost:8999/Home/User/register,就可以看到我們的註冊表單頁面了。
注意到form表單中,action="__URL__/registerValidate",這表示提交到當前的控制器的registerValidate()方法處理,所以我們在UserController中增加registerValidate()方法:
public function registerValidate() { $data['username'] = $_POST['username']; $data['email'] = $_POST['email']; $user = D("User"); if ( !$user->create($data) ) { exit($user->getError()); } //todo: validation passes, add data to database and redirect somewhere echo 'validation passes'; }
這裡的if ( !$user->create($data) )會觸發自動驗證並判斷驗證是否通過驗證。你可以嘗試在表單裡填寫不同的資料來進行測試,也可以修改一下驗證規則,更多規則可以到官網查看:
http://document.thinkphp.cn/manual_3_2.html
關聯模型
通常我們所說的關聯關係包括下面三種:
一對一關聯 :ONE_TO_ONE,包括HAS_ONE 和 BELONGS_TO
一對多關聯 :ONE_TO_MANY,包括HAS_MANY 和 BELONGS_TO
多對多關聯 :MANY_TO_MANY
關聯定義
ThinkPHP可以很輕鬆的完成資料表的關聯CURD操作,目前支援的關聯關係包括下面四種:
HAS_ONE、BELONGS_TO、HAS_MANY和MANY_TO_MANY。
一個模型根據業務模型的複雜程度可以同時定義多個關聯,不受限制,所有的關聯定義都統一在模型類的 $_link 成員變數裡面定義,並且可以支援動態定義。要支援關聯操作,模型類必須繼承Think\Model\RelationModel類,關聯定義的格式類似於:
namespace Home\Model;use Think\Model\RelationModel;class UserModel extends RelationModel{ protected $_link = array( '關聯' => array( '關聯屬性1' => '定義', '關聯屬性N' => '定義', ), );}
關於關聯屬性的定義和值,你可以到官方文檔仔細查看,我們下面也會給出一些最常用的。
在我們的講解例子中,會採用HAS_MANY和BELONGS_TO來示範,對於其他的幾個關聯式模式,可以參考官方文檔舉一反三。
首先我們知道資料庫裡面有兩張表,使用者表和文章表,並且我們也為其建立了不同的模型(UserModel ArticelModel)。
現在我們仔細來想想他們之間的對應關係:一個使用者可以擁有多篇文章,而每一篇文章都屬於某個特定的使用者。所以我們可以分別為這兩種關係添加關聯模型:
在UserModel中:
protected $_link = array( 'Article' => self::HAS_MANY );
在ArticleModel中:
protected $_link = array( 'User' => self::BELONGS_TO );
以上者兩種都是最簡潔的模型關聯聲明。因為在最開始設計資料庫的時候,我們遵守了ThinkPHP的官方的規範:
外鍵的預設規則是當前資料對象名稱_id,例如:UserModel對應的可能是表think_user,那麼think_user表的外鍵預設為user_id,如果你的外鍵不是user_id,而是其他自訂的欄位如:user_identify,那麼就必須在定義關聯的時候定義 foreign_key 。如下:
在UserModel中:
protected $_link = array( 'mapping_type' => self::HAS_MANY, 'class_name' => 'Article', 'foreign_key' => 'user_identify', );
更多自訂的關聯模型參數可以到官網查看。
有了以上的定義之後,我們就可以在檢索使用者資料的同時將屬於他的文章也一起檢索出來,使用relation()。
同樣是在testDemo()這個方法中:
$user = D('User');$record = $user->relation(true)->find(4);dump($record);
訪問熟悉的http://localhost:8999/Home/User/testDemo,你將會看到神奇的結果。
以上所述就是本文的全部內容了,希望大家能夠喜歡。