search
Homephp教程php手册CakePHP 2.x CookBook 中文版 第七章 模型 之 检索数据

检索数据

如前所述,模型层的一个角色是从多种存储中获取数据。 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(string $value, array $fields, array $order, int $limit, int $page, int $recursive)

 

findAllBy 示例 相应的 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(string $value);

 

findBy 魔术函数也接受一些可选参数:

 

findBy(string $value[, mixed $fields[, mixed $order]]);

 

findBy 示例 相应的 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

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 );

 

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
如何使用CakePHP中的数据库查询构造器?如何使用CakePHP中的数据库查询构造器?Jun 04, 2023 am 09:02 AM

CakePHP是一个开源的PHPMVC框架,它广泛用于Web应用程序的开发。CakePHP具有许多功能和工具,其中包括一个强大的数据库查询构造器,用于交互性能数据库。该查询构造器允许您使用面向对象的语法执行SQL查询,而不必编写繁琐的SQL语句。本文将介绍如何使用CakePHP中的数据库查询构造器。建立数据库连接在使用数据库查询构造器之前,您首先需要在Ca

如何在CakePHP中创建自定义分页?如何在CakePHP中创建自定义分页?Jun 04, 2023 am 08:32 AM

CakePHP是一个强大的PHP框架,为开发人员提供了很多有用的工具和功能。其中之一是分页,它可以帮助我们将大量数据分成几页,从而简化浏览和操作。默认情况下,CakePHP提供了一些基本的分页方法,但有时你可能需要创建一些自定义的分页方法。这篇文章将向您展示如何在CakePHP中创建自定义分页。步骤1:创建自定义分页类首先,我们需要创建一个自定义分页类。这个

如何使用PHP和CakePHP框架进行应用程序开发如何使用PHP和CakePHP框架进行应用程序开发May 11, 2023 pm 03:39 PM

在当今数字化时代,应用程序对于企业和个人来说,已经成为了不可或缺的一部分。应用程序能够让人们更加便捷地进行各种操作,而PHP和CakePHP框架则是日益流行的应用程序开发工具。在本文中,我们将讨论如何使用PHP和CakePHP框架进行应用程序开发。一、PHP是什么?PHP(外文全称为“HypertextPreprocessor”)是一种开源的服务器端脚本语

如何在CakePHP中使用FPDF?如何在CakePHP中使用FPDF?Jun 03, 2023 pm 06:32 PM

CakePHP是一种流行的PHP框架,用于开发Web应用程序。与许多其他PHP框架一样,CakePHP也提供了许多有用的功能和插件来帮助业务流程,其中包括生成PDF文件。这项任务可以使用FPDF插件轻松完成。本文将介绍如何在CakePHP中使用FPDF。FPDF是一种开源的PHP类库,用于生成PDF文件。它具有许多有用的功能,例如嵌入字体、添加图像、绘制基本

如何在CakePHP中使用Guzzle?如何在CakePHP中使用Guzzle?Jun 03, 2023 pm 01:51 PM

CakePHP是一款优秀的PHP开发框架,它通过提供一系列强大的功能和工具,简化了Web应用程序的开发过程。而Guzzle是一个PHPHTTP客户端和请求库,它能够帮助开发者轻松地发送HTTP请求和访问Web服务。在本文中,我们将介绍如何在CakePHP中使用Guzzle,以便更加高效地开发Web应用程序。一、安装Guzzle首先,我们需要在CakePHP

如何在CakePHP中进行数据查询和更新?如何在CakePHP中进行数据查询和更新?Jun 03, 2023 pm 02:11 PM

CakePHP是一个流行的PHP框架,它提供了方便的ORM(对象关系映射)功能,使得查询和更新数据库变得非常容易。本文将介绍如何在CakePHP中进行数据查询和更新。我们将从简单的查询和更新开始,逐步深入,了解如何使用条件和关联的模型来更复杂地查询和更新数据。基本查询首先,让我们看看如何进行最简单的查询。假设我们有一个名为“Users”的数据表,并且我们想要

如何在CakePHP中使用多个数据库连接?如何在CakePHP中使用多个数据库连接?Jun 04, 2023 am 08:21 AM

CakePHP是一款流行的PHP开发框架,它提供了快速开发Web应用程序所需的基本功能和结构。在现代应用中,使用多个数据库连接已经成为了一个普遍的需求,例如,建立主从数据库连接或将数据分片到不同的数据库中。本文将介绍如何在CakePHP中使用多个数据库连接。CakePHP中的默认数据库连接在开始之前,让我们先了解一下CakePHP中默认的数据库连接。Cake

如何使用CakePHP中的Cookie组件?如何使用CakePHP中的Cookie组件?Jun 03, 2023 pm 06:31 PM

CakePHP是一款流行的PHP框架,它为Web开发提供了许多便利的功能。其中一个非常有用的功能是Cookie组件。在本文中,我们将介绍如何在CakePHP中使用Cookie组件来存储和检索数据。一、什么是Cookie?Cookie是一个小的数据片段,存储在网站上的用户计算机上。它可以用来存储用户喜好、登陆信息和其他相关的数据。Cookie可以被服务器和客户

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version