- 浏览: 849174 次
- 性别:
- 来自: 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
One feature of PHP rarely seen in production code is PHP Iterators. Iterators are not unique to PHP, as Java and C++ have them, but they are a powerful mechanism to increase code usability. A very useful feature of PHP Iterators is the ability to extend them to iterate over any type of array or object. A unique implementation of PHP Iterators is to quickly and easily iterate over a result from a SQL query against a database. This provides a fast and very memory efficient implementation for loading up many objects.
Essentially, with an Iterator, you can use the foreach() loop as opposed the while() loop to load objects. Adding to their power, at each iteration, you can have the iterator load up additional data or do any side processing automatically.
Setting Up The Database Environment
You will need to set your environment up for this article to work properly. First, create a new database, `iterator_test` with two tables, `user` and `user_comment`:
CREATE DATABASE `iterator_test` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; CREATE TABLE `user` ( `id` SMALLINT( 3 ) NOT NULL AUTO_INCREMENT PRIMARY KEY , `email_address` VARCHAR( 255 ) NOT NULL , `firstname` VARCHAR( 64 ) NOT NULL , `lastname` VARCHAR( 64 ) NOT NULL , `age` TINYINT( 1 ) NOT NULL ) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci; CREATE TABLE `user_comment` ( `id` SMALLINT( 3 ) NOT NULL AUTO_INCREMENT PRIMARY KEY, `from_id` SMALLINT( 3 ) NOT NULL , `to_id` SMALLINT( 3 ) NOT NULL , `comment` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci; INSERT INTO `user` (`id`, `email_address`, `firstname`, `lastname`, `age`) VALUES (1, 'vmc@leftnode.com', 'vic', 'cherubini', 25), (2, 'joe@google.com', 'joe', 'perry', 43); INSERT INTO `user_comment` (`id`, `from_id`, `to_id`, `comment`) VALUES (1, 1, 2, 'this is a comment'), (2, 1, 2, 'this is also a comment!'), (3, 2, 1, 'howdy, thanks for contacting me!');
The table `user_comment` will hold a list of comments `from_id` makes to `to_id`. These both point to the `id` field of the `user` table.
Classes and Models
Two classes are needed to manage User’s and User_Comment’s. They will both extend from a base class, Model, that defines some common methods and variables between them.
<?php /** * The abstract Model class that is the base for all other classes * that interact with a datastore. * @author vmc <vmc@leftnode.com> */ abstract class Model { ///< The ID of the object from the datastore. protected $_id = 0; ///< The data as a key-value array of the object. protected $_model = array(); /** * The default constructor of the object. * @author vmc <vmc@leftnode.com> * @param $object_id The optional ID to load from the datastore. * @retval Object Returns a new Model object. */ public function __construct($object_id=0) { $this->_load(intval($object_id)); } /** * Destructor. * @author vmc <vmc@leftnode.com> * @retval NULL Returns NULL. */ public function __destruct() { $this->_model = array(); } /** * The magic method to get an element from the $_model array. * @author vmc <vmc@leftnode.com> * @param $name The name of the element to get. * @retval mixed Returns the value from the model, NULL if not found. */ public function __get($name) { if ( true === isset($this->_model[$name]) ) { return $this->_model[$name]; } return NULL; } /** * Sets a value in the model. * @author vmc <vmc@leftnode.com> * @param $name The name of the key to set. * @param $v The value of the key to set. * @retval bool Returns true. */ public function __set($name, $v) { $this->_model[$name] = $v; return true; } /** * Returns the ID of the object. * @author vmc <vmc@leftnode.com> * @retval int Returns the ID of the object. */ public function getId() { return $this->_id; } /** * Returns an array of elements from the model. By default, returns * all of them, however, the inclusion or exclusion of them can be defined. * @author vmc <vmc@leftnode.com> * @param $list An option array of elements to include or exclude from the result. * @param $ignore False to include the elements, true to include them. * @retval Object Returns a new Model object. */ public function getArray($list=array(), $ignore=false) { $return = $this->_model; if ( count($list) > 0 ) { if ( false === $ignore ) { $return = array_intersect_key($this->_model, asfw_make_values_keys($list)); } else { foreach ( $list as $v ) { unset($return[$v]); } } } return $return; } /** * Sets all of the model data from an array. If 'id' is a field * of the array, it is extracted out first, and set as the $_id. * @author vmc <vmc@leftnode.com> * @param $obj The object to load from. * @retval Object Returns $this for chaining. */ public function loadFromArray($obj) { $this->_id = 0; if ( true === isset($obj['id']) ) { $this->_id = $obj['id']; unset($obj['id']); } $this->_model = (array)$obj; return $this; } /** * Writes all of the data to the datastore. If the object is already loaded, * ie, the ID is greater than 0, the data is updated, otherwise, it is inserted. * @author vmc <vmc@leftnode.com> * @retval Object Returns a new Model object. */ public function write() { if ( $this->_id > 0 ) { $this->_update(); } else { $this->_insert(); } return $this->_id; } /** * Loads all of the data from the datastore for this model object. * @author vmc <vmc@leftnode.com> * @param $object_id The ID of the model to load. * @retval int Returns the ID of the loaded model. */ protected function _load($object_id) { $table_name = strtolower(get_class($this)); $object_id = intval($object_id); if ( $object_id > 0 ) { $result_model = LN::getDb()->select() ->from($table_name) ->where('id = ?', $object_id) ->query(); if ( 1 == $result_model->numRows() ) { $model = $result_model->fetch(); unset($model['id']); $this->_model = $model; $this->_id = $object_id; } } return $this->_id; } /** * Inserts the new model data into the datastore. * @author vmc <vmc@leftnode.com> * @retval int Returns the ID of the new model. */ protected function _insert() { LN::getDb()->insert() ->into($this->_table) ->values($this->_model) ->query(); return $this->_id; } /** * Updates the model data into the datastore. * @author vmc <vmc@leftnode.com> * @retval int Returns the ID of the new model. */ protected function _update() { LN::getDb()->update() ->table($this->_table) ->set($this->_model) ->where('id = ?', $this->_id) ->query(); return $this->_id; } }
Fortunately, the Model object takes care of most of the methods and variables for User and User_Comment. The User class needs a simple way to get a list of comments quickly, in which the getCommentList() works well. The optional argument to the method allows the programmer to override the Lazy Loading method and to force it to always load from the database.
<?php /** * Basic User class for handling users. * @author vmc <vmc@leftnode.com> */ class User extends Model { ///< The Db_Iterator object of comments. private $_commentList = NULL; /** * Returns a list of comments that the user has made. * @author vmc <vmc@leftnode.com> * @param $force Optional variable to force loading of the comment list even if not null. * @return Object Returns Db_Iterator object to cycle through the results. */ public function getCommentList($force=false) { if ( NULL == $this->_commentList || true === $force ) { $result_comment = LN::getDb()->select() ->from('user_comment') ->where('from_id = ?', $this->_id) ->query(); $this->_commentList = new Db_Iterator($result_comment, new User_Comment()); /** * Calling $result_comment->free() here will cause the application to break * because the variables are copy-on-write. Because nothing was written, * the $result_comment variable in the iterator will be freed, and no results * can be fetched. * * $result_comment->free(); * * However, if you had an unset($result_comment), it will only unset this * locally scoped variable and not the variable in the iterator because the * variable in the iterator will be considered written to, and thus, copied * to a new memory location. You'll see the memory go up slightly if you * add the unset() because of the copy-on-write. * * unset($result_comment); * */ } $this->_commentList->rewind(); return $this->_commentList; } }
<?php /** * Basic User class for handling users. * @author vmc <vmc@leftnode.com> */ class User_Comment extends Model { /** * Allows the object to be printed directly. * @author vmc <vmc@leftnode.com> * @return string Returns a string representation of the object. */ public function __toString() { $str = 'User #' . $this->_model['from_id'] . ' made the comment, "'; $str .= $this->_model['comment'] . '", to User #' . $this->_model['to_id'] . '.'; return $str; } }
Because User_Comment has no dependencies, it remains a nearly empty class. A single __toString() method was added to allow easy object display. User, however, needs to load up a list of User_Comment objects. It is at this point where this implementation becomes very memory efficient. Over the course of a User’s existence on a website, they could create hundreds or thousands of comments. Loading all of these up at a single time as an array of objects is very inefficient. The initial loop must iterate through each result to build the array. This array would be very large and take up unnecessary memory. A much better implementation is to store a pointer to the initial result set and only loop through the comments when necessary.
发表评论
-
Creating PDF documents with PHP in 10 steps
2009-11-09 08:33 1609Step 1 - Install the PDFlib e ... -
26 Hints for Agile Software Development
2009-11-04 08:04 741I collect nuggets of wisdom on ... -
40个迹象表明你还是PHP菜鸟
2009-10-28 08:40 60340个迹象表明你还是PHP菜鸟 ... -
PHP performance tips
2009-10-21 09:15 741PHP performance tips Author: ... -
国外优秀开源PHP建站程序一览
2009-10-15 08:06 1330大量的PHP开源(开放源 ... -
十步让你成为一名优秀的Web开发人员
2009-10-15 08:03 845第一步:学好HTML HTML( ... -
What's Agile To You?
2009-10-09 08:34 792As a project manager, archite ... -
install Merb 1.0 on Windows
2009-10-05 17:25 925早期的Merb在Windows上安装是件很恶心的事,缺这少 ... -
WebWork敏捷开发尝试
2009-10-05 09:11 791WebWork是一个优秀的J2EE ... -
敏捷开发中常见的九大误解
2009-10-05 09:10 766一、敏捷是“一个” ... -
浅谈敏捷项目管理在软件开发中的应用
2009-10-05 09:09 1196一、使用传统项目管理技术管理软件开发项目的方法 按照 ... -
揭示PHP成功背后的秘密:PHP创始人访谈录
2009-10-01 12:47 920Rasmus Lerdorf可能是格陵兰最著名的电脑牛人,他1 ... -
GitHub: Speed matters
2009-09-29 22:25 869Impressions from the first arti ... -
PHP5 Database Iterators <2>
2009-09-29 22:15 1023Introducing the Db_Iterator Obj ... -
REST-*组织
2009-09-29 11:10 850JBoss已在月初的JBoss世界大会上正式宣布了它的新项 ... -
Agile 2009 Conference Retrospective
2009-09-26 21:51 819A month has passed since Agile ... -
Bill Burke Discusses REST-*, SOA/ROA and REST
2009-09-26 21:49 981InfoQ's recent post on REST-* ... -
git is great 2
2009-09-26 15:11 1478Git梳妆我们可以利用Git的config命令或者直接编辑~/ ... -
git is great
2009-09-26 15:08 1668Git是一个分布式的版本控制工具,本篇文章从介绍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>
1,pop3.zip<br>CPop3Connection - an MFC Class to encapsulate the POP3 protocol(15KB)<END><br>2,ipenum.zip<br>IPEnum - an MFC class and console app to allow IP address enumeration(11KB)<END><br>3,smtp....
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)。包括各种基本算法,如比较、交换、查找、排序、遍历操作、复制、修改、移除、反转、合并...
vector<int> numbers = {3, 1, 4, 1, 5, 9}; sort(numbers.begin(), numbers.end()); for (int n : numbers) { cout << n << " "; } cout << endl; return 0; } ``` #### 3.11 迭代器 (Iterators) 迭代器...
部分内容部分介绍了C++标准库中包含的头文件和功能模块,其中包括了常用的<array>、<iostream>、<string>等,这些都是构建C++程序不可或缺的部分。文档提及了算法(Algorithm)、分配器(Allocators)、迭代器...
1. **输入/输出流(I/O Streams)**:这是C++中最基础的库之一,主要包含在`<iostream>`头文件中。`std::cin`用于从标准输入读取数据,`std::cout`用于向标准输出(通常是显示器)打印数据。此外,还有`std::cerr`和...
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::...
1. 输入/输出(I/O)库:C++的`<iostream>`库是处理输入输出的基础,包含了`cin`和`cout`对象,分别用于标准输入和输出。例如,可以使用`std::cin`获取用户输入,用`std::cout`打印输出信息。此外,`cerr`和`clog`用于...
public RotateIterator(List<Iterator<T>> iterators) { this.iterators = iterators; } @Override public boolean hasNext() { while (currentIteratorIndex < iterators.size()) { if (iterators.get...
1. **定义聚合对象**:创建一个类,实现 `IEnumerable` 或 `IEnumerable<T>` 接口。这些接口要求你提供一个返回 `IEnumerator` 或 `IEnumerator<T>` 的 `GetEnumerator` 方法。这个方法将返回一个迭代器实例,用于...
- 容器适配器(Container Adapters):例如`<stack>`、`<queue>`和`<priority_queue>`,它们是基于其他容器的特殊版本,提供了特定的操作行为,如先进先出(FIFO)或优先级排序。 3. 迭代器(Iterators): 迭代...
<FIRSTNAME>Walt</FIRSTNAME> <LASTNAME>Whitman</LASTNAME> </ITEM> <ITEM> <FIRSTNAME>Walt2</FIRSTNAME> <LASTNAME>Whitman2</LASTNAME> </ITEM> </ELEMENT> </ROOTNODE> ``` ##### 2. 解析XML 解析XML...
STL的核心组件包括容器(containers)、迭代器(iterators)、函数对象(functors)和算法(algorithms)。在这个主题中,我们将深入探讨vector、list、map、set和deque这五个主要的STL容器,并通过具体的例子和PPT...
- **实例化**:通过指定具体类型来创建泛型类型的实例,如`List<int> intList = new List<int>();`。 - **约束**:可以通过添加约束限制类型参数的范围,例如要求类型必须实现特定接口或继承自特定基类。 #### 泛型...
5. **HashSet<T>**:无序且不允许重复元素的集合,适合快速查找和插入操作。 6. **Dictionary<TKey, TValue>**:键值对集合,用于存储具有唯一键的对象。它提供了快速的查找和访问速度。 7. **Queue<T>**:FIFO...