热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CakePHP2.xCookBook中文版第七章模型之检索数据

如果需要对查询有更多控制,可以使用预处理语句。它允许你直接与数据库驱动对话,并且传递任何你需要的自定义查询:

检索数据

如前所述,模型层的一个角色是从多种存储中获取数据。 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 
            var cpro_id = "u6885494";

        
        
    
推荐阅读
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • 程序员妻子吐槽:丈夫北漂8年终薪3万,存款情况令人意外
    一位程序员的妻子在网上分享了她丈夫在北京工作八年的经历,月薪仅3万元,存款情况却出乎意料。本文探讨了高学历人才在大城市的职场现状及生活压力。 ... [详细]
  • 在 Windows 10 中,F1 至 F12 键默认设置为快捷功能键。本文将介绍几种有效方法来禁用这些快捷键,并恢复其标准功能键的作用。请注意,部分笔记本电脑的快捷键可能无法完全关闭。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
  • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 如何在PHPcms网站中添加广告
    本文详细介绍了在PHPcms网站后台添加广告的方法,涵盖多种常见的广告形式,如百度广告和Google广告,并提供了相关设置的步骤。同时,文章还探讨了优化网站流量的SEO策略。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 在哈佛大学商学院举行的Cyberposium大会上,专家们深入探讨了开源软件的崛起及其对企业市场的影响。会议指出,开源软件不仅为企业提供了新的增长机会,还促进了软件质量的提升和创新。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
author-avatar
打杂大叔_868
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有