Toggle Navigation
首页
Golang
PHP
Laravel
Magento
Linux
数据库
MySQL
Redis
Mongodb
热门知识
程序与生活
架构师之路
静态站点
GitHub
主页
处理大型的Magento集合
处理大型的Magento集合
12-18
Mark
675
Magento集合代表了分组模型一种很方便的方式。得益于集合模型提供的方法,我们可以用很少或者几乎不用SQL语句来从数据库中获取一组模型。集合可能很大(新产品,金额互,类别,大量的属性等),成为一件棘手的工作。让我们看看怎么做能让大集合变得更易于管理。 如果说我们想让我们客户的名字大写,那么我们可能会这么做: ```php $customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToSelect(array('firstname'), 'inner'); foreach ($customers as $customer) { $customer->setFirstname(strtoupper($customer->getFirstname())); $customer->save(); } ``` 这段代码在小集合里运行得很不错,但是作用于大一点的集合时就会耗尽内存,产生下面的错误: ```php “Fatal error: Allowed memory size of X bytes exhausted (tried to allocate X bytes) in magento_site\lib\Varien\Data\Collection.php on line 550“. ``` 为什么会这样呢? 集合基本上是一个对象数组,这里是一个客户对象数组。对象越多,选取的属性越多,产生的结果数组就越大,这样就导致高内存的使用。 解决Magento中的这个问题要实施到Mage_Core_Model_Resource_Iterator模型的形式。它允许我们从数据库里一个一个地抓取数据,这与我们上面例子中一次性抓取数据相对。这个迭代器中最主要的就是walk()方法,它需要两个强制参数去工作,收集查询语句和回调方法。 如果我们看下方法的实现: ```php public function walk($query, array $callbacks, array $args=array(), $adapter = null) { $stmt = $this->_getStatement($query, $adapter); $args['idx'] = 0; while ($row = $stmt->fetch()) { $args['row'] = $row; foreach ($callbacks as $callback) { $result = call_user_func($callback, $args); if (!empty($result)) { $args = array_merge($args, $result); } } $args['idx']++; } return $this; } ``` 我们可以看到,它需要查询语句,执行语句,一个一个地获取结果然后传送到回调方法。通过回调方法的结果被放到$args里,在回调功能里,我们可以访问$args[‘row’]的数据。 下面是我类似于迭代器的例子: ```php public function uppercaseAction() { $customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToSelect(array('firstname'), 'inner'); Mage::getSingleton('core/resource_iterator')->walk($customers->getSelect(), array(array($this, 'customerCallback'))); } public function customerCallback($args) { // get customer model $customer = Mage::getModel('customer/customer’); $customer->setData($args['row']); $customer->setFirstname(strtoupper($customer->getFirstname())); $customer->getResource()->saveAttribute($customer, 'firstname'); } ``` 事情在这里变得相当简单。我们定义集合并传送它的sql查询语句给迭代器的walk()方法。迭代器执行给出的语句,并在每个数据库返回的结果后面调用customerCallback() 方法。在调用方法中,我们实例化客户模型,映射$args[‘row’]中的数据到模型并改变其名字属性为大写。 有一件要注意的是对象保存。为了我们的脚本尽可能有效地执行,我们节省了大量模型。使用"classic"保存是一件耗时耗资源的工作。由于我们只改变一个属性,所以最好使用saveAttribute()方法,这要快得多。 这样,再也没有"out of memory"报警了。
最新文章
Golang内存问题处理
WebSocket详解
Gopher面试中的Coding(三)
Golang用os/signal包实现平滑重载配置文件
Nginx实现负载均衡的几种方式
Golang中子goroutine与主协程同步的四种实现
Dockerfile文件详解
Golang开发微信公众号
最热文章
Magento实现下载csv数据表格
1324
Magento上传文件、缩略图和导出CSV
1238
Laravel带有条件搜索的分页
1148
Magento优化 – MySQL读写分离
1101
Magento后台添加rule规则
1052
Magento常用模块分享
870
Magento 建立自己的shell命令
812
10个实用的PHP正则表达式
799
热门标签
下载
上传
导出
laravel分页
读写分离
rule
规则
模块
shell
正则
Collection
binlog
命名空间
微信公众号
Git
解锁
锁表
string
处理
composer
事务处理
读写
架构
系统
表分割
函数
redis sentinel
time
日志分析
进阶
事务处理
缓存
package
schedule
交叉编译
HTTPS
fmt
golang
channel
事务
分布式锁
日志过滤
日志分割
mongodb
git服务器
gogs
多数据库
Dockerfile
json
php
protobuf
版本号
concat
发展方向
Gopher面试
get
post
goroutine
负载均衡
重载配置
模型关系
rpc
算法
mongodb
laravel
docker
elasticsearch
写文件
golang算法
defer
panic
redis
代码部署
主从配置
Dataflow
curl
package
Shell
生成插件
直接下载
并发
量级
数据类型
protobuf
参数
错误传递
队列
Go指针
成长
方法
websocket
grpc
路上
风景
protobuf
Redis持久化
yum
内存泄漏