Php output for categories - php

I have a shop with more than 30k categories in it and it's almost impossible to edit products in admin because the way it handles categories selection in products edit page it's not designed for that amount of categories. It loads very long and sometimes even crashes. It's a simple select box and I wonder what can be done?
Do I need ajax for this to work?
Here's the code:
<?php function custom_catalog_tree($category_id=0, $depth=1, $count=0) {
$output = '';
if ($category_id == 0) {
$output .= '<div class="checkbox" id="category-id-'. $category_id .'"><label>'. functions::form_draw_checkbox('categories[]', '0', (isset($_POST['categories']) && in_array('0', $_POST['categories'], true)) ? '0' : false, 'data-name="'. htmlspecialchars(language::translate('title_root', 'Root')) .'" data-priority="0"') .' '. functions::draw_fonticon('fa-folder', 'title="'. language::translate('title_root', 'Root') .'" style="color: #cccc66;"') .' ['. language::translate('title_root', 'Root') .']</label></div>' . PHP_EOL;
}
// Output categories
$categories_query = database::query(
"select c.id, ci.name
from ". DB_TABLE_CATEGORIES ." c
left join ". DB_TABLE_CATEGORIES_INFO ." ci on (ci.category_id = c.id and ci.language_code = '". language::$selected['code'] ."')
where c.parent_id = '". (int)$category_id ."'
order by c.priority asc, ci.name asc;"
);
while ($category = database::fetch($categories_query)) {
$count++;
$output .= ' <div class="checkbox"><label>'. functions::form_draw_checkbox('categories[]', $category['id'], true, 'data-name="'. htmlspecialchars($category['name']) .'" data-priority="'. $count .'"') .' '. functions::draw_fonticon('fa-folder fa-lg', 'style="color: #cccc66; margin-left: '. ($depth*1) .'em;"') .' '. $category['name'] .'</label></div>' . PHP_EOL;
if (database::num_rows(database::query("select * from ". DB_TABLE_CATEGORIES ." where parent_id = '". $category['id'] ."' limit 1;")) > 0) {
$output .= custom_catalog_tree($category['id'], $depth+1, $count);
}
}
database::free($categories_query);
return $output;
}
echo custom_catalog_tree();
?>

I would suggest you to make a search box instead of a select box. Write down a query to search the product category with ajax if you can. Make a search query with select * from table_name where category like %your_value%

You can easily handle this using Select2 plugin.
It provides a suggestion dropdown, where users can type and filter through dropdown values.
On server side you have to create web service to fetch categories by name.
Go through section Loading remote data,
https://select2.github.io/examples.html#data-ajax

Related

How to pass an alias from a database query into a loop for output in Wordpress

I am querying the database in Wordpress to retrieve comment_content in the wp_comments table as well as the meta_value of 2 meta_keys in the wp_commentmeta table. My aim is to take every comment in the database and output it within a list, with each list item displaying the comment, as well as my 2 commentmeta items (name and country).
I am using an alias for each meta_key as so:
$querystr = " SELECT * FROM $wpdb->comments, $wpdb->commentmeta AS commentmeta1, $wpdb->commentmeta AS commentmeta2
WHERE $wpdb->comments.comment_ID = commentmeta1.comment_id
AND $wpdb->comments.comment_ID = commentmeta2.comment_id
AND commentmeta1.meta_key = 'comment_name'
AND commentmeta2.meta_key = 'comment_country' ORDER BY $wpdb->comments.comment_date DESC";
$comment_info = $wpdb->get_results($querystr, OBJECT);
I then run run my loop to display my results:
echo '<ul>';
// display the results
foreach($comment_info as $info) {
echo '<li class="commentBox"><p>' . $info->comment_content . '</p>
<h6>' . $info->meta_value['commentmeta1'] . ', ' . $info->meta_value['commentmeta2'] . '</h6></li>';
}
echo '</ul>';
What I need to do is pass the alias I defined for each meta_key into my loop so I can display it's respective meta_value. I tried using $info->comment_content and $info->meta_value['commentmeta2'] but it doesn't work. Using $info->meta_value only displays commentmeta2. Can anybody help?
Thanks to MatBailie's suggestion, the final working code is as follows:
$querystr = " SELECT comment_content, commentmeta1.meta_value AS comment_name, commentmeta2.meta_value AS comment_country
FROM $wpdb->comments, $wpdb->commentmeta AS commentmeta1, $wpdb->commentmeta AS commentmeta2
WHERE $wpdb->comments.comment_ID = commentmeta1.comment_id
AND $wpdb->comments.comment_ID = commentmeta2.comment_id
AND commentmeta1.meta_key = 'comment_name'
AND commentmeta2.meta_key = 'comment_country' ORDER BY $wpdb->comments.comment_date DESC";
$comment_info = $wpdb->get_results($querystr, OBJECT);
echo '<ul>';
// display the results
foreach($comment_info as $info) {
echo '<li class="commentBox"><p>' . $info->comment_content . '</p>
<h6>' . $info->comment_name . ', ' . $info->comment_country . '</h6></li>';
}
echo '</ul>';

