Jump to content
phil_s

How do I loop through a sliced array?

Recommended Posts

I am finishing up my first processwire site (yay), and this last bit is giving me a bit of a headache:
For a news slider, I want to output x number of posts, with three posts per slide. (for a theoretically unlimited number of slides)

I figure in theory this should work something like the code below, however the looping logic, among other things :) is still somewhat beyond me:

<?php
    $items_per_page = 3;
    $start = ($pages->get("/news/")->find("sort=sort")->pageNum - 1) * $items_per_page;
    $total = count($pages->get("/news/")->find("sort=sort"));
    $slicedarticles = $pages->get("/news/")->find("sort=sort")->slice($start, $items_per_page);
    
    foreach ($slicedarticles as $slicedarticle => $total) {
        echo "<div class='slide'>";
        
        foreach ($slicedarticle as $article) {
            echo "<h3>{$article->title}</h3><p>{$article->body}</p>";
        }
        
    echo "</div>";
    }
?>

Can someone point me in the right direction with this?

Much appreciated!

Cheers,

Phil

Share this post


Link to post
Share on other sites

Not sure what kind of markup you are after, but getting and looping three posts is simple as this:

$articles = $pages->find("parent=/news/, limit=3");

foreach($articles as $article) {
  echo "<div class='slide'>$article->title</div>";
}

Share this post


Link to post
Share on other sites

@apeisa, sorry, edited the initial post to make this more clear:

I want to output x number of posts, and "package" them into slides (each slide containing three posts).

Makes more sense?

Share this post


Link to post
Share on other sites

Hm, there are several things to correct in your code. First one, and most important, is that slice() will give you only one array

$a->slice($n, $limit) -> Returns a new WireArray containing a slice of items starting from the $n'th item and including up to $limit number of items.

and I don't think this is what you are looking after.

Second one, is the way you are using the => sign in your foreach. When you do "$slicedarticle => $total", what will happen is that $slicedarticle will be populated the key of this element, and $total will be the value of the element. So, the content that you had on these variables will simply be lost. Read here http://php.net/manual/en/control-structures.foreach.php

What I interpret that you want, is to create the amount of slides needed so you have only three elements on each slide. Is that right? If so, try this:

$items_per_page = 3;

$myPages = $pages->get(1)->find('sort=sort');

$nrSlides = count($myPages)/$items_per_page;

while($nrSlides > 0) {

    echo "<div class='slide'>";

        for($i=$items_per_page; $i>0; $i--) {
            
            if(count($myPages)) {
         
                $article = $myPages->shift();

                echo "<h3>{$article->title}</h3><p>{$article->id}</p>";

            }

        }

    echo "</div>";

    $nrSlides--;
}
 

Edit: By your new explanation, I think this is what you want :)

Also, look for shift() on the cheatsheet http://cheatsheet.processwire.com/ to understand what's happening in my code:

Remove (shift) the first $item from the WireArray and return it.

Edit2: changed the if statement in the code for something better

Share this post


Link to post
Share on other sites

@apeisa, sorry, edited the initial post to make this more clear:

I want to output x number of posts, and "package" them into slides (each slide containing three posts).

Makes more sense?

$articles = $pages->find("parent=/news/, limit=18");

$out = '';
foreach ($articles as $key => $article) {
  if ($key == 0) $out .= "<div class='slide first'>"; // Open the first .slide
  else if ($key % 3 == 0) $out .= "</div><div class='slide'>"; // Close the previous slide and open next
  $out .= "<div class='post'><h2>$article->title</h2></div>"; // render the actual markup
}
$out .= "</div>"; // Close the final .slide

echo $out;

not tested and written in browser. You can omit the limit if you want to.

  • Like 2

Share this post


Link to post
Share on other sites

@Apeisa, just went through my old posts and noticed I never replied back! Sorry, and  thank you very much, this worked perfectly!

$articles = $pages->find("parent=/news/, limit=18");

$out = '';
foreach ($articles as $key => $article) {
  if ($key == 0) $out .= "<div class='slide first'>"; // Open the first .slide
  else if ($key % 3 == 0) $out .= "</div><div class='slide'>"; // Close the previous slide and open next
  $out .= "<div class='post'><h2>$article->title</h2></div>"; // render the actual markup
}
$out .= "</div>"; // Close the final .slide

echo $out;

not tested and written in browser. You can omit the limit if you want to.

  • Like 1

Share this post


Link to post
Share on other sites

Actually there is a solution for working with slice_array. The thing is that $pages->get("/news/")... returns a PageArray thing, which is not a php array, but probably an object (not sure).

But there is a way to get this data as a php array like this:

$array=$pages->get("/news/")->getArray();

This one you can slice.

And there is a native way to slice PageArray (diogo wrote about it):

