Loop type

To add a new loop type, create a class that extends from the base loop.

It can extend from other loop types, such as post or user loop.


Core loop types are defined in tangible-loop-module/types.

Base loop

Tangible\Loop\BaseLoop is a generic class for looping through any kind of items.

It implements an interface, which outlines all the methods that a loop class must have. If a loop class doesn't define a method, it will be inherited from the base loop.

See the Interface section below for a list of defined methods.


The implementation is in tangible-loop-module/types/base/index.php.


Here is a minimal example of an EDD customer loop.

namespace Tangible\Loop\Integrations\EDD;

use Tangible\Loop\BaseLoop;

class CustomerLoop extends BaseLoop {

  static $config = [
    'name'        => 'edd_customer',
    'title'       => 'EDD Customer',
    'category'    => 'edd',
    'description' => 'Loop through customers of Easy Digital Downloads',
    'query_args'  => [
      'orderby' => [
        'description' => 'Order by field',
        'type'        => [ 'string', 'array' ],
        'default'     => 'name',
    'fields'      => [
      'id'             => [
        'description' => 'Customer ID',

  function run_query( $query_args = [] ) {
    return EDD()->customers->get_customers( $query_args );

  function get_item_field( $item, $field_name, $args = [] ) {

    switch ( $field_name ) {
      case 'id': return $item->id;

tangible_loop()->register_type( CustomerLoop::class );


A loop class has a required static property config, to pass the loop type definition.

This definition is used for registering the loop type, and for generating documentation about available query arguments and fields.

The main properties are:

  • name - Name of loop type

    Must be in "snake case": lowercase, alphanumeric, underscore _.

  • title - Title of loop type

  • description - Description of loop type

  • category - Category name

    Must be in "snake case": lowercase, alphanumeric, underscore _.

    Category is used for organizing the loops in the documentation.

    Currently there are: core, acf, edd, woocommerce, wp_fusion.

  • query_args - Available query arguments for creating a loop

    An associative array with the argument name as key, and value of:

    • description
    • type
    • default
  • fields - Available fields for each loop item.

    An associative array with the field name as key, and value of:

    • description


Get an instance of the Loop module, and call register_type.

tangible_loop()->register_type( SomeLoop::class );

Pass the name of the loop class as a string. The easiest way is to use the static property ::class, which returns the full class name with namespace.


The BaseLoop class provides generic methods to query, loop, and paginate an array of items.

To integrate with a specific content type, commonly overridden methods are: create_query_args, run_query, and get_item_field.

For an overview, see the defined methods below.

namespace Tangible\Loop;

interface BaseLoopInterface {

  // Loop type name
  function get_name();

  // Loop type config
  function get_config();

  // Query
  function create_query_args( $args );
  function create_query( $query_args );
  function run_query( $query_args );
  function get_items_from_query( $query );

  // Loop over items
  function loop( $fn);
  function each( $fn ); // Alias of loop
  function map( $fn );
  // function reduce( $fn, $acc = [] );

  // Cursor
  function get_current();
  function set_current( $item );
  function next();
  function has_next();
  function reset();

  // Field
  function get_field( $field_name, $args );

  // Pagination

  // Paginated items
  function get_items();
  function get_items_count();
  function get_items_per_page();

  // Current page
  function get_current_page();
  function set_current_page( $current_page );
  function get_current_page_items();

  // All pages
  function get_total_items();
  function get_total_items_count();
  function get_total_pages();