ThinkPHP 內置的 add 方法用于向數據表添加數據,相當于 SQL 中的 INSERT INTO 行為。
ThinkPHP Insert 添加數據
添加數據 add 方法是 CURD(Create,Update,Read,Delete / 創建,修改,讀取,刪除)中的 Create 的實現,ThinkPHP 支持以普通數組方式和面向對象方式將數據寫入數據表。
現在以《PHP MySQL 數據庫教程》中操作 user 表數據的例子(具體參見:MySQL Insert into 添加數據)為例,來演示如何在 ThinkPHP 中實現對數據表的數據添加操作。
例子:
在 IndexAction 控制器(Lib/Action/IndexAction.class.php)里,添加 insert() 操作:
訪問執行該操作:http://127.0.0.1/html/Myapp/index.php/Index/insert
- public?function?insert(){?
- header("Content-Type:text/html;?charset=utf-8");?
- $Dao?=?M("User");??
- ?
- ?
- $data["username"]?=?"大部落";?
- $data["password"]?=?md5("123456");?
- $data["email"]?=?"12345@163.com";?
- $data["regdate"]?=?time();?
- ?
- ?
- if($lastInsId?=?$Dao->add($data)){?
- echo?"插入數據?id?為:$lastInsId";?
- }?else?{?
- $this->error('數據寫入錯誤!');?
- }?
- }
語法解讀
M("User") 用于高效實例化一個數據模型(M 是 new Model 的簡寫,稱為快捷方法),參數為要操作的表名。
接下來構建要保存數據的數組 $data 。
最后是用 add() 方法將數據寫入庫表,由于使用的是 M快捷方法,需要將 $data 數組傳入 add() 方法。
add() 方法如果添加數據記錄成功,返回的是新數據記錄主鍵,可直接得到。
該例子實際運行的 SQL 為:
- INSERT?INTO?user(username,password,email,regdate)?VALUES?('大部落','e10adc3949ba59abbe56e057f20f883e',?
- '12345@163.com',1283612673)
提示:運行該例子,請確認在配置文件里正確配置了數據庫的相關賬號密碼等信息,具體參見《ThinkPHP 項目配置》
對象方式添加數據
上面的方式是以構造數據數組的方式,然后將數據以參數形式傳入 add 方法寫入數據表。ThinkPHP 也支持以對象的方式將數據寫入數據表,將上面的代碼更改為:
對象方式除了數據以數據對象方式賦值外,在調用 add 方法寫入數據的時候不需要傳遞參數
- public?function?insert(){?
- header("Content-Type:text/html;?charset=utf-8");?
- $Dao?=?M("User");??
- ?
- ?
- $Dao->username?=?"大部落";?
- $Dao->password?=?md5("123456");?
- $Dao->email?=?"12345@163.com";?
- $Dao->regdate?=?time();?
- ?
- ?
- if($lastInsId?=?$Dao->add()){?
- echo?"插入數據?id?為:$lastInsId";?
- }?else?{?
- $this->error('數據寫入錯誤!');?
- }?
- }
ThinkPHP 表單數據智能寫入 create 方法
創建數據對象 create()除了手動構造入庫的數據集之外,ThinkPHP 還提供了自動創建數據對象的 create() 方法。create() 方法將自動收集提交的表單數據并創建數據對象而無需人工干預,這在表單
數據字段非常多的情況下更具優勢。
將前文寫入表單數據的例子用 create() 來實現:
create() 創建數據對象后,將自動收集提交過來的表單數據。而表單數據可能需要經過一定加工(例如將密碼加密)才能寫入數據表,所以可以對數據對象的成員屬性值根據進行修改或添加去除等。
- public?function?insert2(){?
- header("Content-Type:text/html;?charset=utf-8");?
- $Dao?=?M("User");?
- ?
- if($Dao->create()){?
- $Dao->password?=?md5($_POST["password"]);?
- $Dao->regdate?=?time();?
- if($lastInsId?=?$Dao->add()){?
- echo?"插入數據?id?為:$lastInsId";?
- }?else?{?
- echo?"數據寫入錯誤!";?
- }?
- }else{?
- exit($Dao->getError().'?[?<a?href="javascript:history.back()">返?回</a>?]');?
- }?
- }?
提示:create() 創建的數據對象存放于內存,在執行入庫動作(add() 或 save())之前,都可以進行修改。
在上面的例子里,create()方法 的行為和 date()方法 是一致。但 date() 方法只是簡單的創建數據對象,但 create() 方法還具備:
令牌驗證
數據自動驗證
字段映射支持
字段類型檢查
數據自動完成
等各種高級的數據功能,要完成這些高級數據模型功能,需要使用 D方法 實例化數據模型。
在 LibModel 目錄下創建 UserModel.class.php 文件(User 為創建的模型對象,也對應 前綴_user 表),加入自動驗證和自動填充規則:
將 insert2 操作更改為:
如果提交的數據不符合驗證要求(如用戶名存在),則 create() 創建數據對象失敗(返回 FALSE ),$Dao->getError() 會打印出自動驗證設置規則里面設置的提示信息:用戶名已經存在!
如果驗證規則通過后,系統會進行自動填充設置,將表單密碼進行 MD5 加密以及取得當前的時間戳填充入 create() 的數據對象。
所以 D方法 配合 create() 是非常智能而強大的,恰當運用可以達到事半功倍快速開發的目的。
提示
D 方法配合 create() 由于其功能強大,也就損失了一定的效率,在業務邏輯不復雜的情況下推薦 M方法+data() 模式create() 默認接受 POST 數據,若要接受其他類型數據,只需在參數內指定即可,如接受 GET 數據:create($_GET)
- class?UserModel?extends?Model{?
- ?
- protected?$_validate?=?array(?
- array('username','require','用戶名必須填寫!',1),?
- array('email','email','郵箱格式錯誤!',2),?
- array('username','','用戶名已經存在!',0,'unique',1),?
- );?
- ?
- protected?$_auto?=?array(?
- array('regdate','time',self::MODEL_INSERT,'function'),?
- array('password','md5',self::MODEL_INSERT,'function'),?
- );?
- }
將 insert2 操作更改為:
- public?function?insert2(){?
- header("Content-Type:text/html;?charset=utf-8");?
- $Dao?=?D("User");?
- ?
- if($Dao->create()){?
- if($lastInsId?=?$Dao->add()){?
- echo?"插入數據?id?為:$lastInsId";?
- }?else?{?
- echo?"數據寫入錯誤!";?
- }?
- }else{?
- exit($Dao->getError().'?[?<a?href="javascript:history.back()">返?回</a>?]');?
- }?
- }
如果提交的數據不符合驗證要求(如用戶名存在),則 create() 創建數據對象失敗(返回 FALSE ),$Dao->getError() 會打印出自動驗證設置規則里面設置的提示信息:用戶名已經存在!
如果驗證規則通過后,系統會進行自動填充設置,將表單密碼進行 MD5 加密以及取得當前的時間戳填充入 create() 的數據對象。
所以 D方法 配合 create() 是非常智能而強大的,恰當運用可以達到事半功倍快速開發的目的。
提示
D 方法配合 create() 由于其功能強大,也就損失了一定的效率,在業務邏輯不復雜的情況下推薦 M方法+data() 模式create() 默認接受 POST 數據,若要接受其他類型數據,只需在參數內指定即可,如接受 GET 數據:create($_GET)
ThinkPHP 查詢數據主要提供以下幾類查詢:
select:普通查詢,同 findAll() 方法
find:取得符合查詢條件的一條記錄
getBy動態查詢:根據某個字段取得符合查詢條件的一條記錄
getField:獲取某個字段的值或多個字段的索引數組
區間查詢:取得符合查詢條件的區間記錄
統計查詢:取得符合查詢條件的統計數據
定位查詢:取得符合查詢條件的一條或多條記錄
原生SQL查詢:支持以原生 SQL 進行查詢或執行操作
select()
select() 是 ThinkPHP 中最常用的普通查詢方法,得到的是一個二維數組。findAll() 為 select() 方法的別名
,并建議使用 select()
讀取操作
下面的例子將 user 表的所有數據讀取出來并顯示:
- public?function?read(){?
- $Dao?=?M("User");?
- ?
- ?
- $list?=?$Dao->select();?
- ?
- ?
- ?
- $this->assign("list",?$list);?
- ?
- $this->display();?
- }?
假設上面的例子對應的 class 文件為 Lib/Action/IndexAction.class.php ,那么對應的模板文件為
Tpl/default/Index/read.html。
數據顯示模板
模板文件用于顯示剛才讀取的 User 表的數據。在學習階段,要不想使用模板,也可以直接使用 foreach 語法在
read() 操作內直接顯示讀取的數據。下面是模板相應的代碼片段,我們將讀取的數據在一個表格中顯示出來:
- "1">?
- ?
注冊時間?- ?
- "list"?id="vo">?
- ?
{$vo['username']}?- {$vo['email']}?
- {$vo['regdate']|date='Y-m-d?H:i',###}?
- ?
- ?
- ?
"10%">ID?
- "1">?
- ?
注冊時間?- ?
- "list"?id="vo">?
- ?
{$vo['username']}?- {$vo['email']}?
- {$vo['regdate']|date='Y-m-d?H:i',###}?
- ?
- ?
- ?
"30%">用戶名?
- "1">?
- ?
注冊時間?- ?
- "list"?id="vo">?
- ?
{$vo['username']}?- {$vo['email']}?
- {$vo['regdate']|date='Y-m-d?H:i',###}?
- ?
- ?
- ?
"30%">電子郵件?
- "1">?
- ?
注冊時間?- ?
- "list"?id="vo">?
- ?
{$vo['username']}?- {$vo['email']}?
- {$vo['regdate']|date='Y-m-d?H:i',###}?
- ?
- ?
- ?
- "1">?
- ?
注冊時間?- ?
- "list"?id="vo">?
- ?
{$vo['username']}?- {$vo['email']}?
- {$vo['regdate']|date='Y-m-d?H:i',###}?
- ?
- ?
- ?
要了解更多關于 ThinkPHP模板 的知識,請參閱:《ThinkPHP 模板》。
field() 查詢指定字段
select() 方法默認是查詢所有字段的數據,如果要查詢某個或某些字段,就需要使用 filed() 方法。
filed() 是屬于 ThinkPHP 連貫操作 中的一個方法,如在上面的例子中,只查詢用戶名和電子郵件地址,則查詢
方法對應更改為:
$list = $Dao->field('username,email')->select();
使用查詢條件
使用 ThinkPHP 連貫操作 可以很方便的對數據查詢使用查詢條件。下面是一些簡單的查詢條件的例子。
where() 條件
- ??
- $condition['username']?=?'Admin';?
- ?
- $list?=?$Dao->where($condition)->select();
上述查詢的就是 username='Admin' 這個條件的數據。關于 ThinkPHP where 條件更詳細資料,請參閱
《ThinkPHP Where 條件》。
ORDER BY 排序
在查詢中使用 ORDER BY 對數據進行排序:
- ?
- list?=?$Dao->order('uid?DESC')->select();
這個例子就是數據按照 ORDER BY uid DESC 進行查詢,而 order() 方法中的參數意義跟 SQL 語句中的意義完全
一致。
LIMIT 限制
在查詢中使用 LIMIT 限定數據返回的記錄數:
- ?
- $list?=?$Dao->limit('4,5')->select();
這個例子就是將第 5-10 條記錄取出,limit() 方法內的參數意義跟 SQL 語句中的 LIMIT 完全一致。
連貫操作
ThinkPHP 中允許將數據對象中的各個方法寫在一起操作,如:
- $list?=?$Dao->order('uid?DESC')->limit('4,5')->select();
這就是連貫操作,關于連貫操作更詳細的介紹,參見《ThinkPHP 連貫操作》。
原生SQL查詢有 query() 和 execute() 兩個方法:
query():用于 SQL 查詢操作,并返回符合查詢條件的數據集
execute():更新和寫入數據的 SQL 操作,返回影響的記錄數
query()
query() 方法是用于 SQL 查詢操作,和select()方法一樣返回符合查詢條件的數據集。
例子:
對于 query() 方法返回的數據集,跟 select() 一樣,可以在模板里直接循環輸出。
execute()
execute() 方法用于更新和寫入數據的 SQL 操作(注:非查詢操作,無返回數據集),返回影響的記錄數。
例子:
如果查詢比較復雜或一些特殊的數據操作不能通過 ThinkPHP 內置的 ORM 和 ActiveRecord 模式實現時,就可以通過直接使用原生 SQL 查詢來實現。
注意:以上都是 user 沒有表前綴的例子,在查詢語句中,查詢的表應該寫實際的表名字(包括前綴)。
小技巧
原生 SQL 查詢需要在查詢語句中寫上對應的表名,如果表名有改動的時候,就需要逐行去更改 SQL 語句中的表名字,這樣不免麻煩。ThinkPHP 提供了一個小技巧來幫助解決這個問題。
在 SQL 語句中,以 __TABLE__ 來替代真實的表名,而在實例化模型時,仍以表名為參數,如:
系統在解析的時候會自動替換成當前模型對應的表名,這樣就可以做到即使表名有所變化,只需修改實例化對應的表名即可而不用修改原生的 SQL 語句。
query():用于 SQL 查詢操作,并返回符合查詢條件的數據集
execute():更新和寫入數據的 SQL 操作,返回影響的記錄數
query()
query() 方法是用于 SQL 查詢操作,和select()方法一樣返回符合查詢條件的數據集。
例子:
- public?function?read(){?
- ?
- $Dao?=?M();?
- ?
- ?
- $list?=?$Dao->query("select?*?from?user?where?uid<5");?
- if($list){?
- $this->assign('list',?$list?);?
- $this->display();?
- }?else?{?
- $this->error($Dao->getError());?
- }?
- }
對于 query() 方法返回的數據集,跟 select() 一樣,可以在模板里直接循環輸出。
execute()
execute() 方法用于更新和寫入數據的 SQL 操作(注:非查詢操作,無返回數據集),返回影響的記錄數。
例子:
- public?function?read(){?
- header("Content-Type:text/html;?charset=utf-8");?
- ?
- $Dao?=?M();?
- ?
- ?
- $num?=?$Dao->execute("update?user?set?email?=?'12345@xxx.com'?where?uid=3");?
- if($num){?
- echo?'更新?',$num,'?條記錄。';?
- }else{?
- echo?'無記錄更新';?
- }?
- }
如果查詢比較復雜或一些特殊的數據操作不能通過 ThinkPHP 內置的 ORM 和 ActiveRecord 模式實現時,就可以通過直接使用原生 SQL 查詢來實現。
注意:以上都是 user 沒有表前綴的例子,在查詢語句中,查詢的表應該寫實際的表名字(包括前綴)。
小技巧
原生 SQL 查詢需要在查詢語句中寫上對應的表名,如果表名有改動的時候,就需要逐行去更改 SQL 語句中的表名字,這樣不免麻煩。ThinkPHP 提供了一個小技巧來幫助解決這個問題。
在 SQL 語句中,以 __TABLE__ 來替代真實的表名,而在實例化模型時,仍以表名為參數,如:
- public?function?read(){?
- $Dao?=?M("User");?
- $list?=?$Dao->query("select?__TABLE__?from?user?where?uid<5");?
- ?
- }
系統在解析的時候會自動替換成當前模型對應的表名,這樣就可以做到即使表名有所變化,只需修改實例化對應的表名即可而不用修改原生的 SQL 語句。