MySQL to PHP output HTML with grouped content (categories) - php

i have problem that i googled allot to try and figure out, but all solutions are variations on mine.
So i have output like this
<div class="row">
<?php $cat= '';?>
<div class="blank">
#foreach($posts as $post)
#if($cat!= $post->cat_id)
</div><div class="col-sm-3">
<p class="alert alert-info"><strong>{{$post->category_name}}</strong></p>
<?php $cat= $post->cat_id; ?>
#endif
</ul><ul>
<li>
{{$post->title}}
</li>
#endforeach
So basically i wont output that category name is in and then all the posts of that category within that div in ul li, and then close the DIV.
But i managed to make it only with this blank div, and closing ul and div before open, but that gives me invalid html, but its sorted good.
Is there any smart way to get this done?
Thanks

here is a working example. I think the problem was the place where you were opening and closing the foreach.
...
(I replaced the blade statements for plain php for clarity, but you should be able to change it back.)
EDIT:
I was not that far..
<?php $posts = [
['cat_id' => 1, 'cat_name' => 'a name', 'title' => 'title'],
['cat_id' => 1, 'cat_name' => 'a name2', 'title' => 'title2'],
['cat_id' => 2, 'cat_name' => 'another name', 'title' => 'title3'],
['cat_id' => 2, 'cat_name' => 'another name2', 'title' => 'title4'],
]; ?>
<div class="col-sm-3">
<?php $cat= '';?>
<?php foreach($posts as $post): ?>
<?php if($post['cat_id'] != $cat): ?>
<p class="alert alert-info">
<strong><?php echo $post['cat_name'];?></strong>
</p>
<ul>
<?php endif; ?>
<li> <?=$post['cat_name'];?> </li>
<?php if($post['cat_id'] == $cat): ?>
</ul>
<?php endif; ?>
<?php $cat= $post['cat_id']; ?>
<?php endforeach; ?>
</div>
Here I edited my previous answer, a few recommendations tho:
The point is not to just write code that works, but also maintainable and readable. That will help you or whoever has to change some functionality in the future.
Try to be as clear as you can be when asking, and provide an example of your desired output if needed (just like in the comment).
You could probably format the data before passing it to the view, so you can print it easily, for example, transforming the array I used in the above code to something like:
$posts = [
['cat_id' => 1, 'cat_name' => 'a name', 'posts' => [
['title' => 'a title','content' => 'whatever'],
['title' => 'another title','content' => 'whatever2'],
]
];
That way it would be waaay easier to show it, and it'll give you ways to
write clearer code.
Best regards!

So after extensive trying, i got what i wanted. Hope this is correct way of doing it.
<?php
$cat= '';
foreach($posts as $post){
if($cat != $post['cat_id']){
echo $cat!= '' ? '</ul></div>' : '';
echo '<div class="col-sm-4 col-md-3">
<p class="alert alert-info"><strong>'.$post['cat_name'].'</strong></p>
<ul>';
$cat= $post['cat_id'];
}
echo '<li>'.$post['title'].'</li>';
}
echo '</ul>'; //close last opened ul
echo '</div>'; //close last opened div
?>

Related

adding attributes Html::img yii2

I add images to the page, to which I add some attributes
<?php
$data = [
[
'data-z-index' => 1,
'data-width' => 300,
]
];
?>
<?php foreach ($posts as $i => $item) { ?>
<div class="item">
<?php if ($item->img) { ?>
<?= Html::img($item->img->getUrl(), $data[$i]) ?>
<?php } ?>
</div>
<?php } ?>
As a result, on the page all this works for me and I get
<img src="//test.loc/storage/posts-image/1-2.jpg" alt="" data-z-index="1" data-width="300">
Now I also want to add an alt attribute that will come from the database
<?= Html::img($item->img->getUrl(), [$data[$i], 'alt' => $item->img_alt]) ?>
But now the attribute formatting is changing and 0 appears at the beginning
<img src="//test.loc/storage/posts-image/1-2.jpg" alt="post1" 0-data-z-index="1" 0-data-width="300">
What could be the problem?
It's because $data is an array. So you have a nested array as options.
Try to merge the arrays:
array_merge($data[$i], ['alt' => $item->img_alt]);

wordpress mega menu items, iterating all items on each level of a menu tree (dropdowns)

I've been re-writing a portion of this mega menu code to better serve menus where we have 3 levels of items. In this case the main menu has a dropdown called "Sports" which then has "basketball" and "football" each of which are dropdowns with their own respective teams so the menu tree looks like this:
-sports
--basketball
---commanders
---chargers
--football
---sharks
---bears
The issue is that this "sports" dropdown then shows everything in a single list and I want to display a column for each sport. My problem lies in the loop where I'm getting li elements because it iterates one by one and gives the football and basketball options the has-children class, which is fine, but I want to iterate on all 2nd level items first (i.e. the football and basketball items) so that I can make those into columns and then just use CSS for the rest.
How can I restructure the list items in order to achieve that properlY?
<?php
/**
* Mega Menu Category - Display recent posts from a parent category.
*/
// Walker to create the left part of mega menu
$sub_walker = new Walker_Nav_Menu;
$have_sub_menu = !empty($sub_items) ? true : false;
if (!isset($sub_items)) {
$sub_items = array();
}
?>
<div class="sub-menu mega-menu mega-menu-a wrap">
<?php if ($have_sub_menu): ?>
<div class="column sub-cats">
<ol class="sub-nav">
<?php foreach ($sub_items as $nav_item): ?>
<?php
ob_start();
// Simulate a simpler walk - $escaped_output is passed-by-ref
$escaped_output = '';
$sub_walker->start_el($escaped_output, $nav_item, 0, $args);
$sub_walker->end_el($escaped_output, $nav_item, $args);
ob_end_clean();
echo $escaped_output; // phpcs:ignore WordPress.Security.EscapeOutput -- Safe markup generated via WordPress default Walker_Nav_Menu::start_el()
?>
<?php endforeach; ?>
<li class="menu-item view-all menu-cat-<?php echo esc_attr($item->object_id); ?>"><a href="<?php echo esc_url($item->url); ?>"><?php
esc_html_e('View All', 'bunyad'); ?></a></li>
</ol>
</div>
<?php endif; ?>
<?php
// Add main item (view all) as default
array_push($sub_items, $item);
$columns = $have_sub_menu ? 4 : 5;
?>
<section class="column recent-posts" data-columns="<?php echo intval($columns); ?>">
<?php foreach ($sub_items as $item): ?>
<div class="posts" data-id="<?php echo esc_attr($item->object_id); ?>">
<?php
echo Bunyad::blocks()->load(
'Loops\Grid',
[
'query_type' => 'custom',
'posts' => $columns,
'cat' => $item->object_id,
'columns' => $columns,
'meta_items_default' => false,
'meta_above' => [],
'meta_below' => ['date'],
'heading_type' => 'none',
'excerpts' => false,
'style' => 'sm',
'space_below' => 'none',
'pagination' => false,
'cat_labels' => false
]
);
?>
</div> <!-- .posts -->
<?php endforeach; ?>
</section>
</div>

Foreach Nested Loops

So here is my code. The problem I am having is that I want the number from HP in my PHP code into my HP HTML code and the same thing with Cylinders. I have figured out the other stuff but when it comes to that part I am stuck
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$cars = array(
array(
"car" => "Ferrari",
"model" => "Testarossa",
"gearbox" => "Manual 5 Shift",
"designer" => "Battista Pininfarina",
"engine" =>
array(
"HP" => 390,
"Cylinders" => 12
),
),
);
?>
<?php foreach($cars as $cars_key => $car_val): ?>
<ul>
<div style="margin-bottom: 10px;">
<li><b>Car:</b> <?php echo $car_val["car"]; ?></li>
<li><b>Model:</b> <?php echo $car_val["model"]; ?></li>
<li><b>Gearbox:</b> <?php echo $car_val["gearbox"]; ?></li>
<li><b>Designer:</b> <?php echo $car_val["designer"]; ?></li>
<li><b>Engine</b></li>
<ul>
<li><b>HP:</b></li>
<li><b>Cylinders:</b></li>
</ul>
</div>
</ul>
<?php endforeach; ?>
I have a few concerns:
You lose the brilliance/utility of an associative array when you hardcode values into your script that you could otherwise just call from the array.
I don't like the look of the mid-list <div>. I can't think of any good reason to break up your unorder list flow with it.
I don't like the floating sub-list either. It logically belongs to Engine and good markup would dictate that the sub-list exist inside of its parent.
Here is what I would suggest considering my above points...
*Some Notes:
I'm not sure how you want to layout multiple lists as your array grows in size.
The echoing is just my personal preference. You can bounce in and out of php if you like.
ucfirst() allows you to avoid hardcoding the keys.
My snippet will make your task clean, DRY, and concise.
Code: (Demo)
$cars = array(
array(
"car" => "Ferrari",
"model" => "Testarossa",
"gearbox" => "Manual 5 Shift",
"designer" => "Battista Pininfarina",
"engine" => array(
"HP" => 390,
"Cylinders" => 12
)
)
);
foreach($cars as $details){
echo "<ul style=\"margin-bottom:10px;\">";
foreach($details as $key=>$item){
echo "<li><b>",ucfirst($key),":</b>";
if(!is_array($item)){
echo " $item</li>";
}else{
echo "<ul>";
foreach($item as $subkey=>$subval){
echo "<li><b>$subkey:</b> $subval</li>";
}
echo "</ul>";
echo "</li>";
}
}
echo "</ul>";
}
Source Code Output:
<ul style="margin-bottom:10px;">
<li><b>Car:</b> Ferrari</li>
<li><b>Model:</b> Testarossa</li>
<li><b>Gearbox:</b> Manual 5 Shift</li>
<li><b>Designer:</b> Battista Pininfarina</li>
<li><b>Engine:</b>
<ul>
<li><b>HP:</b> 390</li>
<li><b>Cylinders:</b> 12</li>
</ul>
</li>
</ul>
Rendered Output: (run my snippet # phptester.net to see this)
From you example, it seems to me that the list is static and consists of two elements, then you need not use forEach at all.
<?php foreach($cars as $cars_key => $car_val): ?>
<ul>
<div style="margin-bottom: 10px;">
<li><b>Car:</b> <?php echo $car_val["car"]; ?></li>
<li><b>Model:</b> <?php echo $car_val["model"]; ?></li>
<li><b>Gearbox:</b> <?php echo $car_val["gearbox"]; ?></li>
<li><b>Designer:</b> <?php echo $car_val["designer"]; ?>
</li>
<li><b>Engine</b></li>
<ul>
<li><b>HP:</b><?php echo $car_val["engine"]["HP"]; ?></li>
<li><b>Cylinders:</b><?php echo $car_val["engine"]["Cylinders"]; ?></li>
</ul>
</div>
</ul>
<?php endforeach; ?>
If you do need to use a nested forEach, here is how you would go about doing that:
foreach($cars as $cars_key => $car_val):
if($cars_key == "engine")
foreach($car_val["engine"] as $engine_key => $engine_val):
echo $engine_key.$engine_val;
endforeach;
endforeach;

How to give hyperlink to items in CodeIgniter

I need give some hyperlink to my items category in codeigniter.
$this->data['itemdata'] = array(
array(
'title' => 'Printers / Accessories',
'items' => ['Printers', 'Printer Cartridges', 'Compatible Toners'],
'brands' => ['hp', 'cannon', 'brother', 'toshiba', 'sharp']
),
how can I create it?
Updated
view file
<div class="items">
<ul class="floated">
<?php foreach ($item['items'] as $key => $value): ?>
<li><?php echo $value; ?></li>
<?php endforeach; ?>
</ul>
</div>
You have to do it something like below:-
<li><?php echo $value;?></li>
Note:- I hope through URL you want to send user to some fruitful link. So change controller/function/uri to corresponding values.
Reference:-CodeIgniter - Correct way to link to another page in a view
Note:- if you want to remove link then do like below:-
<li><?php echo $value;?></li>

How can I loop this PHP code for six times exactly?

OK, this is my code:
<?php if (!empty($projectSectorItem1Title)): ?>
<div class="project" style="overflow:hidden;">
<?php if (!empty($projectSectorItem1Image)) { ?>
<img src="<?php echo $projectSectorItem1Image; ?>" width="100%"/>
<div class="project_box_info">
<h3><a><?php echo $projectSectorItem1Title; ?></a></h3>
<p><?php echo $projectSectorItem1Description; ?></p>
</div>
<?php } else { ?>
<div class="project_box_info" style="opacity:1;">
<h3><a><?php echo $projectSectorItem1Title; ?></a></h3>
<p><?php echo $projectSectorItem1Description; ?></p>
</div>
<?php } ?>
</div>
<?php endif; ?>
This code is repeated currently in my .php file six times, as I have up to six items. If the first if statement returns false, naturally nothing appears. This is good. It works. However, I've noticed my page is loading slower now with six of these stacked up on each other.
Is there a way to systematically loop this exact code for each of the numbers? The only thing that would need to change is the numbers.. i.e. above #1, second #2, third #2 etc. Lines containing numbers that need to increase are: 1, 3, 4, 6, 7, 11, 12. So there are 7 places. I have no idea how to do this!
I have a similar issue in the same .php file, but if I know how to do this one, I should be able to "kill two birds with one stone" as they say. Many thanks for any help.
To clarify what I'm trying to do for one of the commenters: I have six boxes which are associated with meta data for each item inside each box. If the title variable is filled in, we go ahead with the rest of the code. However, if there is no image, there is no "hover" feature; instead, the opacity of the hover box is already filled (hence that opacity:1; in the second bit).
So... check for title > if title exists, go ahead > if image, proceed as normal but if not > proceed as normal without the image and set opacity to 1 for project_box_info
Really I'm just reiterating the code here in English, but that's all I can do really!
You can use a forloop like below
<?php for($i=1;$i<=6;$i++): ?>
<?php if (!empty(${"projectSectorItem{$i}Title"})): ?>
<div class="project" style="overflow:hidden;">
<?php if (!empty(${"projectSectorItem{$i}Image"})) { ?>
<img src="<?php echo ${"projectSectorItem{$i}Image"}; ?>" width="100%"/>
<div class="project_box_info">
<h3><a><?php echo ${"projectSectorItem{$i}Title"}; ?></a></h3>
<p><?php echo ${"projectSectorItem{$i}Description"}; ?></p>
</div>
<?php } else { ?>
<div class="project_box_info" style="opacity:1;">
<h3><a><?php echo ${"projectSectorItem{$i}Title"}; ?></a></h3>
<p><?php echo ${"projectSectorItem{$i}Description"}; ?></p>
</div>
<?php } ?>
</div>
<?php endif; ?>
<?php endfor; ?>
That is your loop.. Feel free to ask any questions.
You would use a for loop;
<?
for (int i = 0; i < 6; i++) {
// your code here
}
This would loop through the above statement 6 times. If you want to change a number, you could substitute in for i - (or i+1);
<?
for (int i = 0; i < 3; i++) {
echo("this is cycle number $i");
}
Would return with;
this is cycle 0
this is cycle 1
this is cycle 2
I believe you're looking for something along these lines.
Having an array of items with set titles, descriptions and image urls should greatly increase the execution speed. Then, as others have suggested, loop over the array with a for or foreach.
Using this method better separates the data from the presentation, which makes the whole thing easier to read and modify.
$items = array(
array(
'title' => 'Item 1',
'description' => 'This is the description for item1',
'image' => 'http://fake.com/images/item1.png'
),
array(
'title' => 'Item 2',
'description' => 'This is the description for item2',
'image' => 'http://fake.com/images/item2.png'
),
array(
'title' => 'Item 3',
'description' => 'This is the description for item3'
),
array(
'title' => 'Item 4',
'description' => 'This is the description for item4',
'image' => 'http://fake.com/images/item4.png'
),
array(
'title' => 'Item 5',
'description' => 'This is the description for item5',
'image' => 'http://fake.com/images/item5.png'
),
array(
'title' => 'Item 6',
'description' => 'This is the description for item6'
)
)
foreach ($items as $item) {
echo '
<div class="project">
', (isset($item['image']) ? '<img src=' . $item['image'] . '" alt="" />' : ''), '
<div class="project_box_info">
<h3><a>', $item['title'], '"</a></h3>
<p>', $item['description'], '"</p>
</div>
</div>';
}
I did omit your inline styles here for the sake of readability. Really they should be in an external stylesheet anyway.

Categories