Jump to content

Best way to output multiple, HTML formatted pages from pagearray?


kathep
 Share

Recommended Posts

Hey all,

I have a small problem. I am trying to output a formatted list of categories (fieldname & parent page are both called design_technique) from a Multipage array associated with the current page.

I have got as far as showing two of the categories (see below):

post-2947-0-85401100-1421170563_thumb.pn

But when there are more than two categories in the multipage array, I get stuck. 

The code that works to get the first and second categories is this:

$read_test = '';

$design_tech = $page->design_technique; 

if($design_tech instanceof PageArray) {
	foreach($design_tech as $item) {
		$read_test = "<h3>On the same design skills</h3> <h4>" . $page->design_technique->first->title . "</h4>" . "<p> Placeholder where article in this category should go. </p> <h4>" . $page->design_technique->getNext($page->design_technique->first)->title . "</h4> <p> Placeholder where article in this category should go. </p> ";
	}
}

For the third category output, I have tried slice() like this:

<h4>" . $page->design_technique->slice(3, 4)->title . "</h4> <p> Placeholder where article in this category should go. </p>";

And I have also tried looping getNext() like this:

<h4>" . $page->design_technique->getNext($page->design_technique->getNext)->title . "</h4> <p> Placeholder where article in this category should go. </p>";

Neither has worked. 

In other situations i have used implode() to generate a list of items in a pageArray, but since I want the HTML formatting, and eventually more php calls where the placeholder text is right now, I am stuck. 

Does anyone have any idea of how to get this code to work? 

Link to comment
Share on other sites

Hey @kathep

You just need to use:

$item->title etc, rather than trying to get each different item from the original page field array. You are already accessing each item inside your foreach loop.

Does that make sense?

  • Like 1
Link to comment
Share on other sites

As Adrian already mention you're already in the loop. So you'll need to reference $item instead of $page.

$read_test = '';
 
$design_tech = $page->design_technique; 
 
if($design_tech instanceof PageArray) {
	foreach($design_tech as $item) {
		$read_test = "<h4>" . $item->title . "</h4>";
	}
}
  • Like 5
Link to comment
Share on other sites

Ah ok! Thank you @adrian and @nghi. But then for my next question...

I find this solution doesn't work when I replace the placeholder text with correct code. This code:

$read_test = '';

$design_tech = $page->design_technique; 

$readings_dt = $pages->find("template=readings, design_technique=$page->design_technique");

if($design_tech instanceof PageArray) {
	foreach($readings_dt as $item){
	$readings_test_list .= "<p> '<a href=$item->url>" . $item->title . "</a>' " . "-" . $item->book_section_reading_time->title . "</p>";
	}
	foreach($design_tech as $item) {
		$read_test = "<h3>On the same design skills</h3> <h4>" . $item->title . "</h4>" . $readings_test_list ;
	}
}

... only outputs the last field and associated reading in the design_technique field. Like this:

post-2947-0-76201700-1421179718_thumb.pn

I want the code to show each of the three categories (Pantone, CMYK, RGB), and a list of every reading associated with that category. But I don't know how to tell the code to do this!

What would be the best way to get each category to display with the associated readings (design_technique->title) and time (design_technique->book_section_reading_time->title) below it?

I suspect this is really simple, just beyond my knowledge  :mellow:

Link to comment
Share on other sites

There's a weird check in your logic that seems to be unnecessary. Not that it's prevent your code from working.

design_technique is a field type of page set to multiple as you told us. 

So the if($design_tech instanceof PageArray) statement will always be true, thus no need to check it.

Link to comment
Share on other sites

@Martijn Geerts ah yes, this is my probably-not-very-good way of writing 

'If this page has something in the design_tech field, show the following code.' Not all pages with the 'readings' template have the design_tech field, and where it does not occur, I don't want the associated HTML to appear.

If there is a better way to write this, please let me know!


@horst I think we replied at the same time. I am now trying the code with the concat dot....

  • Like 1
Link to comment
Share on other sites

UPDATE: Not resolved!

It worked, mostly! The only thing stopping @nghi's code from working was a missing concat dot that @horst pointed out. 

Thank you all for your help. I am learning so much, and having so much fun.

  • Like 2
Link to comment
Share on other sites

One more related question: what is the best way to filter out the current page from the pageArray results?

The code I'm using lists all readings in the category, including the current page. It would be better if I could filter out the current page from all results. 

Link to comment
Share on other sites

UPDATE: Duplicating output issue
 
I've been working on this since my last post, and I have made some progress. Removed current page from pageArray thanks to @LostKobrakai. However, I've noticed a problem with my code that calls the readings.
 
This output is being generated:
post-2947-0-47586000-1421190315_thumb.pn
 
The code is collecting all readings related to all all categories, and outputting the entire list under each category heading.
 
Here is the incorrect code:

