3fingers Posted December 8, 2016 Share Posted December 8, 2016 Hello guys, here is my messy code, I'm here to ask for a help in refactoring a foreach loop: $grandchildred = $page->children(); foreach ($grandchildred as $grandchild) { $children = $grandchild->children(); $outGrandchild = ''; /* MARKUP FOR GRANDCHILD */ $outGrandchild.= "<div class='uk-grid uk-grid-large'>"; $outGrandchild.= "<div class='uk-width-medium-1-3'>"; $outGrandchild.= "<div class='uk-panel uk-panel-box prodotto__panel-mod'>"; $outGrandchild.= "<div class='uk-panel-teaser'>"; $outGrandchild.= "<div class='uk-cover-background' style='background-image: url({$grandchild->product_image->url});'>"; $outGrandchild.= "<img class='uk-invisible' src='{$grandchild->product_image->url}' width='600' height='400' alt='Placeholder'>"; $outGrandchild.= "</div></div></div>"; $outGrandchild.= "<a class='prodotto__panel-links prodotto__panel-links-blue' href='{$grandchild->url}'><span>Discover more</span></a>"; $outGrandchild.= "</div>"; $outGrandchild.= "<div class='uk-width-medium-2-3'>"; $outGrandchild.= "<div class='prodotto__descr'><span>{$grandchild->product_options->title}</span>"; $outGrandchild.= "<h3 class='shadow-blue'>{$grandchild->title}</h3>"; $summary = truncateText($grandchild->product_description); $outGrandchild.= "<p>{$summary}</p><p><a href='{$grandchild->url}'><i class='uk-icon-chevron-circle-right uk-margin-small-right'></i>Link</a></p>"; $outGrandchild.= "</div></div></div>"; $outChild = ''; foreach ($children as $child) { /* MARKUP FOR CHILDREN - IT'S THE SAME AS ABOVE */ // HOW CAN I AVOID TO REWRITE IT? $outChild.= "<div class='uk-grid uk-grid-large'>"; $outChild.= "<div class='uk-width-medium-1-3'>"; $outChild.= "<div class='uk-panel uk-panel-box prodotto__panel-mod'>"; $outChild.= "<div class='uk-panel-teaser'>"; $outChild.= "<div class='uk-cover-background' style='background-image: url({$child->product_image->first()->url});'>"; $outChild.= "<img class='uk-invisible' src='{$child->product_image->first()->url}' width='600' height='400' alt='Placeholder'>"; $outChild.= "</div></div></div>"; $outChild.= "<a class='prodotto__panel-links prodotto__panel-links-blue' href='{$child->url}'><span>Discover more</span></a>"; $outChild.= "</div>"; $outChild.= "<div class='uk-width-medium-2-3'>"; $outChild.= "<div class='prodotto__descr'><span>{$child->product_options->title}</span>"; $outChild.= "<h3 class='shadow-blue'>{$child->title}</h3>"; $summary = truncateText($child->product_description); $outChild.= "<p>{$summary}</p><p><a href='{$child->url}'><i class='uk-icon-chevron-circle-right uk-margin-small-right'></i>Link</a></p>"; $outChild.= "</div></div></div>"; } /* OUTPUT CONDITION */ if(!count($grandchild->children())){ echo $outGrandchild; } else { echo $outChild; } } $grandchild and $children shares the same markup, but sometimes I just want to echo out $grindchild when they haven't $children. How can I code this in a more elegant way? Link to comment Share on other sites More sharing options...
Macrura Posted December 8, 2016 Share Posted December 8, 2016 <?php function renderUkGrid($page) { $summary = truncateText($page->product_description); $out = "<div class='uk-grid uk-grid-large'>"; $out .= "<div class='uk-width-medium-1-3'>"; $out .= "<div class='uk-panel uk-panel-box prodotto__panel-mod'>"; $out .= "<div class='uk-panel-teaser'>"; $out .= "<div class='uk-cover-background' style='background-image: url({$page->product_image->url});'>"; $out .= "<img class='uk-invisible' src='{$page->product_image->url}' width='600' height='400' alt='Placeholder'>"; $out .= "</div></div></div>"; $out .= "<a class='prodotto__panel-links prodotto__panel-links-blue' href='{$page->url}'><span>Discover more</span></a>"; $out .= "</div>"; $out .= "<div class='uk-width-medium-2-3'>"; $out .= "<div class='prodotto__descr'><span>{$page>product_options->title}</span>"; $out .= "<h3 class='shadow-blue'>{$page->title}</h3>"; $out .= "<p>{$summary}</p><p><a href='{$page->url}'><i class='uk-icon-chevron-circle-right uk-margin-small-right'></i>Link</a></p>"; $out .= "</div></div></div>"; return $out; } foreach($page->children() as $grandchild) { if($grandchild->children()) { foreach($grandchild->children() as $child) { echo renderUkGrid($child); } } else { echo renderUkGrid($grandchild); } } i think this is how i would do it, or i wouldn't use a function, and have a partial for the markup and then do a wireRenderFile(); in either case i would keep the markup out of the loop.. 1 Link to comment Share on other sites More sharing options...
blynx Posted December 8, 2016 Share Posted December 8, 2016 This is very exemplary and you have to apply it to your loop, still: But you can put the small piece into a seperate .php file - for example /templates/partials/piece.php Have a look at http://processwire.com/api/ref/files/render/ Then, you could: <?php // template file $output = $files->render('partials/piece.php', ['value' => $data]) // or with the loop $output = '' foreach($items as $item) { $output .= $files->render('partials/piece.php', ['value' => $item]) } The partial piece.php could be this, I really like the php style to have plain HTML and only insert small php tags where necessary: (It looks nice in my editor, too) <div class="some-grid"> <div> <?= $value->object_prop ?> </div> <div> <?= $value['array_elem'] ?> </div> <ul> <?php foreach($value->data as $item): ?> <li><?= $item->property ?></li> <?php endforeach ?> </ul> </div> PS: You might also want to have a look at https://processwire.com/blog/posts/processwire-3.0.7-expands-field-rendering-page-path-history-and-more/ "field rendering with template files" - again, I am recommending the same stuff all over - but it really helps structuring the files. 2 Link to comment Share on other sites More sharing options...
3fingers Posted December 8, 2016 Author Share Posted December 8, 2016 You are both providing good adivices and code. I did dozen times what @Macrura wrote...but that's what happens when you got a 5 months baby crying all night long: your mind blows :). Thanks @blynx too, I'm going to investigate more on It. 1 Link to comment Share on other sites More sharing options...
adrian Posted December 8, 2016 Share Posted December 8, 2016 Based on @Macrura's example - maybe just a personal preference more than anything, but I prefer the look of this. I do think it really helps to indent the code though function renderUkGrid($page) { return " <div class='uk-grid uk-grid-large'> <div class='uk-width-medium-1-3'> <div class='uk-panel uk-panel-box prodotto__panel-mod'> <div class='uk-panel-teaser'> <div class='uk-cover-background' style='background-image: url({$page->product_image->url});'> <img class='uk-invisible' src='{$page->product_image->url}' width='600' height='400' alt='Placeholder'> </div> </div> </div> <a class='prodotto__panel-links prodotto__panel-links-blue' href='{$page->url}'><span>Discover more</span></a> </div> <div class='uk-width-medium-2-3'> <div class='prodotto__descr'><span>{$page>product_options->title}</span> <h3 class='shadow-blue'>{$page->title}</h3> <p>".truncateText($page->product_description)."</p> <p><a href='{$page->url}'><i class='uk-icon-chevron-circle-right uk-margin-small-right'></i>Link</a></p> </div> </div> </div> "; } 2 Link to comment Share on other sites More sharing options...
tpr Posted December 8, 2016 Share Posted December 8, 2016 Definitely better - I would also recommend looking into the heredoc syntax. 2 Link to comment Share on other sites More sharing options...
BitPoet Posted December 8, 2016 Share Posted December 8, 2016 2 hours ago, blynx said: $output = $files->render('partials/piece.php', ['child', $data]) Shouldn't that read 'piece' instead of 'child', since you're using $piece in piece.php? 1 Link to comment Share on other sites More sharing options...
blynx Posted December 8, 2016 Share Posted December 8, 2016 @BitPoet Yep! Thanks! I corrected it and took a more generic name - also I had commas instead of '=>' !! The point is, the keys of the array passed in $files->render() become exposed as variables in the fetched .php partial. Link to comment Share on other sites More sharing options...
Martijn Geerts Posted December 8, 2016 Share Posted December 8, 2016 I have a slightly different pattern as @adrian & @Macrura, this way there are no un necessary whitespace characters in HTML $out = "<div class='uk-grid uk-grid-large'>" . "<div class='uk-width-medium-1-3'>" . "<div class='uk-panel uk-panel-box prodotto__panel-mod'>" . "<div class='uk-panel-teaser'>" . "<div class='uk-cover-background' style='background-image: url(" . $page->product_image->url . ");'>" . "<img class='uk-invisible' src='" . $page->product_image->url . "' width='600' height='400' alt='Placeholder'>" . "</div>" . "</div>" . "</div>" . "<a class='prodotto__panel-links prodotto__panel-links-blue' href='" . $page->url . "'>" . "<span>Discover more</span>" . "</a>" . "</div>" . "<div class='uk-width-medium-2-3'>" . "<div class='prodotto__descr'>" . "<span>" . $page->product_options->title . "</span>" . "<h3 class='shadow-blue'>" . $page->title . "</h3>" . "<p>" . (truncateText($child->product_description)) . "</p>" . "<p>" . "<a href='" . $page->url . "'>" . "<i class='uk-icon-chevron-circle-right uk-margin-small-right'></i>Link". "</a>" . "</p>" . "</div>" . "</div>" . "</div>"; 1 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