- 浏览: 849009 次
- 性别:
- 来自: lanzhou
文章分类
最新评论
-
liu346435400:
楼主讲了实话啊,中国程序员的现状,也是只见中国程序员拼死拼活的 ...
中国的程序员为什么这么辛苦 -
qw8226718:
国内ASP.NET下功能比较完善,优化比较好的Spacebui ...
国内外开源sns源码大全 -
dotjar:
敢问兰州的大哥,Prism 现在在12.04LTS上可用么?我 ...
最佳 Ubuntu 下 WebQQ 聊天体验 -
coralsea:
兄弟,卫星通信不是这么简单的,单向接收卫星广播信号不需要太大的 ...
Google 上网 -
txin0814:
我成功安装chrome frame后 在IE地址栏前加上cf: ...
IE中使用Google Chrome Frame运行HTML 5
Introducing the Db_Iterator Object
The getCommentList() method in the User class returns a Db_Iterator instance that holds a result set to the list of comments created by that User. getCommentList() uses Lazy Loading, a method to only load up the comments when necessary (i.e., the first time getCommentList() is called, rather than on object construction). Looking at the Db_Iterator object (with kind thanks to the original implementer, Trevor Andreas), one can see that it stores the result object as a private member variable.
<?php /** * Creates a new Db Iterator object. Allows for fast and memory efficient * handling of a lot of rows that correspond to an object. * @author tandreas <tandreas@gmail.com> * @author vmc <vmc@leftnode.com> */ class Db_Iterator implements Iterator { ///< The result set from the database. private $_result = NULL; ///< The object/model that is built on each iteration. private $_object = NULL; ///< The current row. private $_key = 0; /** * The default constructor to build a new Iterator. * @author tandreas <tandreas@gmail.com> * @param $result The result object. * @param $object An empty object. * @retval Object Returns a new Db_Iterator object. */ public function __construct(Artisan_Db_Result $result, $object) { $this->_result = $result; $this->_object = $object; $this->_key = 0; } /** * Destructs the iterator and frees the result set if its not null. * @author vmc <vmc@leftnode.com> * @retval NULL Returns NULL. */ public function __destruct() { $this->_object = NULL; if ( NULL !== $this->_result ) { $this->_result->free(); $this->_result = NULL; } } /** * Destructs the iterator and frees the result set if its not null. * @author vmc <vmc@leftnode.com> * @param $data Sets the data of the object through loadFromArray(). * @retval Object Returns the object for easy write access. */ public function set($data) { if ( true === is_array($data) ) { $this->_object->loadFromArray($data); } return $this->_object; } /** * Returns the current element. * @author tandreas <tandreas@gmail.com> * @retval Object Returns the current element of the iteration list. */ public function current() { return $this->_load($this->_key); } /** * Returns the last row. * @author tandreas <tandreas@gmail.com> * @retval Object Returns the last row. */ public function last() { $num_rows = $this->_result->numRows()-1; return $this->_load($num_rows); } /** * Returns the key of the current element. * @author tandreas <tandreas@gmail.com> * @retval int Returns the integer key of the current element. */ public function key() { return $this->_key; } /** * Moves to the next element. * @author tandreas <tandreas@gmail.com> * @retval int Returns the next key's value. */ public function next() { $this->_key++; return $this->_key; } /** * Rewinds to the first row of the result. * @author tandreas <tandreas@gmail.com> * @retval boolean Returns true. */ public function rewind() { $this->_key = 0; $this->_result->row(0); return true; } /** * Determines if the next() or current() calls are valid. * @author tandreas <tandreas@gmail.com> * @author vmc <vmc@leftnode.com> * @retval bool Returns true if they are valid, false otherwise. */ public function valid() { return ( $this->_key != $this->_result->numRows() ); } /** * Loads up the specified object during iteration. * @author vmc <vmc@leftnode.com> * @param $i The key/index to load from. * @retval Object Returns the built object. */ private function _load($i) { $this->_result->row($i); $row = $this->_result->fetch(); if ( true === is_array($row) ) { $this->_object->loadFromArray($row); } return $this->_object; } }
When initially building this, the largest problem faced was the desire to not have each iteration require a new query to load up that object. To us, that defeated the entire reason for the class as it required a database call on each iteration when a single one could be made instead. The decision to add the set() method, and corresponding loadFromArray() method was made. On each iteration, loadFromArray() is called in _load() to set the data from the row to the object. In turn, loadFromArray() identifies the primary key of the object, id, and the rest of the data as the model. This is a very fast way to load up an object without the use of another query.
In addition to loadFromArray(), set() can be used to add new elements to the list. Because set() returns an instance of the object originally passed into the Db_Iterator instance, one can immediately call write() on the returned object to write it to the datastore. Furthermore, if the $comment_data array has a valid id entry, the object will be updated rather than inserted. This creates a very easy interface for adding and updating new objects from a single point of entry.
Implementation
Testing this implementation is simple and intuitive.
<?php require_once 'Object/LN.php'; require_once 'Object/Model.php'; require_once 'Object/Iterator.php'; require_once 'Object/User.php'; require_once 'Object/Comment.php'; require_once 'Artisan/Db/Adapter/Mysqli.php'; require_once 'Artisan/Config/Array.php'; require_once 'Artisan/Functions/Array.php'; /** * Set up some database configuration data. */ $config_db = new Artisan_Config_Array(array( 'server' => 'localhost', 'username' => 'username', 'password' => 'password', 'database' => 'iterator_test', 'debug' => false ) ); LN::init($config_db); /** * Create a new User object, and load up all of the comments * user ID #1 has made. */ $user = new User(1); $comment_list = $user->getCommentList(); /** * Loop through all of the comments. $comment is an object of type * User_Comment. */ foreach ( $comment_list as $comment ) { echo $comment . '<br>'; } /** * Insert a new comment. $comment_data could easily come from a form submission. * If there was a field name 'id' in the array below, and it had a valid ID, * the comment would be updated rather than inserted when write() is called. */ echo '<br>'; echo 'Adding a new comment....<br>'; $comment_data = array( 'from_id' => 1, 'to_id' => 2, 'comment' => 'thanks for the reply, @joeperry!' ); $comment_list = $user->getCommentList()->set($comment_data)->write(); /** * Force a reload of the comments. true must be passed to the method. */ echo '<br>'; echo 'Reloading the comments....<br><br>'; $comment_list = $user->getCommentList(true); foreach ( $comment_list as $comment ) { echo $comment . '<br>'; } echo '<hr>'; echo round((memory_get_peak_usage()/(1024*1024)), 4) . 'MB'; LN::cleanup();
Final Questions
Using this overall solution begs a question: what happens on the datastore’s end when holding a result set in memory during the page execution. Fortunately, not much. The Db_Iterator class handles the result set variable. PHP uses copy-on-write for its variable’s value, and because the result variable is never written to, the variable that’s passed into the Db_Iterator instance is destroyed by the iterator’s destructor.
Conclusion
The initial implementation is very trivial. Further applications exist for the iterator, such as filtering results and easy pagination. Using these methods, developers can quickly and easily manage their objects from a central object. This technique was used extensively in the Prospect Vista project. Similar to this article, a single User object controls many different iterators of children objects the User object had created. For example, one User type can create: Comments, Contacts, Fans, Payments, Statistics, Statuses, and Videos. With this code, loading up a list of Contacts is as simple as: $user->getContactList().
Iterators are a very powerful and surprisingly simple way to reconfigure your application. One can cut down on the amount of SQL queries executed and the total memory used, and clean up the design of their classes with little effort. The code in this article was adopted from Artisan System, Leftnode’s PHP5 framework.
发表评论
-
Creating PDF documents with PHP in 10 steps
2009-11-09 08:33 1608Step 1 - Install the PDFlib e ... -
26 Hints for Agile Software Development
2009-11-04 08:04 739I collect nuggets of wisdom on ... -
40个迹象表明你还是PHP菜鸟
2009-10-28 08:40 60340个迹象表明你还是PHP菜鸟 ... -
PHP performance tips
2009-10-21 09:15 740PHP performance tips Author: ... -
国外优秀开源PHP建站程序一览
2009-10-15 08:06 1329大量的PHP开源(开放源 ... -
十步让你成为一名优秀的Web开发人员
2009-10-15 08:03 843第一步:学好HTML HTML( ... -
What's Agile To You?
2009-10-09 08:34 791As a project manager, archite ... -
install Merb 1.0 on Windows
2009-10-05 17:25 924早期的Merb在Windows上安装是件很恶心的事,缺这少 ... -
WebWork敏捷开发尝试
2009-10-05 09:11 790WebWork是一个优秀的J2EE ... -
敏捷开发中常见的九大误解
2009-10-05 09:10 764一、敏捷是“一个” ... -
浅谈敏捷项目管理在软件开发中的应用
2009-10-05 09:09 1195一、使用传统项目管理技术管理软件开发项目的方法 按照 ... -
揭示PHP成功背后的秘密:PHP创始人访谈录
2009-10-01 12:47 919Rasmus Lerdorf可能是格陵兰最著名的电脑牛人,他1 ... -
GitHub: Speed matters
2009-09-29 22:25 868Impressions from the first arti ... -
PHP5 Database Iterators <1>
2009-09-29 22:11 883One feature of PHP rarely seen ... -
REST-*组织
2009-09-29 11:10 849JBoss已在月初的JBoss世界大会上正式宣布了它的新项 ... -
Agile 2009 Conference Retrospective
2009-09-26 21:51 817A month has passed since Agile ... -
Bill Burke Discusses REST-*, SOA/ROA and REST
2009-09-26 21:49 980InfoQ's recent post on REST-* ... -
git is great 2
2009-09-26 15:11 1477Git梳妆我们可以利用Git的config命令或者直接编辑~/ ... -
git is great
2009-09-26 15:08 1666Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重 ... -
FindBugs 1.3.9发布了
2009-09-26 08:03 1379由马里兰大学Bill Pugh教 ...
相关推荐
各种函数以及库文件的...Ended Queues <br>C++ Lists <br>C++ Priority Queues <br>C++ Queues <br>C++ Stacks <br>C++ Sets <br>C++ Multisets <br>C++ Maps <br>C++ Multimaps <br>C++ Bitsets <br>Iterators <br>
12.zip<br>Winsock2 Internet functions <br>Winsock 2.0网络函数(5KB)<END><br>90,13.zip<br>Get hostname and ip address of local computer<br>得到本地计算机的主机名和IP地址(4KB)<END><br>91,14.zip<br>Mail ...
The 80x86 MOV Instruction<br>4.8 - Some Final Comments on the MOV Instructions<br><br>4.9 Laboratory Exercises<br>4.9.1 The UCR Standard Library for 80x86 Assembly Language Programmers<br>4.9.2 ...
通用工具<br>5.Standard Template Library(STL,标准模板库)<br>6.STL容器(STL Container)<br>7.STL 迭代器(STL Iterators)<br>8.STL 仿函数(functors)(又名函数对象,function objects)<br>9.STL算法...
<br> <br> What you'll learn:<br> - How C# works with and exploits the CLR<br> - How to use arrays, collections, and iterators<br> - How to handle events with delegates and anonymous functions<br> - ...
Input/Output Using Stream Classes<br/><br/>13.1 Common Background of I/O Streams<br/><br/>13.2 Fundamental Stream Classes and Objects<br/><br/>13.3 Standard Stream Operators << and >><br/><br/>13.4 ...
(case=9436) <br>STL list<> and vector<> member lists appear correctly following a "using namespace std::list" or "using namespace std::vector" directive. (case=12345) 7226 <br>Empty C++ preprocessor ...
STL容器部分主要由头文件<vector>、<list>、<deque>、<set>、< map>、<stack>和<queue>组成。 (2)算法(Algorithms)。包括各种基本算法,如比较、交换、查找、排序、遍历操作、复制、修改、移除、反转、合并...
list<int> numbers = {1, 2, 3, 4, 5}; auto it = numbers.begin(); advance(it, 2); // 移动迭代器到第三个元素 numbers.erase(it); for (int n : numbers) { cout << n << " "; } cout << endl; return...
部分内容部分介绍了C++标准库中包含的头文件和功能模块,其中包括了常用的<array>、<iostream>、<string>等,这些都是构建C++程序不可或缺的部分。文档提及了算法(Algorithm)、分配器(Allocators)、迭代器...
2. **容器**:这部分在`<vector>`, `<list>`, `<set>`, `<map>`等头文件中定义,提供了一种组织和管理数据的方式。例如,`std::vector`是一个动态数组,而`std::list`则是一个双向链表。 3. **迭代器(Iterators)*...
std::vector<int> numbers = {1, 2, 3, 4, 5}; std::vector<int>::iterator it; // 输出所有元素 for (it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << " "; } std::cout << std::...
2. 标准模板库(STL):STL是C++标准库的核心,包含四个主要组件:算法(algorithms)、容器(containers)、迭代器(iterators)和函数对象(function objects)。例如,`vector`、`list`、`map`等容器提供动态数组、链表和...
public RotateIterator(List<Iterator<T>> iterators) { this.iterators = iterators; } @Override public boolean hasNext() { while (currentIteratorIndex < iterators.size()) { if (iterators.get...
- 容器适配器(Container Adapters):例如`<stack>`、`<queue>`和`<priority_queue>`,它们是基于其他容器的特殊版本,提供了特定的操作行为,如先进先出(FIFO)或优先级排序。 3. 迭代器(Iterators): 迭代...
目录 CSV阅读器# include < csv2>int main () { csv2::Reader<delimiter>, quote_character< ' " ' >, first_row_is_header< true>, trim_policy::trim_whitespace> csv; if (csv. mmap ( " foo.csv " )) { const...
2. **实现迭代器**:创建一个类,实现 `IEnumerator` 或 `IEnumerator<T>` 接口。你需要实现 `Current` 属性、`MoveNext` 方法和 `Reset` 方法。通常,迭代器还需要一个构造函数,接收聚合对象的引用,以便在迭代...
<LASTNAME>Whitman2</LASTNAME> </ITEM> </ELEMENT> </ROOTNODE> ``` ##### 2. 解析XML 解析XML是指将XML文档转换为计算机可读的数据结构,以便进行进一步处理。解析XML的方法主要有两种: - **基于DOM ...
5. **HashSet<T>**:无序且不允许重复元素的集合,适合快速查找和插入操作。 6. **Dictionary<TKey, TValue>**:键值对集合,用于存储具有唯一键的对象。它提供了快速的查找和访问速度。 7. **Queue<T>**:FIFO...
STL的核心组件包括容器(containers)、迭代器(iterators)、函数对象(functors)和算法(algorithms)。在这个主题中,我们将深入探讨vector、list、map、set和deque这五个主要的STL容器,并通过具体的例子和PPT...