I have a table similar to the following:
subcategory category
------------------------
apples fruits
oranges fruits
pears fruits
honda cars
volvo cars
audi cars
What would be an easy way to print out something like the example below, using php and mySQL?
Example:
Fruits:
Apples
Oranges
Pears
Cars:
Honda
Volvo
Audi
I have been trying to figure this out for hours now, I appreciate any advice.
Get a list of categories, and then subcategories in each categories.
<?php
$categories = array();
foreach ($results as $result) {
$category = $result['category'];
$categories[$category][] = $result['subcategory'];
}
This will then give you a multidimensional array, with categories and the keys, and the sub-categories as the values. You can loop over them as thus:
<ul>
<?php foreach ($categories as $category => $subcategories): ?>
<li>
<?php echo $category; ?>
<ul>
<?php foreach ($subcategories as $subcategory): ?>
<li><?php echo $subcategory; ?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
$data = getData();
$dataByCat = array();
foreach($data as $row) {
$dataByCat[$row['category']][] = $row;
}
$dataByCat will be an array in the "shape" of your bullet points.
Related
I would like to add a list of categories to my conditional statement, how should I add multiple categories id ?
Using like 123,124,125 or 123 || 124
I have a big list of categories so I am looking for the cleanest way to achieve that
thanks
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
$categories = $product->getCategoryIds(); /*will return category ids array*/
foreach($categories as $category){
$cat = $objectManager->create('Magento\Catalog\Model\Category')->load($category);
echo $cat->getId();
}
?>
<?php if($cat->getId()==123): ?>
<?php echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();?>
<?php endif; ?>
Use in_array PHP function:
<?php if(in_array($cat->getId(), [123, 124, 125])): ?>
The best solution is to use in_array function
<?php
if(in_array($cat->getId(), $your_array){
$block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();
}
?>
Use in_array() : This Checks if a value exists in an array or not.Return true if exist.
<?php
if(in_array($cat->getId(), $categories ):
echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();
endif;
?>
I have a list of 6 products that i want to split in 2 lists of 3 products next to each other. The list are made within a foreach loop, the first list stops after the count == 2, so 3 items wil be displayed. The second list should start with the fourth item. How can i achieve this?
This is wat makes the first list of 3 items:
<?php
$_categoryId = explode(' ', $category['id']);
$count = 0;
$_productCollection = Mage::getModel('catalog/category')->load($_categoryId)
->getProductCollection()
->addAttributeToSelect('*')
->setOrder('date_added', 'DESC');
?>
<?php foreach ($_productCollection as $_product): ?>
<li class="category-row-list-item">
<a class="product-name" href="<?php echo $_product->getProductUrl() ?>">
<?php echo $this->htmlEscape($_product->getName()) ?>
</a>
</li>
<?php
if($count == 2) break; // Stop after 3 items
$count++;
?>
<?php endforeach ?>
Best regards,
Robert
For simplicity you could repeat the foreach statement but doing the opposite and continue on the first three items.
<?php foreach ($_productCollection as $_product): ?>
<?php
$count++; // Note that first iteration is $count = 1 not 0 here.
if($count <= 3) continue; // Skip the iteration unless 4th or above.
?>
<li class="category-row-list-item">
<a class="product-name" href="<?php echo $_product->getProductUrl() ?>">
<?php echo $this->htmlEscape($_product->getName()) ?>
</a>
</li>
<?php endforeach ?>
The keyword continue is used in loops to skip the current iteration without exiting the loop, in this case it makes PHP go directly back to the first line of the foreach-statement, thus increasing counter to 4 (since 4th, 5th and 6th is what we're after) before passing the if statement.
Commentary on the approach
I kept it coherent with your existing solution but a more clean way in this case would probably be to use the built in Collection Pagination.
If you use ->setPageSize(3) you can simply iterate the collection to get the first three products and then use ->setCurPage(2) to get the second page of three items.
I'm linking this blog post on the topic here just to give you an example of how it's used but since I don't know your comfort level in working with collections I retain my first answer based on your existing code.
Something like that with modulo function for have new array each 3 items :
$count = 1;
$count_change = 1;
$key = 0;
$yourList = array(
"1",
"2",
"3",
"4",
"5",
"6",
);
foreach ($yourList as $item) {
if (!isset($$new_list)) {
$new_list = "list" . $count_change . "";
$$new_list = array();
}
if ($count % 3 == 0) {
$key = 0;
$count_change++;
$new_list = "list" . $count_change . "";
$$new_list = array();
}
$$new_list[$key] = $item;
$count++;
$key++;
}
Hope this helps.
I have a $row array that will print the below array
Array
(
[BookCode] => 124
[BookName] => Book1
)
Array
(
[BookCode] => 123
[BookName] => Book2
)
...........
I have a code like this:
<?php foreach($row as $key=>$value){ ?>
<span style="color:red;font-weight:bold;"><?php echo $value; ?></span>
<?php } ?>
But I'm not able to get the BookCode in my anchor tag since I'm using foreach with key-value. In my case I have to use foreach only (as intructed by my client)
So how can I get the value inside the anchor tag?
Your foreach loop is not returning what you expect—you have an array of associative arrays.
<? foreach ( $row as $column ): ?>
<a href="process.php?bcode=<?=$column['BookCode']?>">
<? endforeach; ?>
In the above, the link will be process.php?bcode=124
Alternatively, if you really want to use the $key=>$value:
<? foreach ( $row as $column ): ?>
<? foreach ( $column as $key=>$value ) ?> // here $key = 'BookCode'
<a href="process.php?bcode=<?=$value?>">
<? endforeach; ?>
<? endforeach; ?>
Try foreach like this. It may help to you
foreach($row as $data)
{?>
<?php } ?>
I am currently creating a joomla component, and i am currently stuck with the menu part.
this is in my model file:
public function getMenu(){
$menu_id = JRequest::getInt('id');
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->select('t.country_name,t.country_code, a.continent_name');
$query->from('#__vectormap_countries AS t')
->join('LEFT', '#__vectormap_continents AS a USING(continent_id)')
->where('t.published = 1');
$db->setQuery($query);
$menu_items = $db->loadObjectList();
return $menu_items;
}
and on the front end i have:
<?php $menus = $this->menu ?>
<?php foreach($menus as $menu): ?>
<div><?php echo $menu->continent_name ?></div>
<li id="<?php echo $menu->country_code ?>"><?php echo $menu->country_name ?></li>
<br />
<?php endforeach; ?>
and that returns:
Africa
South Africa
Africa
Mozambique
or if i print out the array this:
Array ( [0] => stdClass Object ( [country_name] => South Africa [country_code] => ZA [continent_name] => Africa ) [1] => stdClass Object ( [country_name] => Mozambique [country_code] => MZ [continent_name] => Africa ) ) 1
Now Finally the question, how would i sort it so that Africa (continent_name) not be repeated but rather have all the countries that have the continent_name of Africa list underneath it?
Keep in mind North America and such will also come in to play..
Summarized question -> How would I sort countries underneath there associated continents fond in the array.
Any Help Greatly Appreciated thanks.
how would i sort it that everything
The easy fix is by ORDERing your query results and then add some logic in your foreach loop
$query->order('a.continent_name ASC, t.country_name ASC');
In your foreach loop remember what the previous continent was
<?php
$lastcontinent = "";
foreach($menus as $k => $menu):
if($lastcontinent != $menu->continent_name){
if($k > 0){ // if this isn't the first continent
// closing tags for the previous continent
echo '</ul></div>';
}
echo '<div>'.$menu->continent_name.'</div><ul>';
}
$lastcontinent = $menu->continent_name;
echo '<li id="'.$menu->country_code.'">'.$menu->country_name.'</li>';
endforeach;
?>
</ul></div> <!-- closing tags for the last continent which hasn't been closed yet -->
Use a foreach loop and make a new array and create continent_name as a key. Then you won't have a repetitive names.
Basically I have a set of object values I want render in 2 separate html lists
I figure the simplest way to do this is by displaying evens only in one list, and odd only in the other
Here is the current code for displaying a single list
<ul>
<?php foreach ($values as $value) : ?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
</ul>
Try this:
<ul>
<?php
/* read the index key */
foreach ($values as $key => $value) :
/* skip the current element if it doesn't have an even index */
if($key % 2 == 1) continue;
?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
You didn't specify if the array has integer index. So I use a separate index pivot. This will do.
$v=array();
$index = 1;
foreach ($values as $value){
$v[($index++)%2][]=$value->value;
}
list ($evens, $odds) = $v;
echo "<ul><li>".implode("</li><li>", $odds)."</li></ul>"; // show list of odds
echo "<ul><li>".implode("</li><li>", $evens)."</li></ul>"; // shows list of even