Displaying Expenses under each expense type using MySQL PDO

I have two tables that I am creating a list that shows all the expenses under each expense type. I have been able to get it to work except when I add the
AND WHERE expenses.pid = " . $pid
it cases a Syntax error and I can't figure out way.
The biggest thing is I need to limet the Expense Type to only show the ones that have some data to go below them
EXPENSETYPE
typeid
pid
exptype
EXPENSES
expid
pid
expdate
checktype
payee
typeid
details
amount
<?php
$pid = 6;
$sql = "SELECT expensetype.typeid, expensetype.exptype
FROM `expensetype` WHERE expensetype.pid = $pid
ORDER BY expensetype.typeid DESC";
$expensetype = $db->query($sql);
foreach($expensetype as $type) {
echo '<li>' . $type['exptype'] . '<ul>';
$sql2 = "SELECT expenses.expid, expenses.expdate, expenses.checktype, expenses.payee, expenses.details, expenses.amount
FROM `expenses` WHERE `expenses`.typeid = " . $type['typeid'] . "AND WHERE expenses.pid = " . $pid ;
$expenses = $db->query($sql2);
foreach($expenses as $exp) {
echo '<li>' . $exp['expdate'] . ' ' . $exp['checktype'] . ' ' . $exp['expdate'] . ' ' . $exp['payee'] . ' ' . $exp['details'] .' ' . $exp['amount'] .'</li>';
}
echo '</ul></li>';
}
?>
Try this SQL statement instead of making two of them :
SELECT `expensetype`.`typeid`, `expensetype.exptype`, `expenses`.`expid`,
`expenses`.`expdate`, `expenses`.`checktype`, `expenses`.`payee`,
`expenses`.`details`, `expenses`.`amount`
FROM `expensetype` INNER JOIN `expenses` ON
`expensetype`.`typeid` = `expense`.`typeid`
WHERE (...)
Also, you cannot use two WHERE in a SQL statement, only use AND.

How can I add categories and subcategories to an array?

