Peter Knight Posted August 22, 2017 Share Posted August 22, 2017 I have a complicated, nested IF statement which I'm trying to clean up. Right now it works and only displays if user=superuser a matrix item of type 'related_product' exists My main issue is I have two of the follwoing foreach($page->related_products as $matrix_item) {} If I delete the first one, the page throws a server error if I delete the second one and it's opening and closing curly bracket, only a single related product displays. In reality there are 4. I shouldn't need two of these in my code but I'm clearly micing up my end curly brackets or something <!-- Gets the related products at the bottom of the page --> <?php // For each related_products in Matrix field set a variable called $matrix_item foreach($page->related_products as $matrix_item) {} // START IF statement: superuser and related product if (($user->hasRole("superuser")) && ($matrix_item->type == 'related_product')) { echo " <div class='uk-section uk-section-muted section-related'> <div class='uk-container'> <h3>Related Products</h3> <div class='uk-grid-match uk-child-width-1-4@s' uk-grid> "; // For each related_products in Matrix field set a variable called $matrix_item foreach($page->related_products as $matrix_item) { // For every child page of the related_random page, output a single random one based on the product template... foreach ($matrix_item->related_random->children('template=product, sort=random, limit=1') as $prod) { // output this echo " <div> <div class='rel-prod-ov-wrapper'> <a href='$prod->url'> <img src='{$prod->images->first()->url}' class='rel-prod-preview'> </a> <div class='rel-prod-ov-text'> <span class='rel-preview-title'><strong>Part No:</strong> {$prod->title}</span> <br/> {$prod->prod_summary} <a href='$prod->url' class='uk-icon-button rel-icon-linky' uk-icon='icon: chevron-right'></a> </div> </div> </div> "; } } echo " </div> </div> </div> "; } // END IF statement: superuser and related product ?> Link to comment Share on other sites More sharing options...
abdus Posted August 22, 2017 Share Posted August 22, 2017 This code seems to render a repeater matrix, are you using field render functionality? Like echo $page->render->matrix_field which uses /site/templates/fields/matrix_field.php? If so, you can divide your code into multiple files for each matrix type and put those under /site/templates/fields/matrix_field/type1.php and so on. https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/#processwire-3.0.5-introduces-field-rendering-with-template-files There's also wireRenderFile() to render a template file with given variables and return string output. I use it a lot in my templates. https://processwire.com/blog/posts/processwire-2.5.2/#new-wirerenderfile-and-wireincludefile-functions I tried to clean up your code. Some remarks: If you know there's only one page in a wirearray, you can get it with $arr->first Use if(! $some_condition) return; to reduce nesting You can open and close <?php ?> tags to give yourself some flexibility, so you wont have to put your HTML inside PHP strings. Anything you put between php tags will be echoed. <?php namespace ProcessWire; // dont show if user is not superuser if (!$user->hasRole('superuser')) return; // dont display partial markup if there are no related products if(!$page->related_products->count) return; // used for picking a random product from related products $randomSelector = 'template=product, sort=random, limit=1'; ?> <div class='uk-section uk-section-muted section-related'> <div class='uk-container'> <h3>Related Products</h3> <div class='uk-grid-match uk-child-width-1-4@s' uk-grid> <?php foreach ($page->related_products as $matrix_item): ?> <?php $randomProd = $matrix_item->related_random->children($randomSelector)->first; ?> <div class='rel-prod-ov-wrapper'> <a href='<?= $randomProd->url ?>'> <img src='<?= $randomProd->images->first()->url ?>' class='rel-prod-preview'> </a> <div class='rel-prod-ov-text'> <span class='rel-preview-title'><strong>Part No:</strong> <?= $randomProd->title ?></span><br/> <?= $randomProd->prod_summary ?> <a href='<?= $randomProd->url ?>' class='uk-icon-button rel-icon-linky' uk-icon='icon: chevron-right'> <!-- THERE SHOULD BE SOME TEXT HERE --> </a> </div> </div> <?php endforeach; ?> </div> </div> </div> Not sure if this works, there are some parts I couldnt make sense, but it should give you some ideas. If you give more info, I might be able to help you better 2 Link to comment Share on other sites More sharing options...
fbg13 Posted August 22, 2017 Share Posted August 22, 2017 33 minutes ago, Peter Knight said: foreach($page->related_products as $matrix_item) {} If I delete the first one, the page throws a server error if I delete the second one and it's opening and closing curly bracket, only a single related product displays. In reality there are 4. The first loop assigns each item in $page->related_products to $matrix_item, so you have one $matrix_item after the first loop. When you delete the first empty loop you will have no $matrix_item anymore in your if statement. When you delete the second one then you will have only one $matrix_item, from your first empty loop. 3 Link to comment Share on other sites More sharing options...
szabesz Posted August 23, 2017 Share Posted August 23, 2017 I would also like to point out what @abdus also did in his example: I try to avoid expressions like these: <?php foreach($page->related_products as $matrix_item) {} foreach ($matrix_item->related_random->children('template=product, sort=random, limit=1') as $prod) {} instead: <?php $related_products = $page->related_products; foreach(related_products as $matrix_item) {} $random_children = $matrix_item->related_random->children('template=product, sort=random, limit=1'); foreach ($random_children as $prod) {} Often easier to read but most importantly one can inject bd($random_children) /Tracy/ or error_log(print_r($random_children,true)); into the code to debug the result sets. BTW, I also use the "style" @abdus presented. PHP is A templating engine itself and that is how a native PHP template looks. 1 Link to comment Share on other sites More sharing options...
Peter Knight Posted August 23, 2017 Author Share Posted August 23, 2017 Thanks guys.. @abdus I'm not familiar with a lot of your method but I'm looking forward to reading up on them and improving my PHP. I'm not familiar with return for example. In the short term I might break down my single PHP block into smaller more manageable blocks and rework it a little. I did try using your example to test it and I got a server error but aside from that am I correct in thinking that the actual Related Product heading isn't based on any conditional. @szabesz and @fbg13 thanks for the tips. 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