$design_prin_rel = $page->design_principle_related; 
 
$readings_dpr = $pages->find("template=readings, design_principle=$page->design_principle_related");
 
if($design_prin_rel instanceof PageArray) { $dpr_heading = "<h3>On related design principles</h3> "; foreach($readings_dpr as $item){ $readings_test2_list .= "<p> '<a href=$item->url>" . $item->title . "</a>' " . "-" . $item->book_section_reading_time->title . "</p>"; } foreach($design_prin_rel as $item) { $read_test2 .= "<h4>" . $item->title . "</h4>" . $readings_test2_list; } }

 
I know what's wrong with it, but I don't know how to fix it.

Avoiding this problem was the reason I was trying to use getNext() and slice() initially, when I started this thread, but I didn't get so far with that experiment.
 
Any suggestions of how I can get each (design_technique->title) and time (design_technique->book_section_reading_time->title) displayed to relate only to the category immediately displayed above it?

Link to comment
Share on other sites


if($design_prin_rel instanceof PageArray){

$related = "<h3>On related design principles</h3>";

foreach($design_prin_rel as $category){

$related .= "<h4>" . $category->title . "</h4>";

foreach($readings_dpr->find("selector to get only pages for $category") as $item){

$related .= "<p> '<a href=$item->url>" . $item->title . "</a>' " . "-" . $item->book_section_reading_time->title . "</p>";

}

}

}

Link to comment
Share on other sites

Thanks @LostKobrakai. I see how your code makes more semantic sense. However, I am stuck on finding this missing piece: 

"selector to get only pages for $category"

Can anyone provide me with a clue to get closer to the code for this selector?

I am looking for a selector that will find the value of the previous $category->title, and then return only the fields (design_technique->title and design_technique->book_section_reading_time->title) related to it.

Link to comment
Share on other sites

You don’t have to get all pages in one go. Just keep it simple. LostKobrakai is showing a good solution where he looks at each design principle and only gets the pages that belong to it. I would like to suggest one minor improvement: Before you build the markup, you should check whether you actually found some pages. You might come across an empty category with no links, which might look awkward.

Also, when you put a hyphen before the reading time, it makes it look like a negative number. Try ' &endash; ' or '&emdash;'. Those are the – much nicer looking – dashes I’m using here.

To answer your follow up question, look at how LostKobrakai handles all design principles individually, by putting each one into the variable $category one after the other. What you want to find are readings that have the current $category page as their design principle, not the previous. Try this:

"template=readings, design_principle=$category"
  • Like 3
Link to comment
Share on other sites

@Jan Romero your post helped me understand @LostKobrakai's better.

I have replaced the minus signs with en dashes, thanks :)

I would like to check whether I found some pages - now that I have added the remove($page), I do get some empty results. However, I have no idea how to check. Could you suggest a link for me to learn from, or some code?

Link to comment
Share on other sites

You can either use $pages->count("selector") the same way as find, just you receive a number of pages. Or you could also use $pageArray->count(), but then all the pages of the array have to be loaded, while the first one counts on the database level, without loading the pages into php. The standart php count($pageArray) works the same way as $pageArray->count().

if($design_prin_rel instanceof PageArray){
  $related = "<h3>On related design principles</h3>";

  foreach($design_prin_rel as $category){
    // Only do stuff, if it's not 0; 0 == false, so no real need to have ... > 0
    if($readings_dpr->count("selector to get only pages for $category")){ 
      $related .= "<h4>" . $category->title . "</h4>";

      foreach($readings_dpr->find("selector to get only pages for $category") as $item){
        $related .= "<p> '<a href=$item->url>" . $item->title . "</a>' " . "-" . $item->book_section_reading_time->title . "</p>";
      }
    }
  }
}

To learn/discover the api I would suggest having a look at this: http://cheatsheet.processwire.com. Don't forget the advanced mode. 

For more "in context" examples have a look here: http://processwire.com/docs/

  • Like 3
Link to comment
Share on other sites

@LostKobrakai Thanks for the code and learning tips! I am using the API cheatsheet a lot, but I didn't know about the 'advanced' mode! That will be very helpful.

I have more knowledge than the 'beginner' tutorials are suitable for, but not enough to understand much on the forum posts outside of 'getting started'. I think there is a big gap in documentation. That is why I keep posting long explanations of things I am learning! Hopefully it will help other tinkerers like myself some day.

Thanks again :) Will play with this count code more. 

Link to comment
Share on other sites

if you not already know this, here is a grouped collection maintained by @pwired: https://processwire.com/talk/topic/4173-grouped-forum-posts-links-articles-tutorials-code-snippets/

@teppo has some things on his site: http://www.flamingruby.com/blog/php-for-template-designers/ (just ignore this twig stuff, focus on the php side), and there are more articles.

The recipes are new but continousliy growing: https://processwire-recipes.com/

...

  • Like 1
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...