CMB2 file_list paginate (real pages) foreach uses serialized data

I have a hard time giving up using CMB2 file_list field my gallery but it doesn't have the option (built in) to paginate (like ACF) and my php skills are lacking. I can do it with jQuery but I want real pages.

This is getting close to what I need and it's cobbled together from another question. It splits out 5 results from the $files (get_post_meta) and creates pages but the images are all the same images on all the pages. I am beyond the limit of my brain.

The $attachment_id => $attachment_url is the individual image from the ones selected from the Media Library.

$files as $attachment_id => $attachment_url

Here's what I have so far (you might want to ditch it in favor of something better):

function gallery_loop() {

if( get_query_var('page') ) {
    $page = get_query_var( 'page' );
} else {
    $page = 1;

$img_size = 'portfolio-catalog';

$files = get_post_meta(get_the_ID(), '_cmb_gallery_images', true);
$limit = 5;
$total = count( $files );
$pages = ceil( $total / $limit );

$curr_page = isset($_GET['page']);
$offset = ($curr_page - 1) * $limit;

$items_array = array_chunk((array) $files, $limit, true); 

$files_array = array_slice($items_array, $offset, true); // this is showing the same 5 items on all the pages

foreach ($files_array as $files) {

    echo '<div style="border:1px solid red;">'; //BEGIN FAKE "page" so I can see if they are splitting correctly

    foreach ($files as $attachment_id => $attachment_url) {


        echo '<div class="file-list-image">';
        echo wp_get_attachment_image($attachment_id, $img_size);
        echo '</div>';


    } // end $files as $attachment_id => $attachment_url

    echo '</div>'; //END "page" so I can see if they are splitting correctly

} // end foreach $files_array as $files

//the correct amount of pages are showing up but the items are all the same
 echo paginate_links( array(
    'base' => get_permalink() . '%#%' . '/',
    'format' => '?page=%#%',
    'current' => $page,
    'total' => $pages
  ) );

// end function

Answer to questions in comments:

This is for a page template called gallery-page.php. It is page that has a CMB2 field type called file_list and that is a place to attach images to (they are attached not to the page, but to that field so you can grab any and upload to it too).

When I do a print_r from $files = get_post_meta(get_the_ID() , '_cmb_gallery_images', true); I get:

Array( [956] => [960] => [958] => [974] =>

and so forth.


Use the below code provided below, 5 images will be displayed per page, and pagination links will allow the user to navigate between the gallery’s pages at pretty URLS such as /gallery/2/, /gallery/3/ and so on.

function gallery_loop() {

    if (get_query_var('page')) {
        $page = get_query_var('page');
    else {
        $page = 1;

    //* variables   
    $row = 0;
    $images_per_page = 5; //image count
    $img_size = 'portfolio-catalog'; //image size
    $images = get_post_meta(get_the_ID() , '_cmb_gallery_images', true); //cmb2 field
    $total = count($images);
    $pages = ceil($total / $images_per_page);
    $min = (($page * $images_per_page) - $images_per_page) + 1;
    $max = ($min + $images_per_page) - 1;

    echo '<ul class="your-class clearfix">';

     //* create the 'pages'    
    if (count($images) > 0) {

       foreach ((array) $images as $attachment_id => $attachment_url ) {


            // ignore this image if $row is lower than $min
            if ($row < $min) {

            // stop loop completely if $row is higher than $max
            if ($row > $max) {

            //echo the images
            echo '<li>';
            echo wp_get_attachment_image($attachment_id, $img_size);
            echo '</li>';

        } //end foreach

         //* pagination
        echo paginate_links(array(
            'base' => get_permalink() . '%#%' . '/',
            'format' => '?page=%#%',
            'current' => $page,
            'total' => $pages

    } else {

        echo '<li>No images found.</li>';

    } //endif;

    echo '</ul>';

} // end gallery_loop;

I assume, that all of the data is actually in your corresponding vars. But anyway, could you please provide var_dump of $files after you set it from post_meta? (In case that my fast solution would not work)

Also, instead of array_slice you can use direct index of array element in foreach statement, but it's not important

foreach ($items_array[$curr_page - 1] as $files) {

Anyway, the main problem is here:

$curr_page = isset($_GET['page']);

isset is always returning true or false (1 or 0). So, despite of the page you're always loading first or second one. Just replace the code with:

$curr_page = isset($_GET['page']) ? $_GET['page'] : 0;

Additionally, you can check your $_GET['page'] with is_int() or is_numeric() & round it ( just in case :D )

Need Your Help

Absolute Positioning Differing Between Browsers

css cross-browser positioning

I have noticed that my three absolutely positioned divs with text inside are positioned one way in internet explorer and firefox and slightly different in chrome and safari. What is the reason and

pass a different model to the partial view


I am trying to pass a different model to the partial view from a view. I have two separate controller actions for both of them and two different view models. But when I call the partial view from w...