Toggle Navigation
首页
Golang
PHP
Laravel
Magento
Linux
数据库
MySQL
Redis
Mongodb
热门知识
程序与生活
架构师之路
静态站点
GitHub
主页
处理大型的Magento集合
处理大型的Magento集合
12-18
Mark
1173
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数据表格
1887
Laravel带有条件搜索的分页
1808
Magento上传文件、缩略图和导出CSV
1758
Golang开发微信公众号
1728
Magento添加Advanced Dataflow
1715
Magento后台添加rule规则
1639
Magento优化 – MySQL读写分离
1589
Magento常用模块分享
1517
热门标签
下载
laravel分页
上传
导出
微信公众号
Dataflow
rule
规则
读写分离
模块
shell
正则
内存泄漏
Collection
binlog
命名空间
Git
处理
composer
string
package
解锁
锁表
redis sentinel
函数
事务处理
time
架构
系统
读写
golang
事务处理
缓存
日志分析
进阶
schedule
fmt
表分割
Gopher面试
交叉编译
日志分割
事务
分布式锁
HTTPS
Dockerfile
mongodb
channel
git服务器
gogs
php
protobuf
重载配置
版本号
多数据库
负载均衡
concat
mongodb
日志过滤
发展方向
defer
panic
模型关系
goroutine
json
get
post
protobuf
golang算法
代码部署
算法
rpc
docker
elasticsearch
redis
写文件
主从配置
websocket
laravel
package
生成插件
直接下载
数据类型
curl
并发
量级
错误传递
成长
Shell
Go指针
grpc
方法
参数
队列
protobuf
Redis持久化
路上
风景
yum