This is a very newbie question. But how would I sort the results of this alphabetically so the names in the li list are in order?
<?php
// FOR THE CATEGORIES (PRODUCT TYPE)
$terms_one = get_terms('product_cat');
$count_one = count($terms_one);
$i_one = 0;
echo '<ul class="submenu one filter option-set" data-filter-group="gem-type">';
echo '<li>ALL';
if ($count_one > 0) {
foreach ($terms_one as $term_one)
{
$i_one++;
$term_list_one .= '<li> <span>'. $term_one->count .'</span>'. $term_one->name .'</li>';
if ($count_one != $i_one)
{
$term_list_one .= '';
} else {
$term_list_one .= '';
}
}
echo $term_list_one;
}
echo '</ul>';
?>
You can put in an array with arguments in the get_terms() function, orderby and order are probably what you want.
Here's the documentation:
http://codex.wordpress.org/Function_Reference/get_terms
$terms_one = get_terms('product_cat','orderby=FIELD&order=ASC');
More information, you can refer to the documentation here: http://codex.wordpress.org/Function_Reference/get_terms
Try
asort($terms_one);
before doing the foreach loop.
If you want to sort by the array-key you can use ksort() ...
Related
Im trying to echo a set of values for categories. What I'd like to do is if there are more than one value, append a comma afterwards. Here's a snippet of what I have:
<?php foreach((get_the_category()) as $category) { echo $category->cat_name . ', '; } ?>
The problem with this is that categories with one value will have a comma at the end.
Alternative 1
Add all values to an array and then just use implode() to glue them all together:
$catArray = [];
foreach((get_the_category()) as $category) {
$catArray[] = $category->cat_name;
}
// Now we can implode the array, using , as the glue
echo implode(', ', $catArray);
Alternative 2
You could also prepend the commas in your loop so you don't need any if-statements:
$glue = '';
foreach((get_the_category()) as $category) {
echo $glue . $category->cat_name;
$glue = ', ';
}
or a shorter version (not as readable though and requires PHP 7+):
foreach((get_the_category()) as $category) {
echo ($glue ?? '') . $category->cat_name;
$glue = ', ';
}
The first iteration won't get any comma in front of it, but the rest will.
You could get the count of results from get_the_category(), set a counter and increment that each time through the loop. Check if $i is equal to the count and if it is, don't add the comma.
Assuming that function is countable and you don't need checks to make sure their aren't 0 results:
<?php
$count = count(get_the_categories());
$i = 1;
foreach((get_the_category()) as $category) {
if($i < $count) {
echo $category->cat_name . ', ';
} else {
echo $category->cat_name;
}
$i++;
}
?>
This script displays the categories of a post, but excludes the ones that the user doesn't want to show:
function exclude_post_categories($excl='', $spacer=' ') {
$categories = get_the_category($post->ID);
if (!empty($categories)) {
$exclude = $excl;
$exclude = explode(",", $exclude);
$thecount = count(get_the_category()) - count($exclude);
foreach ($categories as $cat) {
$html = '';
if (!in_array($cat->cat_ID, $exclude)) {
$html .= '<a href="' . get_category_link($cat->cat_ID) . '" ';
$html .= 'title="' . $cat->cat_name . '">' . $cat->cat_name . '</a>';
if ($thecount > 1) {
$html .= $spacer;
}
$thecount--;
echo $html;
}
}
}
}
The fuctions is triggered like this.
<?php exclude_post_categories('5', ', ');
So if a post has the categories: 1,2,3,4,5 than only 1,2,3,4 are echoed.
The script works great for the posts that have the category that is excluded (5).
The problem lies with the posts that don't have that category.
So if a post has the categories: 1,2,3,4 that those are echoed but with less commas than needed: 1,2,34
$thecount variable is always calculated wrong for the posts that don't have the category that has to be excluded.
Try something like this:
$existing = get_the_category();
$newcategories = array_udiff($existing,$exclude,function($e,$x) {
return $e->cat_ID != $x;
});
$as_links = array_map(function($c) {
return '<a href="'.get_category_link($c->cat_ID).'" '
.'title="'.$cat->cat_name.'">'.$cat->cat_name.'</a>';
},$newcategories);
echo implode($spacer, $as_links);
This will first strip out categories whose IDs are in the $exclude array, then convert each category to a category link, before outputting them with the separator.
EDIT: Slightly mis-read the question. This expects $exclude to be an array. Put the following line at the start:
if( !is_array($exclude)) $exclude = array($exclude);
To make it support single-value inputs as well - this way you can either specify one or many categories to exclude.
Found a better solution to the problem here: http://css-tricks.com/snippets/wordpress/the_category-excludes/#comment-1583708
function exclude_post_categories($exclude="",$spacer=" ",$id=false){
//allow for specifiying id in case we
//want to use the function to bring in
//another pages categories
if(!$id){
$id = get_the_ID();
}
//get the categories
$categories = get_the_category($id);
//split the exclude string into an array
$exclude = explode(",",$exclude);
//define array for storing results
$result = array();
//loop the cats
foreach($categories as $cat){
if(!in_array($cat->cat_ID,$exclude)){
$result[] = "$cat->name";
}
}
//add the spacer
$result = implode($spacer,$result);
//print out the result
echo $result;
}
Basically I'm trying to group my arrays like this:
Shopping
Amazon
Social
Amoeblo
American express
By using below PHP code:
<?php
echo '<ul id="list"><h2 class="searchresults"></h2>';
foreach($records as $catval) {
$sitechar = $catval->site_category;
echo '<h3 id="disappear">'. strtoupper($sitechar) .'</h3>';
echo '<li class="siteli"><a href="#" class="add">';
echo '<p id="text-site">'.$catval->site_name. '</p></a>';
echo '</li>';
}
echo '</ul>';
?>
But I'm getting values only like below.
Shopping
Amazon
Social
Amoeblo
Social
American express
I'm not getting the exact PHP sorting to use for this.
I would create a new array with categories as keys for arrays with the sites.
<?php
$arr = array();
// First create multidimensional array with categories as keys for site arrays
foreach($records as $catval) {
$sitechar = $catval->site_category;
if (!array_key_exists($sitechar, $arr)) {
// Set new array for a category if it does not exist
$arr[$sitechar] = array();
}
// Add site to category
$arr[$sitechar][] = array(
"name"=>$catval->site_name,
"image"=>$catval->site_img
);
}
// Then iterate the new array of categories
echo ("<ul>");
foreach($arr as $category => $sites) {
echo("<h3>" . $site_category "</h3>");
// Iterate array of sites
foreach($sites as $site) {
echo("<li>" . $site["name"] . "-" , $site["image"] . "</li>");
}
}
echo("</ul>");
?>
You can do it using a foreach and ksort
Let $your_array be the array you mentioned above
$res_array = array();
foreach($your_array as $val){
$res_array[$val->site_category][] = $val->site_name;
}
ksort($res_array);
print_r($res_array);
OR search for multisort in php which will solve your problem :)
$tmp = null;
echo '<ul id="list"><h2 class="searchresults"></h2>';
foreach($records as $catval) {
$myHtml = makeHtml($catval,$tmp);
echo $myHtml;
$tmp = $catval->site_category;
}
echo '</ul>';
function makeHtml($catval,$tmp){
if($tmp != $catval->site_category){ $html .= '<h3 id="disappear">'. strtoupper($catval->site_category) .'</h3>';}
$html .='<li class="siteli"><p id="text-site">'.$catval->site_name. '</p></li>';
return $html;
}
I have a single category, that has 2 subcategories. Within each of these categories, are 5 subcategories.
Is there a way to get a list of all of these 10 sub-sub-categories?
Thanks
EDIT:
Something like this:
Main Category
Sub_Cat_1
Cat_1
Cat_2
Cat_3
Sub_Cat_2
Cat_4
Cat_5
Cat_6
Wanting output like:
Cat_1
Cat_2
Cat_3
Cat_4
Cat_5
Cat_6
Thanks
All answers so far load children categories in a loop which is generally bad practice and causes execution of many SQL queries where a single one would suffice.
Performant Single Query Solution:
Let $parentCategory be your Main Category, then this collection will load all subcategories, two levels below:
$subcategoryCollection = Mage::getModel('catalog/category')
->getCollection()
->addFieldToFilter('level', $parentCategory->getLevel() + 2)
->addFieldToFilter('path', ['like' => $parentCategory->getData('path') . '/%']);
The path field contains the category id prefixed with all ancestor ids in the form 1/2/3. Database wise it is a column in catalog_category_entity that has an index, so comparison like this has no performance issues.
Figured it out:
$cat = Mage::getModel('catalog/category')->load(24);
$subcats = $cat->getChildren();
foreach(explode(',',$subcats) as $subCatid)
{
$_category = Mage::getModel('catalog/category')->load($subCatid);
if($_category->getIsActive()) {
$sub_cat = Mage::getModel('catalog/category')->load($_category->getId());
$sub_subcats = $sub_cat->getChildren();
foreach(explode(',',$sub_subcats) as $sub_subCatid)
{
$_sub_category = Mage::getModel('catalog/category')->load($sub_subCatid);
if($_sub_category->getIsActive()) {
echo '<li class="sub_cat">'.$_sub_category->getName().'</li>';
}
}
}
}
Thanks for looking!
I have developed a recursive function to get all children of a category
$categoryObject = Mage::getModel('catalog/category')->load(CATID);
$children = MODEL_OBJECT->getChildCategories($categoryObject);
// IN MODLE FILE
public $_catIds = array();
public function getChildCategories($categoryObject){
$categories = $categoryObject->getChildrenCategories();
foreach ($categories as $catgory){
if($catgory->hasChildren()){
$this->getChildCategories($catgory);
}
$this->_catIds[] = $catgory->getId();
}
return $this->_catIds;
}
Hope this will help you.
$this->getCurrentCategory()->getParentCategory()->getData();
try this
What I do is recursively find the id of the ancestor category.
Once found it, I can print the current category sub categories.
If the current category has no children, than I will just print the father's subcategory.
In this way you can have infinite subcategories and still being able to display a sub category list.
$_helper = Mage::helper("catalog/category");
$rootCat = Mage::app()->getStore()->getRootCategoryId();
$current = Mage::registry('current_category');
show_cat($current,$_helper,$rootCat);
function show_cat($child,$_helper,$rootCat){
if ($child){
//look for anchestor
$parentid = $child->getParentId();
$parent = Mage::getModel("catalog/category")->load($parentid);
if($parentid != $rootCat)
{
//find the anchestor
show_cat($parent,$_helper,$rootCat);
}else{
//is root
$_subcategories = $parent->getChildrenCategories();
if(count($_subcategories)>0){
echo '<ul>';
foreach($_subcategories as $_category){
echo '<li>';
echo ''.$_category->getName().'';
if($child->getId() == $_category->getId()){
$current = Mage::registry('current_category');
if ($current){
//handle current
$_current_subcategories = $current->getChildrenCategories();
if(count($_current_subcategories)>0){
//the current cat has childrens
echo '<ul>';
foreach($_current_subcategories as $_sub_category){
echo '<li>';
echo ''.$_sub_category->getName().'';
echo '</li>';
}
echo '</ul>';
}else{
//the current cat has no childrens
$current_parent = $current->getParentId();
$current_parent = Mage::getModel("catalog/category")->load($current_parent );
$_current_subcategories = $current_parent ->getChildrenCategories();
echo '<ul>';
foreach($_current_subcategories as $_sub_category){
echo '<li>';
echo ''.$_sub_category->getName().'';
echo '</li>';
}
echo '</ul>';
}
}
}
echo '</li>';
}
echo '</ul>';
}
}
}
}
I have this issue where i want to increase a value with 1 and apply this to my HTML, but i can't use a for() or while() loop (at least i think i can't). I'm customizing an e-merchandise program (opencart) and my php knowledge isn't enough to tackle the problem.
There is this function which displays the categories from the store. It uses a variable that is constantly updated via $var .= "value".
I'm so far that i know how many sub-categories there are, but i don't know how to apply this range to my HTML.
I'm working towards a situation like below
<ul id="cats">
<li id="cat1">Cat
<ul id="sub1">
<li>item</li>
<li>item</li>
</ul>
</li>
<li id="cat2">Cat
<ul id="sub2">
<li>item</li>
<li>item</li>
</ul>
</li>
</ul>
I don't have a clue how to increase the count of the second unordered lists. Below the code where the second unordered lists are generated.
[..]
$cPiD = strlen($parent_id);
if ($results) {
if ($parent_id == 0) {
$output .= '<ul id="cats">';
} else {
$output .= '<ul id="sub'.$cPiD.'">';
}
}
[..]
The variable $cPiD holds the total amount of sub categories (in this case 2). I want this variable to automatically apply the correct number to the unordered list (so apply id="sub1" to the first unordered list and id="sub2" tot he second one (as in my example above)).
The problem is that i can't use a for() loop after the else part, because in my HTML i wil get two <ul> tags instead of one.
Below the PHP code where it all happens
$category_id = array_shift($this->path);
$output = '';
$results = $this->model_catalog_category->getCategories($parent_id);
$count = 0;
$cPiD = strlen($parent_id);
if ($results) {
if ($parent_id == 0) {
$output .= '<ul id="cats">';
} else {
$output .= '<ul id="sub'.$cPiD.'">';
}
}
foreach ($results as $result) {
$count++;
if (!$current_path) {
$new_path = $result['category_id'];
$output .= '<li id="cat'.$count.'">';
} else {
$new_path = $current_path . '_' . $result['category_id'];
$output .= '<li>';
}
$children = '';
$children = $this->getCategories($result['category_id'], $new_path);
$output .= $result['name'];
$output .= $children;
if (!$current_path) {
$output .= '</li>';
} else {
$output .= '</li>';
}
}
if ($results) {
if ($parent_id == 0) {
$output .= '</ul>';
} else {
$output .= '</ul>';
}
}
Does anybody maybe have an idea how to solve this?
EDIT:
Oh, i tries adding the following construction in the foreach() loop, but that gave problems when a certain categories don't have any sub categories.
if (!$current_path) {
$output .= '$result['name'] . ' <ul id="sub'.$count.'">';
}else{
$output .= $result['name'];
}
You can use this:
// at the top of your code (ouside of the loop)
$cPiD = 1;
// inside the loop you need to increment the parameter
$output .= '<ul id="sub'.$cPiD++.'">';
After each time the item is used, its value will be incremented by 1. (after already using it)