热门标签 | 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";

        
        
    
推荐阅读
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
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社区 版权所有