如何在从Magento中提取的集合上使用for循环

时间:2013-08-30 09:12:49

标签: php magento

我试图在我从Magento中提取的产品上使用for循环。 当我想在循环中的产品上使用索引时,它会崩溃。

$collection = Mage::getModel('catalog/product')->getCollection();

$collectionLength = count($collection);
for($j = 0; $j < $collectionLength; $j++)
{
     $productFromStore = $collection[$j];//it crashes on this line of code
     $sku = $productFromStore->getSku();
}

但是当我使用foreach循环时,我可以访问所有产品。

foreach($collection as $product)
{
     // this code works fine
     $sku = $product->getSku(); 
}

有人能解释出现了什么问题吗?为什么?

感谢。

6 个答案:

答案 0 :(得分:3)

Magento的ORM中的集合类最终子类Varien_Data_Collection实现了IteratorAggregate;这就是为什么你能够以类似数组的方式使用集合对象(即foreach),但不能让它适用于for循环。首先,dThere没有对对象内部元素的直接基于密钥的访问(_items数组成员) - 不幸的是,假设_items数组的密钥基于行ID。 / p>

结论:在for循环中处理集合项目并不容易,与通过IteratorAggregate及其所有相关产品处理集合项目的难易程度相比,并非易事。

这是两者的一个例子。如果您有直接使用集合项目的首要需求,那么您可以使用$collection->getItems(),但再次意识到_items数组键可能不是连续的,因为它们基于数据。另请注意,您需要将name属性值添加到使用Magento的EAV模式存储的集合中:

<?php
header('Content-Type: text/plain');

include('app/Mage.php');
Mage::app();

$collection = Mage::getResourceModel('catalog/product_collection');
$collection->addAttributeToSelect('name');

//for loop - not as much fun
for ($j=0;$j<count($collection);$j++) {  //count() triggers $collection->load()
    $items = $collection->getItems();
    $item = current($items);
    echo sprintf(
        "%d:\t%s\t%s\n",
        $k,
        $item->getSku(),
        $item->getName()
    );
    next($items); //advance pointer
}

//foreach - a bit better
foreach ($collection as $k => $product) {
    echo sprintf(
        "%d:\t%s\t%s\n",
        $k,
        $product->getSku(),
        $product->getName()
    );
}

以防万一你想知道:Performance of FOR vs FOREACH in PHP

答案 1 :(得分:3)

首先,您尝试将集合对象作为数组进行迭代 这是错误:

  

致命错误:无法使用类型的对象   Mage_Catalog_Model_Resource_Product_Collection as array

,第二个for循环不是迭代集合的最好方法更好的是foreach循环因为循环需要计算数组emelents foreach不需要它。 第三,最好的方法是使用magento资源迭代器。

SKWMediaConstraints* constraints = [[SKWMediaConstraints alloc] init];
    constraints.maxWidth = 960;
    constraints.maxHeight = 540;

    //  constraints.cameraPosition = SKW_CAMERA_POSITION_BACK;
    constraints.cameraPosition = SKW_CAMERA_POSITION_FRONT;

    _msLocal = [SKWNavigator getUserMedia:constraints];

    //////////////////// END: Get Local Stream   /////////////////////////
    // Initialize views
    if ((nil != self.navigationItem) && (nil == self.navigationItem.title))
    {
        NSString* strTitle = @"Video Conference";
        [self.navigationItem setTitletrTitle];
    }

    CGRect rcScreen = self.view.bounds;
    if (NSFoundationVersionNumber_iOS_6_1 < NSFoundationVersionNumber)
    {
        CGFloat fValue = [UIApplication sharedApplication].statusBarFrame.size.height;
        rcScreen.origin.y = fValue;
        if (nil != self.navigationController)
        {
            if (NO == self.navigationController.navigationBarHidden)
            {
                fValue = self.navigationController.navigationBar.frame.size.height;
                rcScreen.origin.y += fValue;
            }
        }
    }

    // Initialize Local video view
    CGRect rcLocal = CGRectZero;
    if (UIUserInterfaceIdiomPad == [UIDevice currentDevice].userInterfaceIdiom)
    {
        rcLocal.size.width = rcScreen.size.width / 5.0f;
        rcLocal.size.height = rcScreen.size.height / 5.0f;
    }
    else
    {
        rcLocal.size.width = rcScreen.size.height / 5.0f;
        rcLocal.size.height = rcLocal.size.width;
    }
    rcLocal.origin.x = rcScreen.size.width - rcLocal.size.width - 8.0f;
    rcLocal.origin.y = rcScreen.size.height - rcLocal.size.height - 58.0f; // changed from 8 to 78 so to present this view above control views
    rcLocal.origin.y -= self.navigationController.toolbar.frame.size.height;

    // New frames for local and remote video views
    CGRect rcRemoteNew;
    rcRemoteNew.origin.x = 0.0;
    rcRemoteNew.origin.y = 0.0;
    rcRemoteNew.size.width = SCREEN_WIDTH;
    rcRemoteNew.size.height = SCREEN_HEIGHT;

    ////////////  START: Add Remote & Local SKWVideo to View   ///////////
    SKWVideo* vwRemote = [[SKWVideo alloc] initWithFrame:rcRemoteNew];
    [vwRemote setBackgroundColorUIColor blackColor]];
    [vwRemote setTag:TAG_REMOTE_VIDEO];
    [vwRemote setUserInteractionEnabled:NO];
    [vwRemote setHidden:YES];
    [baseView addSubview:vwRemote];

    SKWVideo* vwLocal = [[SKWVideo alloc] initWithFrame:rcLocal];
    [vwLocal setBackgroundColorUIColor clearColor]];
    [vwLocal setTag:TAG_LOCAL_VIDEO];
    [baseView addSubview:vwLocal];

    // Add local stream to local video view
    [vwLocal addSrc:_msLocal track:0];

    ////////////  END: Add Remote & Local SKWVideo to View   /////////////

这是一个例子:

Mage::getSingleton('core/resource_iterator')
        ->walk(
           $query->getSelect(), 
           array(array($this,'callbackFunction')));

快乐的编码, 亚当

答案 2 :(得分:0)

我不是magento的专家,但也许是因为该系列除了数字之外还有不同的键?尝试使用print_r打印出该集合,以查看该对象具有哪些键。

如果您需要使用数字进行迭代,您可以随时执行以下操作:

$i=0;
foreach($collection as $product)
{
     $sku = $product->getSku(); 
     $i++;
}

编辑:无论如何,似乎集合不是常规数组,所以你不能像你尝试的那样使用它们。

答案 3 :(得分:0)

$array = array(
    "foo" => "bar",
    "bar" => "foo",
);

您必须使用的索引无法访问此类型的数组

$array["foo"];

如果密钥不可预测,您必须使用

`的foreach

答案 4 :(得分:0)

那是因为你要向getSku函数发送一个空值。

<?php
$collection=array("book1"=>"bat","book2"=>"cat");
$collectionLength = count($collection);
for($j = 0; $j < $collectionLength; $j++)
{
    $productFromStore = $collection[$j];
    echo $productFromStore; //prints nothing !
}

foreach($collection as $var)
{
    echo $var; //prints batcat
}

答案 5 :(得分:-1)

在magento集合中以对象的形式返回。使用下面的代码获取SKU和NAME。或者使用print_r($collection->getData())以数组Key =&gt;值格式获取数据。

foreach($collection as $productCollection){
$sku = $productCollection->getSku();
$name = $productCollection->getName();

}