Mura Iterators - Mura Docs v7.1

Mura Iterators

According to Merriam-Websteriterate means "to say or do again or again and again." In programming, an "iterator" is a design pattern. An iterator wraps a collection or group of objects (e.g., queries/recordsets, arrays, lists, structs, beans, etc.) with common helper methods without the need to fully know or understand the underlying data structure. This allows programmers to use common methods for looping over, or iterating over, many different types of collections or groups of objects.

Mura Iterators are an array of objects, and have a number of common helper methods, allowing developers to loop/iterate over, collections/groups of objects. Mura Iterators wrap an underlying query, and use the returned recordset as the basis for its array of objects. This also means the order of objects in the iterator is determined by the sort order of the underlying recordset.

As you may have already seen in other sections of the documentation, Mura relies on the iterator design pattern itself. Many of Mura's common beans include helper methods which return some type of iterator. For example, in the Content Bean section, you'll see methods such as getRelatedContentIterator(), getCommentsIterator(), etc.

If you've worked with recordsets/queries in the past, you'll find iterators to be quite similar. However, working with iterators gives you so much more power than merely looping over a query/recordset. When iterating over a collection of Mura objects, you'll have access to the entire object itself, including its helper methods. However, if you were merely looping over a query/recordset using <cfoutput> tags, you would only have access to the fields included in the record itself. In addition, when working with a standard query/recordset, it can be cumbersome to do things like pagination, or even loop backwards without having to rewrite the underlying query itself. Mura Iterators can do all of these things for you, and so much more.

Iterator Basics

As an object itself, Mura Iterators have a number of attributes you can inspect using its helper methods. Iterators hold data pertinent to looping over collections or groups of objects. For example, Mura Iterators know how many objects there are in the collection it's working with. They also know if you've started to loop/iterate over the collection, what object you're currently working with, which "page" your on, and so on.

You can use these helper methods to ask the iterator for the next object, or even the previous object, and then do whatever you want with the object itself, and when finished, move on to the next object. For example, you could manipulate each object, and then re-save it. If the objects were content items, you could loop over each object, and then output the associated image and a title to create a slideshow. The possibilities are endless.

While Mura Iterators offer several helper methods, there are only two primary methods you need to know to begin working with them; hasNext() and next().

hasNext()

The hasNext() method inspects the underlying collection/array of objects, and then returns true if there are still objects in the array of objects you're working with, or false, if there are no more objects in the array to work with.

next()

The key method, next(), queues up the next object in the collection/array of objects, and gives you a way to reference the current item/object so you can work with it.

Basic Examples

The examples below demonstrate using the basic hasNext() and next() methods.

Tag-based Example

<cfloop condition="iterator.hasNext()">
  <cfset item = iterator.next()>
  <!--- Do something with 'item' --->
  <cfdump var="#item#">
</cfloop>

Script Example

while ( iterator.hasNext() ) {
  item = iterator.next();
  // Do something with 'item'
  WriteDump( item );
}

// OR

do {
  item = iterator.next();
  // Do something with 'item'
} while ( iterator.hasNext() );

Conditionals

You could also wrap the prior examples with a conditional, and return something in the event that the iterator is empty.

if ( iterator.hasNext() ) {
  // Iterator has objects
} else {
  // Iterator is empty ... no objects
}