I want to list Main categories and subcategories but dont know how ?
What I want to do is like this
Main cat 1
-subcat 1
-subcat 2
-subcat others
Main cat 2
-subcat 1
-subcat 2
-subcat others
I have two part codes which is printing only main categories like this,
Main cat1
Main cat2
Main cat3
Here is the total codes Trying separate ways but cant do it.
$sql_select_cats_list = $db->query("SELECT category_id, items_counter, hover_title FROM " . DB_PREFIX . "categories WHERE parent_id=0 AND hidden=0 AND user_id=0 AND enable_auctions=1 ORDER BY order_id ASC, name ASC");
$cats = array();
while($row=$db->fetch_array($sql_select_cats_list)) {
$cats[$row['category_id']] = $row;
}
$cat_ids = implode(', ', array_keys($cats));
$sql_select_subcats_list = $db->query("SELECT sub.category_id, sub.items_counter, sub.hover_title, parent.order_id FROM " . DB_PREFIX . "categories sub LEFT JOIN " . DB_PREFIX . "categories parent ON (parent.category_id=sub.parent_id) WHERE parent.category_id IN (" . $cat_ids . ") AND sub.hidden=0 AND sub.user_id=0 AND sub.enable_auctions=1 ORDER BY parent.order_id ASC, sub.order_id ASC, sub.name ASC");
while($row=$db->fetch_array($sql_select_subcats_list)) {
if(!isset($subs[$row['parent_id']])) {
$subs[$row['parent_id']] = array();
}
$subs[$row['parent_id']][] = $row;
}
$template->set('cats_list', $cats);
$template->set('subs_list', $subs);
$category_box_content = $template->process('categories_box.tpl.php');
$template->set('category_box_content', $category_box_content);
I am trying to list categories and sub categories with this code:
<?php
foreach($cats as $parent_id => $cats_header_details) {
$category_link = process_link('categories', array('category' => $category_lang[$cats_header_details['category_id']], 'parent_id' => $cats_header_details['category_id']));
// subcategory links:
if(isset($subs_list[$parent_id])) {
foreach($subs_list[$parent_id]) as $sub) {
// do something with your subcategory
}
}
?>
<li><a style="font-size: 11px; font-weight: normal;" href="<?=$category_link;?>"
<?=((!empty($cats_header_details['hover_title'])) ? 'title="' . $cats_header_details['hover_title'] . '"' : '');?> alt="">
<img src="themes/<?=$setts['default_theme'];?>/img/arrow.gif" border="0" hspace="4"><?=$category_lang[$cats_header_details['category_id']];?>
<?=(($setts['enable_cat_counters']) ? (($cats_header_details['items_counter']) ? '(<strong>' . $cats_header_details['items_counter'] . '</strong>)' : '') : '');?></a> </li> <?
}
?>
I get this Warning: Think foreach is returning empty ! cant find the way how to solve it.
Warning: Invalid argument supplied for foreach() in C:\AppServ\www\site\themes\temamiz\templates\categories_box.tpl.php on line 14
And print Main categories on the page with the code below.
<?=$category_box_content;?>
Basically change your pre-template code to first get all category_ids from your categories. Then get a list of subcats which matches that list.
Now process the subs, ordering them to easily be found by their parent id (2nd loop).
Then instead of passing an sql resource to your template (bad form), you hand out the 2 arrays (cats and subcats).
In your template, you then loop through the categories, then within that loop, you have a 2nd loop which loops only over the subcats for that specific category (if any).
In code, like this:
$sql_cats_list = $db->query("SELECT category_id, items_counter, hover_title FROM " . DB_PREFIX . "categories WHERE parent_id=0 AND hidden=0 AND user_id=0 AND enable_auctions=1 ORDER BY order_id ASC, name ASC");
$cats = array();
while($row=$db->fetch_array($sql_cats_list)) {
$cats[$row['category_id']] = $row;
}
$cat_ids = implode(', ', array_keys($cats));
$sql_subcats_list = $db->query("SELECT sub.category_id, sub.items_counter, sub.hover_title, parent.order_id FROM " . DB_PREFIX . "categories sub LEFT JOIN " . DB_PREFIX . "categories parent ON (parent.category_id=sub.parent_id) WHERE parent.category_id IN (" . $cat_ids . ") AND sub.hidden=0 AND sub.user_id=0 AND sub.enable_auctions=1 ORDER BY parent.order_id ASC, sub.order_id ASC, name ASC");
while($row=$db->fetch_array($sql_subcats_list)) {
if(!isset($subs[$row['parent_id']])) {
$subs[$row['parent_id']] = array();
}
$subs[$row['parent_id']][] = $row;
}
$template->set('cats_list', $cats);
$template->set('subs_list', $subs);
$category_box_content = $template->process('categories_box.tpl.php');
$template->set('category_box_content', $category_box_content);
I assume this was your categories_box.tpl.php file (?)
<?php
foreach($cats as $parent_id => $cats_header_details) {
$category_link = process_link('categories', array('category' => $category_lang[$cats_header_details['category_id']], 'parent_id' => $cats_header_details['category_id']));
// subcategory links:
if(isset($subs_list[$parent_id])) {
foreach($subs_list[$parent_id] as $sub) {
// do something with your subcategory
}
}
?>
<li><a style="font-size: 11px; font-weight: normal;" href="<?=$category_link;?>"
<?=((!empty($cats_header_details['hover_title'])) ? 'title="' . $cats_header_details['hover_title'] . '"' : '');?> alt=""><img src="themes/<?=$setts['default_theme'];?>/img/arrow.gif" border="0" hspace="4"><?=$category_lang[$cats_header_details['category_id']];?> <?=(($setts['enable_cat_counters']) ? (($cats_header_details['items_counter']) ? '(<strong>' . $cats_header_details['items_counter'] . '</strong>)' : '') : '');?></a> </li> <?
}
?>
And print Main categories on the page with the code below.
<?=$category_box_content;?>

get category parent id on product page - opencart

