檢索數據 如前所述,模型層的一個角色是從多種存儲中獲取數據。 CakePHP 模型類帶有很多功能,幫助你搜索這些數據,排序,分頁並且進行過濾。你將要使用的很多功能集成於模型的 Model::find() find find(string $type = 'first', array $params = array()) Find 是所有模型數據檢索功能的主力。 $type 可以是 'all', 'first', 'count', 'list', 'neighbors', 'threaded'或者任何自定義查找類型。 切記,$type 是區分大小寫的。 使用大寫字母(例如 All)將得不到期望的結果。 $params 用於向不同的 find 傳遞所有的參數,其默認有如下的鍵值 - 每一個都是可選的: 1 array( 2 'conditions' => array('Model.field' => $thisValue), //array of conditions 3 'recursive' => 1, //int 4 'fields' => array('Model.field1', 'DISTINCT Model.field2'), //array of field names 5 'order' => array('Model.created', 'Model.field3 DESC'), //string or array defining order 6 'group' => array('Model.field'), //fields to GROUP BY 7 'limit' => n, //int 8 'page' => n, //int 9 'offset' => n, //int 10 'callbacks' => true //other possible values are false, 'before', 'after' 11 ) 也可以添加和使用其它的參數,提供給一些查找類型、行為以及你自己的模型方法。 find(‘first’) find('first', $params) 返回一個結果,你可以在任何期望獲得一個結果的情況下使用它。 下面是幾個簡單的(控制器代碼)示例: 1 public function some_function() { 2 // ... 3 $semiRandomArticle = $this->Article->find('first'); 4 $lastCreated = $this->Article->find('first', array( 5 'order' => array('Article.created' => 'desc') 6 )); 7 $specificallyThisOne = $this->Article->find('first', array( 8 'conditions' => array('Article.id' => 1) 9 )); 10 // ... 11 } 在第一個示例中,沒有向 find 傳遞任何參數 - 所以沒有任何條件和排序。這種形式的 find('first') 調用返回的格式如下: 1 Array 2 ( 3 [ModelName] => Array 4 ( 5 [id] => 83 6 [field1] => value1 7 [field2] => value2 8 [field3] => value3 9 ) 10 11 [AssociatedModelName] => Array 12 ( 13 [id] => 1 14 [field1] => value1 15 [field2] => value2 16 [field3] => value3 17 ) 18 ) find(‘count’) find('count', $params) 返回一個整數值。下面是幾個簡單的(控制器代碼)示例: 1 public function some_function() { 2 // ... 3 $total = $this->Article->find('count'); 4 $pending = $this->Article->find('count', array( 5 'conditions' => array('Article.status' => 'pending') 6 )); 7 $authors = $this->Article->User->find('count'); 8 $publishedAuthors = $this->Article->find('count', array( 9 'fields' => 'DISTINCT Article.user_id', 10 'conditions' => array('Article.status !=' => 'pending') 11 )); 12 // ... 13 } 注解 不要向 find('count') 傳遞 fields 數組。你只能為 DISTINCE count 指定列(其它情況下,計數結果總是相同的 - 僅取決於條件)。 find(‘all’) find('all', $params) 返回一個數組(可能有多個)結果。 實際上,它是全部 find() 的變體(包括分頁)。下面是幾個簡單的(控制器代碼)示例: 1 public function some_function() { 2 // ... 3 $allArticles = $this->Article->find('all'); 4 $pending = $this->Article->find('all', array( 5 'conditions' => array('Article.status' => 'pending') 6 )); 7 $allAuthors = $this->Article->User->find('all'); 8 $allPublishedAuthors = $this->Article->User->find('all', array( 9 'conditions' => array('Article.status !=' => 'pending') 10 )); 11 // ... 12 } 注解 上面的例子中, $allAuthors 將包含 users 表的每個用戶。沒有要應用的條件被傳遞給那個 find。 調用 find('all') 的結果格式如下: 1 Array 2 ( 3 [0] => Array 4 ( 5 [ModelName] => Array 6 ( 7 [id] => 83 8 [field1] => value1 9 [field2] => value2 10 [field3] => value3 11 ) 12 13 [AssociatedModelName] => Array 14 ( 15 [id] => 1 16 [field1] => value1 17 [field2] => value2 18 [field3] => value3 19 ) 20 21 ) 22 ) find(‘list’) find('list', $params) 返回一個索引數組,用在想要一個用於類似 HTML 輸入表單中的 select 元素所需的列表的場合。下面是幾個簡單的(控制器代碼)示例: 1 public function some_function() { 2 // ... 3 $allArticles = $this->Article->find('list'); 4 $pending = $this->Article->find('list', array( 5 'conditions' => array('Article.status' => 'pending') 6 )); 7 $allAuthors = $this->Article->User->find('list'); 8 $allPublishedAuthors = $this->Article->find('list', array( 9 'fields' => array('User.id', 'User.name'), 10 'conditions' => array('Article.status !=' => 'pending'), 11 'recursive' => 0 12 )); 13 // ... 14 } 注解 上面的例子中, $allAuthors 將包含 users 表的每個用戶。沒有要應用的條件被傳遞給那個 find。 調用 find('list') 的結果格式如下: 1 Array 2 ( 3 //[id] => 'displayValue', 4 [1] => 'displayValue1', 5 [2] => 'displayValue2', 6 [4] => 'displayValue4', 7 [5] => 'displayValue5', 8 [6] => 'displayValue6', 9 [3] => 'displayValue3', 10 ) 當調用 find('list') 時,傳遞的 fields 參數用於決定使用什麼做數組的鍵、值和(可選的)結果的分組。默認情況下,模型的主鍵被當作鍵,顯示列用作值(可以用模型的 displayField) 屬性配置) 一些清晰的示例: 1 public function some_function() { 2 // ... 3 $justusernames = $this->Article->User->find('list', array( 4 'fields' => array('User.username') 5 )); 6 $usernameMap = $this->Article->User->find('list', array( 7 'fields' => array('User.username', 'User.first_name') 8 )); 9 $usernameGroups = $this->Article->User->find('list', array( 10 'fields' => array('User.username', 'User.first_name', 'User.group') 11 )); 12 // ... 13 } 在上面的例子中,結果變量類似下面這樣: 1 $justusernames = Array 2 ( 3 //[id] => 'username', 4 [213] => 'AD7six', 5 [25] => '_psychic_', 6 [1] => 'PHPNut', 7 [2] => 'gwoo', 8 [400] => 'jperras', 9 ) 10 11 $usernameMap = Array 12 ( 13 //[username] => 'firstname', 14 ['AD7six'] => 'Andy', 15 ['_psychic_'] => 'John', 16 ['PHPNut'] => 'Larry', 17 ['gwoo'] => 'Gwoo', 18 ['jperras'] => 'Joël', 19 ) 20 21 $usernameGroups = Array 22 ( 23 ['User'] => Array 24 ( 25 ['PHPNut'] => 'Larry', 26 ['gwoo'] => 'Gwoo', 27 ) 28 29 ['Admin'] => Array 30 ( 31 ['_psychic_'] => 'John', 32 ['AD7six'] => 'Andy', 33 ['jperras'] => 'Joël', 34 ) 35 36 ) find(‘threaded’) find('threaded', $params) 返回一個嵌套數組,如果你想使用模型數據的 parent_id 列建立相應的嵌套結果。下面是幾個簡單的(控制器代碼)示例: 1 public function some_function() { 2 // ... 3 $allCategories = $this->Category->find('threaded'); 4 $comments = $this->Comment->find('threaded', array( 5 'conditions' => array('article_id' => 50) 6 )); 7 // ... 8 } 小技巧 處理嵌套數據的更好的方法是使用 樹 行為 在上面的例子中,$allCategories 將包含一個呈現整個分類結構的嵌套數組。調用 find('threaded') 的結果格式如下: 1 Array 2 ( 3 [0] => Array 4 ( 5 [ModelName] => Array 6 ( 7 [id] => 83 8 [parent_id] => null 9 [field1] => value1 10 [field2] => value2 11 [field3] => value3 12 ) 13 14 [AssociatedModelName] => Array 15 ( 16 [id] => 1 17 [field1] => value1 18 [field2] => value2 19 [field3] => value3 20 ) 21 22 [children] => Array 23 ( 24 [0] => Array 25 ( 26 [ModelName] => Array 27 ( 28 [id] => 42 29 [parent_id] => 83 30 [field1] => value1 31 [field2] => value2 32 [field3] => value3 33 ) 34 35 [AssociatedModelName] => Array 36 ( 37 [id] => 2 38 [field1] => value1 39 [field2] => value2 40 [field3] => value3 41 ) 42 43 [children] => Array 44 ( 45 ) 46 ) 47 ... 48 ) 49 ) 50 ) 結果呈現的順序是可以改變的,因為它受 order 處理的影響。如果將 'order' => 'name ASC' 作為參數傳遞給find('threaded'),其結果將按 name 排序。類似於此的所有 order 都能被使用,此方法沒有內置的首次返回的頂層結果的順序。 警告 如果指定了 fields,就必須包含 parent_id (或者它的當前別名): 1 public function some_function() { 2 $categories = $this->Category->find('threaded', array( 3 'fields' => array('id', 'name', 'parent_id') 4 )); 5 } 否則,上面例子中返回的數組將不是預期的嵌套結構。 find(‘neighbors’) find('neighbors', $params) 執行與 ‘first’ 相同的查找,但返回的是所請求的前一行和後一行。下面是一個簡單的(控制器代碼)示例: : 1 public function some_function() { 2 $neighbors = $this->Article->find('neighbors', array('field' => 'id', 'value' => 3)); 3 } 本例中 $params 數組包含兩個元素:field 和 value。所有的 find 中的其它元素仍然可用(例如:如果模型可包含,可以在 $params 指定 ‘包含’)。調用 find('neighbors') 的結果格式如下: 1 Array 2 ( 3 [prev] => Array 4 ( 5 [ModelName] => Array 6 ( 7 [id] => 2 8 [field1] => value1 9 [field2] => value2 10 ... 11 ) 12 [AssociatedModelName] => Array 13 ( 14 [id] => 151 15 [field1] => value1 16 [field2] => value2 17 ... 18 ) 19 ) 20 [next] => Array 21 ( 22 [ModelName] => Array 23 ( 24 [id] => 4 25 [field1] => value1 26 [field2] => value2 27 ... 28 ) 29 [AssociatedModelName] => Array 30 ( 31 [id] => 122 32 [field1] => value1 33 [field2] => value2 34 ... 35 ) 36 ) 37 ) 注解 注意,結果總是只包含兩個根元素: prev 和 next。此功能不兌現模型默認的遞歸變量。遞歸設置必須以參數形式傳遞給每個需要的調用。 創建自定義 find 類型 find 方法很靈活,能夠接受自定義查找,這是通過在模型變量中定義自己的類型並在模型類中實現特定的函數完成的。 模型的 find 類型是 find 選項的快捷方式。例如,如下兩種查找是相同的: 1 $this->User->find('first'); 1 $this->User->find('all', array('limit' => 1)); 以下是內核中預定義的類型: first all count list threaded neighbors 那麼其它的類型呢?以在數據庫中查找所有的發布文章為例。每一個改變是在模型中的 Model::$findMethods 變量中添加類型: 1 class Article extends AppModel { 2 public $findMethods = array('available' => true); 3 } 這是在通知 CakePHP 接受值 available 作為 find 函數的第一個參數。 第二步是實現 _findAvailable 函數。 這是一個約定,如果想實現一個叫做 myFancySearch 的查找就需要實現一個叫做 _findMyFancySearch 方法。 1 class Article extends AppModel { 2 public $findMethods = array('available' => true); 3 4 protected function _findAvailable($state, $query, $results = array()) { 5 if ($state == 'before') { 6 $query['conditions']['Article.published'] = true; 7 return $query; 8 } 9 return $results; 10 } 11 } 下面是完整的示例(控制器代碼): 1 class ArticlesController extends AppController { 2 3 // Will find all published articles and order them by the created column 4 public function index() { 5 $articles = $this->Article->find('available', array( 6 'order' => array('created' => 'desc') 7 )); 8 } 9 10 } 上面展示的代碼中特定的 _find[Type] 方法接收3個參數。第一個意指查詢執行在什麼處於狀態時執行,可以是before 或 after。 這是因為此函數是這樣一種回調函數:有能力在完成前編輯查詢,或者在獲取結果後對結果進行編輯。 通常第一件事是檢查 find 函數的查詢狀態。 before 狀態是編輯查詢、綁定新的關聯、應用更多的行為、解釋傳遞給find 的第二個參數的那些特殊鍵的時候。此狀態需要返回 $query 參數(修改或不修改)。 after 狀態是檢查結果、注入新數據、計算並以另一種格式返回它,或者在最近返回的數據上做任何你愛做的事。此狀態需要返回 $result 數組(修改或不修改)。 可以創建任意多你喜歡的自定義查找,這也是在應用程序中跨越模型征用代碼的好辦法。 還可以通過如下類型的自定義對查找進行分頁: 1 class ArticlesController extends AppController { 2 3 // 將對全部發表的文章進行分頁 4 public function index() { 5 $this->paginate = array('available'); 6 $articles = $this->paginate(); 7 $this->set(compact('articles')); 8 } 9 10 } 像上面這樣設置控制器中的 $this->paginate 屬性將導致 find 的 type 變成 available,並且還允許你繼續修改查找的結果。 如果分頁計數出現錯誤,可能需要向 AppModel 添加如下代碼,它可以糾正分頁計數: 1 class AppModel extends Model { 2 3 /** 4 * 如果自定義查找的計數查詢中的 'fields' 鍵是一個數組的話,就刪除它, 5 * 因為它將徹底破壞 Model::_findCount() 調用 6 * 7 * @param string $state Either "before" or "after" 8 * @param array $query 9 * @param array $results 10 * @return int The number of records found, or false 11 * @access protected 12 * @see Model::find() 13 */ 14 protected function _findCount($state, $query, $results = array()) { 15 if ($state === 'before') { 16 if (isset($query['type']) && isset($this->findMethods[$query['type']])) { 17 $query = $this->{'_find' . ucfirst($query['type'])}('before', $query); 18 if (!empty($query['fields']) && is_array($query['fields'])) { 19 if (!preg_match('/^count/i', current($query['fields']))) { 20 unset($query['fields']); 21 } 22 } 23 } 24 } 25 return parent::_findCount($state, $query, $results); 26 } 27 28 } 29 ?> 在 2.2 版更改. 不再需要為糾正計數結果的錯誤而覆寫 _findCount 了。 自定義查找的 'before' 狀態現在將帶有 $query[‘operation’] = ‘count’ 重新進行調用。返回的 $query 將用在 _findCount() 中。 如果有需要你可以通過檢查 'operation' 鍵來辨別並返回不同的 $query: 1 protected function _findAvailable($state, $query, $results = array()) { 2 if ($state == 'before') { 3 $query['conditions']['Article.published'] = true; 4 if (!empty($query['operation']) && $query['operation'] == 'count') { 5 return $query; 6 } 7 $query['joins'] = array( 8 //array of required joins 9 ); 10 return $query; 11 } 12 return $results; 13 } 魔術查找類型 這些魔術函數是依據特定的列搜索表的快捷方式來使用的。只要向這些函數的末尾添加列名(按照駝峰命名格式), 並提供這些列的規則作為其第一個參數。 findAllBy() 函數返回類似於 find('all') 的返回格式的結果, 而 findBy 返回的格式與 find('first') 相同。 findAllBy findAllBy<fieldName>(string $value, array $fields, array $order, int $limit, int $page, int $recursive) findAllBy<x> 示例 相應的 SQL 片段 $this->Product->findAllByOrderStatus('3'); Product.order_status = 3 $this->Recipe->findAllByType('Cookie'); Recipe.type = 'Cookie' $this->User->findAllByLastName('Anderson'); User.last_name = 'Anderson' $this->Cake->findAllById(7); Cake.id = 7 $this->User->findAllByEmailOrUsername('jhon'); User.email = 'jhon' OR User.username ='jhon'; $this->User->findAllByUsernameAndPassword('jhon', '123'); User.username = 'jhon' ANDUser.password = '123'; $this->User->findAllByLastName('psychic', array(),array('User.user_name => 'asc')); User.last_name = 'psychic' ORDER BYUser.user_name ASC 返回結果數組的格式類似於 find('all') 的返回值格式。 findBy findBy<fieldName>(string $value); findBy 魔術函數也接受一些可選參數: findBy<fieldName>(string $value[, mixed $fields[, mixed $order]]); findBy<x> 示例 相應的 SQL 片段 $this->Product->findByOrderStatus('3'); Product.order_status = 3 $this->Recipe->findByType('Cookie'); Recipe.type = 'Cookie' $this->User->findByLastName('Anderson'); User.last_name = 'Anderson'; $this->User->findByEmailOrUsername('jhon'); User.email = 'jhon' OR User.username = 'jhon'; $this->User->findByUsernameAndPassword('jhon','123'); User.username = 'jhon' AND User.password ='123'; $this->Cake->findById(7); Cake.id = 7 findBy() 函數返回的結果類似於 find('first')。 Model::query() query(string $query) 雖然很少有必要,但如果你不能或不想通過其它方法調用 SQL,就可以直接使用模型的 query() 方法。 如果你真想在應用程序中使用這種方法,請確保你已經閱讀過 CakePHP 的 數據清潔,這有助於清理用戶提供的數據,以防止注入和跨站點腳本攻擊。 注解 query() 不理會 $Model->cacheQueries,因為其功能本質上與調用的模型不相關。為避免緩存調用查詢,需要將第二個參數設置為 false,例如: query($query, $cachequeries = false)。 query() 在查詢中使用表名作為返回數據的數組鍵,而不是模型名。例如: 1 $this->Picture->query("SELECT * FROM pictures LIMIT 2;"); 可能返回如下數組: 1 Array 2 ( 3 [0] => Array 4 ( 5 [pictures] => Array 6 ( 7 [id] => 1304 8 [user_id] => 759 9 ) 10 ) 11 12 [1] => Array 13 ( 14 [pictures] => Array 15 ( 16 [id] => 1305 17 [user_id] => 759 18 ) 19 ) 20 ) 要使用模型名作為數組鍵,以與 find 方法的返回結果一致,可以將查詢寫成: 1 $this->Picture->query("SELECT * FROM pictures AS Picture LIMIT 2;"); 將返回: 1 Array 2 ( 3 [0] => Array 4 ( 5 [Picture] => Array 6 ( 7 [id] => 1304 8 [user_id] => 759 9 ) 10 ) 11 12 [1] => Array 13 ( 14 [Picture] => Array 15 ( 16 [id] => 1305 17 [user_id] => 759 18 ) 19 ) 20 ) 注解 此語法及關聯數組結構僅在 MySQL 中有效。在手動運行查詢時,Cake 不提供任何抽象數據,所以其結果在不同的數據庫中有所不同。 Model::field() field(string $name, array $conditions = null, string $order = null) 返回值只有與 $order 指定的排序條件相匹配的第一條記錄中由 $name 指定的單個列。如果沒有傳遞條件並且模型設置了 id,將返回當前模型結果的列的值。如果沒有匹配的記錄,查找將返回 false。 1 $this->Post->id = 22; 2 echo $this->Post->field('name'); // echo the name for row id 22 3 4 echo $this->Post->field('name', array('created <' => date('Y-m-d H:i:s')), 'created DESC'); 5 // 顯示最後創建的實例的 'name' 列。 Model::read() read($fields, $id) read() 是一個用於設置當前模型數據(Model::$data)的方法 – 例如在編輯過程中 – 但是不能用在從數據庫中獲取單條記錄的其它情況中 $fields 用於傳遞單個列的名字,可以是字符串或者列名數組;如果為空(empty),則獲取所有列。 $id 指定要讀取的記錄的 ID。默認是由 Model::$id 指定的當前選擇的記錄。 傳遞不同的值給 $id 將引起記錄被選擇。 read() 總是返回一個數組(即使僅包含了一個列名)。使用 field 來獲取單個列的值。 警告 由於 read 方法覆寫任何存儲在模型的 data 和 id 屬性中的任何信息,使用此功能是要非常小心,尤其在類似 beforeValidata 和 beforeSave 等模型回調函數中使用的時候。通常 find 方法比 read 方法提供了更強大和易用的 API。 復雜的查找條件 多數模型的 find 調用需要傳遞條件集。通常,CakePHP 使用數組來組合需要放在 SQL 查詢的 WHERE 子句中的條件。 使用數組很整潔且易讀,構建查詢也非常容易。這種語法還打散了查詢中的元素(列、值、操作,等等)。它使 CakePHP 有可能生成更高效的查詢,確保 SQL 語法正確,正確分解查詢的每個獨立的部分。使用數組語法還使 CakePHP 能夠確保查詢避免 SQL 注入攻擊。 基於數組的最基礎的查詢類似於: 1 $conditions = array("Post.title" => "This is a post", "Post.author_id" => 1); 2 // 帶有模型的示例 3 $this->Post->find('first', array('conditions' => $conditions)); 此結構非常簡單:它將查找標題等於 “This is a post” 的帖子。注意,我們可以使用 “title” 作為列的名字,但是在構建查詢時,最好總是指定模型名,因為它提高了代碼的清晰度,有助於在你選擇改變架構時防范沖突。 其它的匹配類型呢?同樣簡單。假設你要查找所有的 title 不是 This is a post 的帖子: 1 array("Post.title !=" => "This is a post") 注意,’!=’ 跟在列的名稱之後。CakePHP 能解析任何有效的 SQL 比較操作符,包括使用 LIKE、BETWEEN、REGEX 的匹配表達式,只要你用空格分隔開列名和操作符。IN(...) 風格的匹配例外。假設你想查找 title 包含在給定的值集合之內的帖子: 1 array( 2 "Post.title" => array("First post", "Second post", "Third post") 3 ) 要執行 NOT IN(...) 匹配查找 title 不在給定的值集之內的帖子: 1 array( 2 "NOT" => array("Post.title" => array("First post", "Second post", "Third post")) 3 ) 為條件添加附加的過濾與向數組添加附加的鍵/值對一樣簡單: 1 array ( 2 "Post.title" => array("First post", "Second post", "Third post"), 3 "Post.created >" => date('Y-m-d', strtotime("-2 weeks")) 4 ) 還可以創建對比數據庫中兩個列的查找: 1 array("Post.created = Post.modified") 上面的例子將返回創建時間和編輯時間相同的帖子(就是指那些從來沒被編輯過的帖子)。 記住,如果你發現自己不能在一個方法中生成 WHERE 子句(例如 邏輯運算),你總能用字符串來指定它: 1 array( 2 'Model.field & 8 = 1', 3 // 其它常用條件 4 ) 默認情況下,CakePHP 使用邏輯 AND 連接多個條件;也就是說,上面的代碼片段僅匹配兩星期前創建的並且標題與給定的集中的某一個匹配的帖子。但是我們也能很容易的找到符合任一條件的帖子: 1 array("OR" => array( 2 "Post.title" => array("First post", "Second post", "Third post"), 3 "Post.created >" => date('Y-m-d', strtotime("-2 weeks")) 4 )) CakePHP 接受所有有效的 SQL 邏輯運算,包括 AND、OR、NOT、XOR 等等,而且不區分大小寫。這些條件還能無限制嵌套。假設 Posts 和 Authors 間有 belongsTo 關系,想要找到所有包含特定關鍵詞(”magic”)或者兩星期前建立的,但僅限於由 Bob 發布的帖子: 1 array( 2 "Author.name" => "Bob", 3 "OR" => array( 4 "Post.title LIKE" => "%magic%", 5 "Post.created >" => date('Y-m-d', strtotime("-2 weeks")) 6 ) 7 ) 如果需要在同一個列上設置多個條件,比如想要執行一個帶有多個條款的 LIKE 搜索,可以使用類似如下的條件: 1 array('OR' => array( 2 array('Post.title LIKE' => '%one%'), 3 array('Post.title LIKE' => '%two%') 4 )) Cake 不能檢查 null 列。在本例中,查詢將返回所有 title 不為 null 的記錄: 1 array("NOT" => array( 2 "Post.title" => null 3 ) 4 ) 要處理 BETWEEN 查詢,可以使用如下條件: 1 array('Post.read_count BETWEEN ? AND ?' => array(1,10)) 注解 CakePHP 將引用的數字值依賴於 DB 的列類型。 GROUP BY?: 1 array( 2 'fields' => array( 3 'Product.type', 4 'MIN(Product.price) as price' 5 ), 6 'group' => 'Product.type' 7 ) 所返回的值格式如下: 1 Array 2 ( 3 [0] => Array 4 ( 5 [Product] => Array 6 ( 7 [type] => Clothing 8 ) 9 [0] => Array 10 ( 11 [price] => 32 12 ) 13 ) 14 [1] => Array 15 ... 下面是執行 DISTINCT 查詢的簡單示例。可以按類似格式使用其它操作符,例如 MIN()、MAX(),等等: 1 array( 2 'fields' => array('DISTINCT (User.name) AS my_column_name'), 3 'order' = >array('User.id DESC') 4 ) 通過嵌套多個條件數組,可以構建非常復雜的條件: 1 array( 2 'OR' => array( 3 array('Company.name' => 'Future Holdings'), 4 array('Company.city' => 'CA') 5 ), 6 'AND' => array( 7 array( 8 'OR' => array( 9 array('Company.status' => 'active'), 10 'NOT' => array( 11 array('Company.status' => array('inactive', 'suspended')) 12 ) 13 ) 14 ) 15 ) 16 ) 其對應的 SQL 查詢為: 1 SELECT `Company`.`id`, `Company`.`name`, 2 `Company`.`description`, `Company`.`location`, 3 `Company`.`created`, `Company`.`status`, `Company`.`size` 4 5 FROM 6 `companies` AS `Company` 7 WHERE 8 ((`Company`.`name` = 'Future Holdings') 9 OR 10 (`Company`.`name` = 'Steel Mega Works')) 11 AND 12 ((`Company`.`status` = 'active') 13 OR (NOT (`Company`.`status` IN ('inactive', 'suspended')))) 子查詢 下面的示例假定我們有一個帶有 “id”,”name” 和 “status” 列的 “users” 表。 status 可以是 “A”、”B”、”C”。並且我們想使用子查詢獲取所有 status 不同於 “B” 的用戶。 為了達到此目的,我們將獲取模型數據源,向其發出請求以建立查詢,就像我們正在調用 find 方法,只不過返回的是一條 SQL 語句。然後,我們生成一個表達式並將其添加到條件數組中: 1 $conditionsSubQuery['"User2"."status"'] = 'B'; 2 3 $db = $this->User->getDataSource(); 4 $subQuery = $db->buildStatement( 5 array( 6 'fields' => array('"User2"."id"'), 7 'table' => $db->fullTableName($this->User), 8 'alias' => 'User2', 9 'limit' => null, 10 'offset' => null, 11 'joins' => array(), 12 'conditions' => $conditionsSubQuery, 13 'order' => null, 14 'group' => null 15 ), 16 $this->User 17 ); 18 $subQuery = ' "User"."id" NOT IN (' . $subQuery . ') '; 19 $subQueryExpression = $db->expression($subQuery); 20 21 $conditions[] = $subQueryExpression; 22 23 $this->User->find('all', compact('conditions')); 生成的 SQL 查詢為: 1 SELECT 2 "User"."id" AS "User__id", 3 "User"."name" AS "User__name", 4 "User"."status" AS "User__status" 5 FROM 6 "users" AS "User" 7 WHERE 8 "User"."id" NOT IN ( 9 SELECT 10 "User2"."id" 11 FROM 12 "users" AS "User2" 13 WHERE 14 "User2"."status" = 'B' 15 ) 另外,如果你需要傳遞上面的原始 SQL 查詢的一部分,帶有原始 SQL 的數據源**表達式**為查詢的任意部分工作。www.2cto.com 預處理語句 如果需要對查詢有更多控制,可以使用預處理語句。它允許你直接與數據庫驅動對話,並且傳遞任何你需要的自定義查詢: 1 $db = $this->getDataSource(); 2 $db->fetchAll( 3 'SELECT * from users where username = ? AND password = ?', 4 array('jhon', '12345') 5 ); 6 $db->fetchAll( 7 'SELECT * from users where username = :username AND password = :password', 8 array('username' => 'jhon','password' => '12345') 9 );