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

        
        
    
推荐阅读
  • 基于函数实现的进制转换工具
    本文介绍了一种利用函数实现不同进制数(二进制、八进制、十进制)之间转换的方法。包括了程序的运行效果展示、所使用的主要函数解析、以及如何验证用户输入的合法性。整个项目仅使用了两个全局变量来存储用户的选项和输入的数值。 ... [详细]
  • CSGO
    CSGOTimeLimit:40002000MS(JavaOthers)MemoryLimit:524288524288K(JavaOthers)ProblemDescriptio ... [详细]
  • CGroups: 资源管理和控制
    CGroups(Control Groups)是Linux内核提供的一个功能,旨在限制、记录和隔离进程组使用的物理资源,如CPU、内存和I/O等。它通过精细的资源管理,支持现代容器技术如Docker的资源限制需求。 ... [详细]
  • Kafka 示例项目中 Log4j 的配置与调试
    本文详细介绍了如何在 Kafka 源码中的示例项目配置 Log4j,以确保能够正确记录日志信息,帮助开发者更好地理解和调试代码。 ... [详细]
  • Django框架的使用教程mysql数据库[三]
    Django的数据库1.在Django_test下的view.py里面model定义模型fromdjango.dbimportmodels#Createyourmodelshere ... [详细]
  • Elasticsearch基础操作指南:使用Postman进行数据管理
    本文将介绍如何利用Postman工具执行基本的日志写入和数据管理操作。通过本教程,您将了解如何连接至Elasticsearch服务,创建索引,存储及检索数据。 ... [详细]
  • 统计报表模板及其实现方法
    本文介绍两个实用的统计报表模板,并提供如何将这些静态模板转换为动态JSP页面的方法。同时,文中附上了详细的代码示例。 ... [详细]
  • Shiro功能拓展:登录失败重试次数限制
    本文详细介绍了如何在Apache Shiro框架中实现对用户登录失败重试次数的限制,通过自定义密码匹配器来增强系统的安全性。该方法不仅能够有效防止暴力破解攻击,还能确保合法用户的账户安全。 ... [详细]
  • 致信息安全爱好者的成长指南
    本文旨在为信息安全爱好者提供一份详尽的成长指南,涵盖从学习心态调整到具体技能提升的各个方面。 ... [详细]
  • 本文探讨了为何采用RESTful架构及其优势,特别是在现代Web应用开发中的重要性。通过前后端分离和统一接口设计,RESTful API能够提高开发效率,支持多种客户端,并简化维护。 ... [详细]
  • 本文详细探讨了在Windows Server 2003环境下遇到MySQL连接失败(错误代码10061)的解决方案,包括通过卸载特定的Windows更新和调整系统注册表设置的方法。 ... [详细]
  • 前端监控系列2 | 深入探讨JS错误监控的重要性与实践
    作者:彭莉,火山引擎APM研发工程师,专注于前端监控技术的研发。本文将深入讨论JS错误监控的必要性及其实现方法,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 深度解析:任务宝裂变营销的成功之道
    任务宝裂变作为一种高效用户增长手段,在微信生态下被广泛应用。本文将通过实际案例,探讨如何设计和实施任务宝裂变策略,以实现持续获客的目标。 ... [详细]
  • 本文介绍了一种通过自定义工具类实现Spring的ApplicationContextAware接口来获取Spring容器中Bean的方法,并提供了详细的代码示例和配置说明。 ... [详细]
  • Python与MySQL交互指南:从基础到进阶
    本文深入探讨了Python与MySQL数据库的集成方法,包括数据库连接、数据表创建、索引管理、数据操作以及如何防止SQL注入等关键内容。适合初学者及希望提升数据库操作技能的开发者。 ... [详细]
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社区 版权所有