Is there a way to get the category parent_id of a product, in the product page of Opencart v1.5.4.1. What am trying to change the button href based on the category parent_id.. If parent_id = 20 then the button should have href1 else href2.
So far, i've done this but its not working.
Added before "$this->load->model('tool/image');"
$product_cat = $this->model_catalog_product->getCategories($product_id);
$product_cat_parent = $this->model_catalog_category->getCategory($product_cat[0]['category_id']);
if ($product_cat_parent['parent_id'] == '20') {
$this->data['sizeguide'] = $this->url->link('faq/faq/info', 'fpath=12');
} else {
$this->data['sizeguide'] = $this->url->link('faq/faq/info', 'fpath=13');
}
in template file:
<a class="button2 sizeguidebox" href="<?php echo $sizeguide; ?>"><?php echo $text_sizeguide; ?></a>
This looks more complicated but it actually simpler and more efficient as a fool proof method of checking. It will pick all of the categories related to the current product, find all their category info, and filter the categories with the parent_id of 20. If the query has any results (i.e. one of the categories is a subcategory of the category with ID 20) then it will set the faq info accordingly
$product_cat = $this->model_catalog_product->getCategories($product_id);
$result = $this->db->query("
SELECT
`c`.`parent_id`
FROM
`" . DB_PREFIX . "category` `c`
LEFT JOIN
`" . DB_PREFIX . "product_to_category` `p2c`
ON
`c`.`category_id` = `p2c`.`category_id`
WHERE
`c`.`parent_id` = '20'
AND
`p2c`.`product_id` = '" . (int) $product_id . "'
");
if($result->num_rows > 0) {
$this->data['sizeguide'] = $this->url->link('faq/faq/info', 'fpath=12');
} else {
$this->data['sizeguide'] = $this->url->link('faq/faq/info', 'fpath=13');
}
Note that this hasn't been tested but should work in theory

showing products after categories php

I have the following markup which shows a list of categories and subcategories:
<table border="0" width="100%" cellspacing="0" cellpadding="2">
<tr class="dataTableHeadingRow">
<td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS; ?></td>
<td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_WEIGHT; ?> </td>
</tr>
<?php
function category_list( $category_parent_id = 0 )
{
$sql = 'select cd.categories_name,c.categories_id, c.parent_id, c.sort_order from ' . TABLE_CATEGORIES . ' c, ' . TABLE_CATEGORIES_DESCRIPTION . ' cd where c.categories_id = cd.categories_id AND c.parent_id='.$category_parent_id;
$res = tep_db_query( $sql );
$cats = array();
while ( $cat = tep_db_fetch_array( $res ) )
{
$cats[] = $cat;
}
if (count($cats) == 0)
{
return '';
}
$list_items = array();
foreach ( $cats as $cat )
{
$list_items[] = '<tr class="dataTableRow"><td class="dataTableContent">';
if($category_parent_id != 0) $list_items[] = ' ';
if($category_parent_id == 0 )$list_items[] = '<b>';
$list_items[] = $cat['categories_name'];
if($category_parent_id == 0) $list_items[] = '</b>';
$list_items[] = '</td><td class="dataTableContent">';
$list_items[] = category_list( $cat['categories_id'] );
$list_items[] = '</td></tr>';
}
$list_items[] = '';
return implode( '', $list_items );
}
echo category_list();
?>
</table>
Each category is show in bold and the sub category is shown slightly indented to the right. I need to show the products available in each of the subcategory's. I tried adding the needed product fields to the sql query, but it didn't respond. The fields I need to add to search for the products are: products_id, products_name, these are from the table TABLE_PRODUCTS_DESCRIPTION, and to sort it their categories, there is another table called TABLE_PRODUCTS_TO_CATEGORIES, which has the fields products_id and categories_id.
How would I go about doing this?
It looks like you are using osCommerce or one of its forks and you want to display the amount of products for each category.
If you have only two levels of categories that's ok to do, if your category tree goes deeper, be warned that this is a real performance killer as building the category-tree in osCommerce is done, let's say, not really performance optimized, especially for complex tree structures.
The straight forward way is, to count the entries of the TABLE_PRODUCTS_TO_CATEGORIES table where the column categories_id holds the current category id:
$query = 'SELECT COUNT(*) FROM `'.TABLE_PRODUCTS_TO_CATEGORIES.'` WHERE `categories_id` = "'.$cat['categories_id'].'"';
Fetch the result and you have the count.
With this approach though you will only get the count of products directly in tnis category, not the count of products which reside in children categories.
You might also have a look on includes/boxes/categories.php as this is already built in in osC - the methods tep_show_category() and the herein called tep_count_products_in_category() might be usable for your purpose so no need to write it yourself.
I don't really like the from thing in the query for joining 2 tables. I have changed the query the way I prefer. You can change it to the from way if you wish.
$sql = 'select cd.categories_name,c.categories_id, c.parent_id, c.sort_order, pd.products_id, pd.products_name
from ' . TABLE_CATEGORIES . ' c
inner join ' . TABLE_CATEGORIES_DESCRIPTION . ' cd on c.categories_id = cd.categories_id
inner join '. TABLE_PRODUCTS_TO_CATEGORIES .' pc on pc.categories_id=c.categories_id
inner join ' . TABLE_PRODUCTS_DESCRIPTION . ' pd on pd.products_id=pc.products_id
where c.parent_id='.$category_parent_id;

Categories