SamC Posted July 21, 2017 Share Posted July 21, 2017 I'm building a testimonials page, and currently have this (one review will always be at the top, the first one, whichever that may be after shuffling): // views/testimonials.php <?php namespace ProcessWire; ?> <?php $arr = $page->testimonials; $arr->shuffle(); $firstTestimonial = $arr->first(); $otherTestimonials = $arr->not("$firstTestimonial"); ?> <div class="jumbotron jumbotron-fluid bg-color"> <div class="container"> <h2><?= $firstTestimonial->title; ?></h2> <p><?= $firstTestimonial->testimonialBody; ?> - <i><?= $firstTestimonial->testimonialReviewee; ?></i></p> </div> </div> <div class='container'> <div class='row py-6'> <?php foreach($otherTestimonials as $testimonial): ?> <div class='col-sm-12 col-md-6 py-3 px-lg-5'> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> </div> <?php endforeach; ?> </div> </div> ... the problem I have is from a design perspective. Using a flexbox grid means columns are equal height. Each row contains three columns on desktop. Now, if one column has shorter content than the next one, there is large white space under it because it doesn't fill the column vertically (but the longer ones do). You end up with this: ------------------------------------------------------------------------------ Title Title Title ngjkagas ndjskagdasj njgksgnjsk gdjkgasjk gdjskgbjksa gdasjgkads gndjaskgnjdasnjg ds gbdjskgbdjkab dgasnjk jgfksjgfds jgdksajkgds njdkajda njdasxlhs gf jkdgjsagjdajdasdga fdjakfdbjak fhdjkahf fdbjabfdj fdjsjkakjka ------------------------------------------------------------------------------ Title Title Title ngjkagas ndjskagdasj njgksgnjsk gdjkgasjk gdjskgbjksa gdasjgkads gndjaskgnjdasnjg ds gbdjskgbdjkab dgasnjk jgfksjgfds jgdksajkgds njdkajda njdasxlhs gf jkdgjsagjdajdasdga fdjakfdbjak fhdjkahf fdbjabfdj fdjsjkakjka fnfsjsjs dhhdsjsjds fdnsjkfdjs fdhj dhksd ------------------------------------------------------------------------------ So I thought I'd get the original PageArray, split it into two equal parts, then just loop the two new arrays into two columns. to get this: -------------------------------- -------------------------------- Title Title ngjkagas ndjskagdasj gdjskgbjksa gdasjgkads gndjaskgnjdasnjg ds gbdjskgbdjkab dgasnjk njdkajda njdasxlhs gf jgfksjgfds jgdksajkgds jkdgjsagjdajdasdga fdjakfdbjak fhdjkahf Title fdbjabfdj fdjsjkakjka jfdksahfjka hfdjkasfhjdafalk fnfsjsjs dhhdsjsjds ndjskagjka hdsk hjkdsahjkgd fdnsjkfdjs fdhj dhksd jgdskgksa hgdjskahgjdashgkdas Title Title ngjkagas ndjskagdasj gdjskgbjksa gdasjgkads gndjaskgnjdasnjg ds gbdjskgbdjkab dgasnjk njdkajda njdasxlhs gf jgfksjgfds jgdksajkgds jkdgjsagjdajdasdga fdjakfdbjak fhdjkahf Title fdbjabfdj fdjsjkakjka jfdksahfjka hfdjkasfhjdafalk fnfsjsjs dhhdsjsjds ndjskagjka hdsk hjkdsahjkgd fdnsjkfdjs fdhj dhksd jgdskgksa hgdjskahgjdashgkdas -------------------------------- -------------------------------- So my new code is sketchy and I could do with some help to possibly refactor and also to fill in the gaps where my knowledge fails. Here it is so far: <?php namespace ProcessWire; ?> <?php // get PageArray of all testimonials (which is a repeater: title, testimonialReviewee, testimonialReviewee) $arr = $page->testimonials; // shuffle them $arr->shuffle(); // grab the first one $firstTestimonial = $arr->first(); // grab the others $otherTestimonials = $arr->not("$firstTestimonial"); // get total items in array $numberOfItems = count($otherTestimonials); // return new PageArray (half of $otherTestimonials) $firstHalfArr = $otherTestimonials->slice(0, ($numberOfItems / 2)); // return new PageArray (half + 1) to end $secondHalfArr = $otherTestimonials->slice(($numberOfItems / 2) + 1, $numberOfItems); ?> <div class="jumbotron jumbotron-fluid bg-color"> <div class="container"> <h2><?= $firstTestimonial->title; ?></h2> <p><?= $firstTestimonial->testimonialBody; ?> - <i><?= $firstTestimonial->testimonialReviewee; ?></i></p> </div> </div> <div class='container'> <div class='row'> <div class='col-6'> <?php foreach($firstHalfArr as $testimonial): ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> <?php endforeach; ?> </div> <div class='col-6'> <?php foreach($secondHalfArr as $testimonial): ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> <?php endforeach; ?> </div> </div> </div> Sure you guys don't need the comments but it helps me as I go along to build the logic. The obvious problem is what happens when the PageArray contains an odd number of items. Is there a round method or something? If I round incorrectly though, I think maybe one testimonial item would be missed i.e. [0,1,2,3] and [5,6,7,8]. Anyway, the problem I'm having right now in PHP and JS as I learn is thinking like a programmer. I'm getting better at reading technical docs and using methods from instructions etc. but the thinking like a programmer bit (logic included) eludes me somewhat. I'll get there in the end. Any advice is appreciated as always. Thanks. (p.s. I am aware of CSS3 column-count) 1 Link to comment Share on other sites More sharing options...
SamC Posted July 21, 2017 Author Share Posted July 21, 2017 Actually, this seems to work: <?php namespace ProcessWire; ?> <?php // get PageArray of all testimonials (which is a repeater: title, testimonialReviewee, testimonialReviewee) $arr = $page->testimonials; // shuffle them $arr->shuffle(); // grab the first one $firstTestimonial = $arr->first(); // grab the others $otherTestimonials = $arr->not("$firstTestimonial"); // get total of half the array $numberInFirstHalf = ceil(count($otherTestimonials) / 2); // return new PageArray (half of $otherTestimonials) $firstHalfArr = $otherTestimonials->slice(0, $numberInFirstHalf); // return new PageArray (halfway to end) $secondHalfArr = $otherTestimonials->slice($numberInFirstHalf, $numberOfItems); ?> <div class="jumbotron jumbotron-fluid bg-color"> <div class="container"> <h2><?= $firstTestimonial->title; ?></h2> <p><?= $firstTestimonial->testimonialBody; ?> - <i><?= $firstTestimonial->testimonialReviewee; ?></i></p> </div> </div> <div class='container'> <div class='row'> <div class='col-6'> <?php foreach($firstHalfArr as $testimonial): ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> <?php endforeach; ?> </div> <div class='col-6'> <?php foreach($secondHalfArr as $testimonial): ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> <?php endforeach; ?> </div> </div> </div> I get one main one featured at top, 3 in left column and 2 in right column, total of 6 testimonials. 1 Link to comment Share on other sites More sharing options...
Robin S Posted July 21, 2017 Share Posted July 21, 2017 Nice one. Just another way to skin the cat... <?php $testimonials = $page->testimonials; $testimonials->shuffle(); $firstTestimonial = $testimonials->shift(); ?> <div class="jumbotron jumbotron-fluid bg-color"> <div class="container"> <h2><?= $firstTestimonial->title; ?></h2> <p><?= $firstTestimonial->testimonialBody; ?> - <i><?= $firstTestimonial->testimonialReviewee; ?></i></p> </div> </div> <div class='container'> <div class='row'> <div class='col-6'> <?php foreach($testimonials as $index => $testimonial): ?> <?php if($index == ceil(count($testimonials) / 2)): ?> </div> <div class='col-6'> <?php endif; ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold text-muted">- <i><?= $testimonial->testimonialReviewee; ?></i></p> <?php endforeach; ?> </div> </div> </div> 5 Link to comment Share on other sites More sharing options...
SamC Posted July 21, 2017 Author Share Posted July 21, 2017 Thanks I was thinking of a way avoid repeating that block twice when only the array differs between the two. Not 100% on what these lines do though, using a key=>value instead of the way I did it: Just now, Robin S said: <?php foreach($testimonials as $index => $testimonial): ?> <?php if($index >= count($testimonials) / 2): ?> What's the value of $index here for each loop? This code confuses me somewhat with the div placement. Nice and short though, I like it! I also extended it now to include a page ref field in the repeater: ...so you can choose which site the review came from (with the site title and URL stored in a different template)... ...works quite well, and having the reviews out of the standard 3 across grid looks so much better to me. Glad to be back using PW. Paid job this one. 1 Link to comment Share on other sites More sharing options...
Robin S Posted July 21, 2017 Share Posted July 21, 2017 18 minutes ago, SamC said: What's the value of $index here for each loop? This code confuses me somewhat with the div placement. Nice and short though, I like it! $index is the key of the array item, which in the case of a PageArray like this is the zero-based index of the item in the array. So it starts at 0 and goes up with each subsequent item. The "</div><div class='col-6'>" portion is where we end the first column and start the second column. There was an error in my code which I have corrected now - we only want this inserted once, when $index matches half the number of items in $testimonials rounded up to the nearest whole number. 2 Link to comment Share on other sites More sharing options...
SamC Posted July 22, 2017 Author Share Posted July 22, 2017 Thanks for the explanation @Robin S, you're a gent! I understand it now, final code: <?php namespace ProcessWire; ?> <?php $testimonials = $page->testimonials; $testimonials->shuffle(); $firstTestimonial = $testimonials->shift(); ?> <div class="jumbotron jumbotron-fluid bg-color"> <div class="container"> <h2><?= $firstTestimonial->title; ?></h2> <p><?= $firstTestimonial->testimonialBody; ?></p> <p class="font-weight-bold"> <i><?= $firstTestimonial->testimonialReviewee; ?> - Review from <a href='<?= $firstTestimonial->reviewSitePageRef->reviewSiteURL; ?>' target='_blank'> <?= $firstTestimonial->reviewSitePageRef->title; ?></a> </i> </p> </div> </div> <div class='container'> <div class='row py-5'> <div class='col-sm-12 col-md-6 px-lg-5'> <?php foreach($testimonials as $index => $testimonial): ?> <?php if($index == ceil(count($testimonials) / 2)): ?> </div> <div class='col-sm-12 col-md-6 px-lg-5'> <?php endif; ?> <h2 class='py-3'><?= $testimonial->title; ?></h2> <p><?= $testimonial->testimonialBody; ?></p> <p class="font-weight-bold"> <i><?= $testimonial->testimonialReviewee; ?> - Review from <a href='<?= $testimonial->reviewSitePageRef->reviewSiteURL; ?>' target='_blank'> <?= $testimonial->reviewSitePageRef->title; ?></a> </i> </p> <?php endforeach; ?> </div> </div> </div> I see that shift() removes the first item of an array and returns it so seems a neat way to extract the first item leaving the rest in the original array. Found the guide here: https://processwire.com/api/arrays/page/ Anyway, thanks again On a side note, I also found a 404 on the PW site where I would have expected a page: 1) Go to https://processwire.com/api/ref/ 2) Choose something from dropdown, say $page, takes you here: https://processwire.com/api/ref/page/ 3) Back to dropdown, choose 'API Reference...' at the very top (I wanted to go back to the root at https://processwire.com/api/ref/ ) 4) Takes you here instead: https://processwire.com/api/ref/class-loader/API Reference … Maybe someone can have a look. Might be intended behaviour but thought I'd mention it. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now