Jump to content

Cleaning a foreach loop


3fingers
 Share

Recommended Posts

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?

:undecided:

 

Link to comment
Share on other sites

<?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..

  • Like 1
Link to comment
Share on other sites

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.

  • Like 2
Link to comment
Share on other sites

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>
    ";
}

 

  • Like 2
Link to comment
Share on other sites

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>";

 

  • 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...