Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - Object equivalent of array_slice();

I'm trying to remove the first two items in an Object. For example, if I wanted to remove the first two items from an array, I'd use array_slice($arrayName, 2).

I've tried this on my object (Hey, why not? I know it's not technically an array, but I'm optimistic) and it didn't work.

When searching for this, all I found were methods for removing items from arrays.

    $categories = array_slice(Mage::getModel('catalog/category')->getCollection()->addAttributeToSelect('*'), 2);


    foreach($categories as $category){
        echo "<div class='col'>{$category->getName()}</div>";
    }

In the example above, I'd like to remove the first two categories from the $categories (which are 'Root Category' and 'Default') object before running it through the foreach loop. What would be the best method to go about this? I know I could do;

if($category->getName() != 'Root Category' && $category->getName() != 'Default'){
  echo $category->getName();
}

But this feels like a dirty solution.

Edit

After reading Patrick Q's comment, I realised that this is indeed an array of objects. So my question now becomes, why when applying an array_slice to this array, does it result in a blank screen? The loop works fine when array_slice is not applied.

Edit 2

Ignore the last Edit. It is an Object.

As for possible duplication, while the question (in question) did indeed help me solve my problem, I think, inherently they are different questions. This question, at it's core, centred around finding a useful alternative to array_slice() for objects. The question linked on the other hand, wants to to find a way, specifically, to filter Magento collections based on a drop-down attribute. Whilst they may have arrived at the same destination, the purpose and journey are very different.

like image 658
Lewis Avatar asked Mar 11 '16 15:03

Lewis


1 Answers

The functionality doesn't, to my knowledge, exist in Magento.

I'm trying to remove the first two items in an Object (emphasis mine)

By default, PHP objects do not act like arrays. There's no internal to PHP concept of what it would mean for an object to have a first, second, or third item.

The reason you can foreach or count a Magento collection object as though it were an array is because the base collection object implements special interfaces from PHP's standard library -- IteratorAggregate and Countable

#File: lib/Varien/Data/Collection.php
class Varien_Data_Collection implements IteratorAggregate, Countable
{
}

By implementing these interface, (by defining methods in Varien_Data_Collection per the manual links above) the object gets foreach and count() functionality.

Magento's IteratorAggregate implementation (the thing that gives you foreach functionality) relies on PHP's built in ArrayIterator class

#File: lib/Varien/Data/Collection.php
class Varien_Data_Collection implements IteratorAggregate, Countable
{
    public function getIterator()
    {
        $this->load();
        return new ArrayIterator($this->_items);
    }
}

And objets created from the ArrayIterator class have no built in slice functionality. This makes sense -- conceptually the idea behind an iterator is that it allows you to traverse a list without loading the entire underlying list into memory at once. That Magento and PHP's base iterators work with already loaded arrays is a bit of all-to-common redundancy in OO PHP.

So, if you wanted to use slice with a Magento collection object, I'd try the getArrayCopy method of the underlying iterator.

$array = array_slice($categories->getIterator()->getArrayCopy(), 2);

This should (untested) return a PHP array with the expected elements sliced.

Hope that helps!

like image 171
Alan Storm Avatar answered Sep 19 '22 01:09

Alan Storm