$pages->get("/news/")->slice($n, $limit). Read about it here.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By louisstephens
      From my last post, I was given a good idea on how to count the repeater items, and it worked wonderfully. I got my code working well and the columns (based on the count) all work well as well. Now, I have a head scratcher on my hands. 
      <?php $buttonsIncluded = $page->special_custom_buttons->find('special_custom_buttons_include=1'); $buttonsIncludedCount = count($buttonsIncluded); $buttonsIncludedCountAdditional = $buttonsIncludedCount +1; echo $buttonsIncludedCount; ?> <div class="row"> <?php foreach($buttonsIncluded as $button): ?> <?php if($button->custom_buttons_include): ?> <?php if($buttonsIncludedCountAdditional == 2): ?> <div class="col-6"> <a href=""><?php echo $button->custom_buttons_text; ?></a> </div> <?php elseif($buttonsIncludedCountAdditional == 3): ?> <div class="col-4"> <a href=""><?php echo $button->custom_buttons_text; ?></a> </div> <?php elseif($buttonsIncludedCountAdditional == 4): ?> <div class="col-3"> <a href=""><?php echo $button->custom_buttons_text; ?></a> </div> <?php endif; ?> <?php endif; ?> <?php endforeach; ?> </div> All of this is included in a larger foreach statement that is pulling in other data (like body copy etc etc) from a Page Table field. As you can see in my code above, I am adding "1" to the count, so I can have space in the grid layout for a new button.
      So, right now: it looks something like: 
      [repeater button] [repeater button] [repeater button] [space for new button] What I really need to do is to pull in the button from the Page Table and add it into the new space so it looks like:
      [repeater button] [repeater button] [repeater button] [button from Page Table] Is this even possible todo, or is there a better way to go about this? 
       
      *Edit*
      So, I really just overlooked something quite easy here. Since the grid is based on 12 columns, I could just take 12 and divide by $buttonsIncludedCountAdditional which would give me the remaining col width to use outside the foreach loop. I was trying to make this too complicated.
    • By rolisx
      Hi all
      I have a problem here. I created a gallery with 240 pictures. Created an images field with no maximum amount (0). Unfortunately, only 98 of the 240 images show on the website. Any idea what I possibly could have done wrong? Thanks for your help!
      <?php foreach ($page->images as $image) { $options = array( 'quality' => 90, 'upscaling' => false ); $thumb = $image->size(250, 250, $options); ?> <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-6 foto"> <a href="<?= $image->url ?>" data-lightbox="lightbox" > <img src="<?= $thumb->url ?>" alt="" > </a> </div> <?php } ?>  
    • By celfred
      Hello !
      I have somehting I don't understand here... Here's my code :
      $allPlayers = $pages->find("parent.name=players, team=$selectedTeam"); $allTrains = $allPlayers->find("template=event, task.name~=ut-action, refPage!='', date>=$startDate, date<=$endDate, sort=refPage, sort=date"); bd('$allTrains:'.$allTrains->count()); // DISPLAYS 0 ???? foreach($allPlayers as $p) { $allTrainings = $p->find("template=event, task.name~=ut-action, refPage!='', date>=$startDate, date<=$endDate, sort=refPage, sort=date"); $test += $allTrainings->count(); } bd('$test:'.$test); // DISPLAYS 883 pages (normal) As you can read from my comments, I have no idea why my first $allTrains stays at 0 while the second request actually finds the corresponding pages. If someone could explain I'd appreciate a lot. I have been struggling with this for hours now... For your information, my pages having template 'event' are in a subtree like so :
      - player 01
        - history-1
          - event 01
         - event 02
         - event ...
        - history-2
          - event 01
          - event ...
      - player 02
        - history-1
          - event 01
         - event 02
         - event ...
        - history-2
          - event 01
          - event ...
      - player ...
        - history-1
          - event 01
         - event 02
         - event ...
        - history-2
          - event 01
          - event ...
       
      Thanks in advance. (sorry for my preceding 'tree' which doesn't look like much. I need to find a way to output this better 😉 )
    • By burning
      Hi All, maybe a really stupid question, but is there a way to sort repeater items on -created?
      Like $page->social_activity('limit=10,sort=created'), with 'social_activity' as the repeater field?
      Tried this but it didnt work 😞 
      Any help appreciated! 
    • By flod
      I'm working on a newsletter solution with WireMailSMTP and this Newsletter Tutorial.
      I only changed the lines 73 to 83 in newsletter.php, but there's a strange issue with the $subscribers array:
      $testMode = isset($_POST['test_email']) ? true : false; if ($testMode) { $subscribers = wire('input')->post('test_email'); if (strpos($subscribers, ',') !== false) { $subscribers = explode(',', $subscribers); } } else { $subscribers = $pages->find('template=subscriber'); $subscribers = $subscribers->explode('email'); } if (is_array($subscribers)) { $subscribers = array_map('trim', $subscribers); } $mail = wireMail(); $mail->sendSingle(true)->to('test@domain.de')->bcc($subscribers); $mail->from('xxx@domain.de'); $mail->subject($newsletter->title); $mail->bodyHTML($html); $numSent = $mail->send(); echo json_encode(count($subscribers)); $this->halt(); The email is sent to test@domain.de but not to bcc $subscribers. Errorlog: PHP Notice: Unknown: Invalid mailbox list: <> (errflg=3) in Unknown on line 0 I'm grateful for any advice.
      Greetings
      Florian
×
×
  • Create New...