estrich Posted October 23, 2017 Share Posted October 23, 2017 Hello everyone, In our shop we have some categories containing only a single product. I am looking for a way to automatically redirect a user who is clicking on one of these category links directly to the product page. I could do this manually via htaccess but would prefer an automatic solution. Frankly I have no clue where to start without breaking a lot of stuff - does anybody have any pointers for me? Thanks in advance, estrich Link to comment Share on other sites More sharing options...
burt Posted October 23, 2017 Share Posted October 23, 2017 This can be done with zero core code changes by utilising a header_tag module. Header Tags were introduced in the 2.3 series at I think 2.3.1 - so... tell us which version of osCommerce your shop is built with. Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 Hey burt, thanks for the reply - thats good news! I am using the bootstrap gold version. So I implement a header tags module where I check if I am currently in a category and if so if the category only contains 1 item and then just redirect to the product page? Thanks again for the help. estrich Link to comment Share on other sites More sharing options...
douglaswalker Posted October 24, 2017 Share Posted October 24, 2017 1 hour ago, estrich said: Hey burt, thanks for the reply - thats good news! I am using the bootstrap gold version. So I implement a header tags module where I check if I am currently in a category and if so if the category only contains 1 item and then just redirect to the product page? Thanks again for the help. estrich Hi there just wondered if you would like to share the code.. sounds great Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 Sure. This is what I got so far: ht_categories_redirect.php in includes/modules/header_tags/ <?php class ht_categories_redirect { var $code = 'ht_categories_redirect'; var $group = 'header_tags'; var $title; var $description; var $sort_order; var $enabled = false; function __construct() { $this->title = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_TITLE; $this->description = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_DESCRIPTION; if ( defined('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS') ) { $this->sort_order = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER; $this->enabled = (MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS == 'True'); } } function execute() { global $PHP_SELF, $cPath, $current_category_id; if (basename($PHP_SELF) == FILENAME_DEFAULT) { if ($current_category_id > 0) { $product_count = tep_count_products_in_category($current_category_id); if ($product_count == 1) { $product_query = tep_db_query("SELECT p.products_id FROM " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c WHERE p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$current_category_id . "'"); $product = tep_db_fetch_array($product_query); if($product) { tep_redirect(tep_href_link(FILENAME_PRODUCT_INFO, ($cPath ? 'cPath=' . $cPath . '&' : '') . 'products_id=' . (int)$product['products_id'])); } } } } } function isEnabled() { return $this->enabled; } function check() { return defined('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS'); } function install() { tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Categories Redirect Module', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS', 'True', 'Do you want to enable the Categories Redirect module?', '6', '1', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())"); tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort Order', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())"); } function remove() { tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')"); } function keys() { return array('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER'); } } ?> and ht_categories_redirect.php in includes/languages/english/modules/header_tags/ <?php define('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_TITLE', 'Automatic redirect to product page in categories with single product'); define('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_DESCRIPTION', 'Add automatic redirect to product page in categories with single product'); ?> Link to comment Share on other sites More sharing options...
burt Posted October 24, 2017 Share Posted October 24, 2017 @estrich super! well done on this. Now this works, but it can be optimised further to save on queries. When writing code it is always advisable to get something that works (which you have done!), then to optimise and optimise and optimise until it is ready for others to use. If you want to learn how, I can give some "advice" but would then expect you to go away, work on it, then post back where I can give more "advice" and do so again. In other words, I'll point you the right way but won't give you the code. Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 Thanks burt, sure, I can try optimising it - if you have some pointers I'm all ears. Thinking about it, it would probably be good to combine the count query inside tep_count_products_in_category with the products_id query in my module somehow as both are operating on the same set - allthough I am not quite sure yet how to do that. cheers, estrich Link to comment Share on other sites More sharing options...
burt Posted October 24, 2017 Share Posted October 24, 2017 Excellent, and maybe other can follow as well. Or even to point out if the optimisations I come up with can be further or better optimised. What you have here is, be well aware, an excellent start. Well done. Link to comment Share on other sites More sharing options...
burt Posted October 24, 2017 Share Posted October 24, 2017 Optimisation 1: Get rid of the all the FILENAME_* and replace with their actual page names (eg index.php). Optimisation 2: Same for TABLE_*, replace with the actual database table names. At this point after these two optimisations, it is useable on Edge. Post back the code and we will then move onto that execute() function... Link to comment Share on other sites More sharing options...
tgely Posted October 24, 2017 Share Posted October 24, 2017 I wonder if you could use this code without query: global $categories_products_query; // get result if (is_object($categories_products_query) && tep_db_num_rows($categories_products_query) == 1) { // do your stuf // fetch result to get the link } osCommerce based shop owner with minimal design and focused on background works. When the less is more.Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store. Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 ht_categories_redirect.php in includes/modules/header_tags/ <?php class ht_categories_redirect { var $code = 'ht_categories_redirect'; var $group = 'header_tags'; var $title; var $description; var $sort_order; var $enabled = false; function __construct() { $this->title = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_TITLE; $this->description = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_DESCRIPTION; if ( defined('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS') ) { $this->sort_order = MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER; $this->enabled = (MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS == 'True'); } } function execute() { global $PHP_SELF, $cPath, $current_category_id; if (basename($PHP_SELF) == 'index.php') { if ($current_category_id > 0) { $product_count = tep_count_products_in_category($current_category_id); if ($product_count == 1) { $product_query = tep_db_query("SELECT p.products_id FROM products p, products_to_categories p2c WHERE p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$current_category_id . "'"); $product = tep_db_fetch_array($product_query); if($product) { tep_redirect(tep_href_link('product_info.php', ($cPath ? 'cPath=' . $cPath . '&' : '') . 'products_id=' . (int)$product['products_id'])); } } } } } function isEnabled() { return $this->enabled; } function check() { return defined('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS'); } function install() { tep_db_query("INSERT INTO configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) VALUES ('Enable Categories Redirect Module', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS', 'True', 'Do you want to enable the Categories Redirect module?', '6', '1', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())"); tep_db_query("INSERT INTO configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Sort Order', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())"); } function remove() { tep_db_query("DELETE FROM configuration WHERE configuration_key IN ('" . implode("', '", $this->keys()) . "')"); } function keys() { return array('MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_STATUS', 'MODULE_HEADER_TAGS_CATEGORIES_REDIRECT_SORT_ORDER'); } } ?> Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 17 minutes ago, tgely said: I wonder if you could use this code without query: global $categories_products_query; // get result if (is_object($categories_products_query) && tep_db_num_rows($categories_products_query) == 1) { // do your stuf // fetch result to get the link } no, because the $categories_products_query does only check if there are products in the category but not if these products have the status 1 (and are therefor visible). Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 How about this change to the execute function(): <?php function execute() { global $PHP_SELF, $cPath, $current_category_id; if (basename($PHP_SELF) == 'index.php') { if ($current_category_id > 0) { $product_query = tep_db_query("SELECT p.products_id FROM products p, products_to_categories p2c WHERE p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$current_category_id . "'"); if(tep_db_num_rows($product_query) == 1) { $product = tep_db_fetch_array($product_query); if($product) { tep_redirect(tep_href_link('product_info.php', ($cPath ? 'cPath=' . $cPath . '&' : '') . 'products_id=' . (int)$product['products_id'])); } } } } } ?> Link to comment Share on other sites More sharing options...
tgely Posted October 24, 2017 Share Posted October 24, 2017 @estrich sorry I gave a shit example. I didnt see the count(*) in the query. :) Yes the last code use less query. I think its better. osCommerce based shop owner with minimal design and focused on background works. When the less is more.Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store. Link to comment Share on other sites More sharing options...
burt Posted October 24, 2017 Share Posted October 24, 2017 Getting better! In your $product_query, if you group by p2c.products_id ... you then get an aggregated result count... If that result is 1 ... Link to comment Share on other sites More sharing options...
estrich Posted October 24, 2017 Author Share Posted October 24, 2017 Hmm - I'm a bit lost here... If I GROUP BY the products_id I will not get a count of all products_ids using COUNT(*) but a row for each products_id with the count of 1 - or am I missunderstanding something? SELECT count(*), p2c.products_id FROM products p, products_to_categories p2c WHERE p.products_id = p2c.products_id AND p.products_status = '1' and p2c.categories_id = '119' GROUP BY p2c.products_id count(*) products_id 1 424 1 453 1 503 Link to comment Share on other sites More sharing options...
douglaswalker Posted October 24, 2017 Share Posted October 24, 2017 Enjoying this very much Link to comment Share on other sites More sharing options...
burt Posted October 24, 2017 Share Posted October 24, 2017 Count the rows...in the result set. If rows == 1 { do something } else { do nothing } Link to comment Share on other sites More sharing options...
Bob Terveuren Posted October 24, 2017 Share Posted October 24, 2017 $product_query = tep_db_query("SELECT p.products_id FROM products p, products_to_categories p2c WHERE p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$current_category_id . "'"); if(tep_db_num_rows($product_query) == 1) { $product = tep_db_fetch_array($product_query); tep_redirect(tep_href_link('product_info.php', ($cPath ? 'cPath=' . $cPath . '&' : '') . 'products_id=' . (int)$product['products_id'])); } Take your original and cut it down a bit more? Link to comment Share on other sites More sharing options...
estrich Posted October 25, 2017 Author Share Posted October 25, 2017 @burtMaybe I'm missing something but this is what I am already doing in my revised execute function from yesterday: (using tep_db_num_rows...) 18 hours ago, estrich said: How about this change to the execute function(): <?php function execute() { global $PHP_SELF, $cPath, $current_category_id; if (basename($PHP_SELF) == 'index.php') { if ($current_category_id > 0) { $product_query = tep_db_query("SELECT p.products_id FROM products p, products_to_categories p2c WHERE p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$current_category_id . "'"); if(tep_db_num_rows($product_query) == 1) { $product = tep_db_fetch_array($product_query); if($product) { tep_redirect(tep_href_link('product_info.php', ($cPath ? 'cPath=' . $cPath . '&' : '') . 'products_id=' . (int)$product['products_id'])); } } } } } ?> Link to comment Share on other sites More sharing options...
burt Posted October 26, 2017 Share Posted October 26, 2017 Sorry I got myself confused and most likely you too. So basically, look at the products_to_categories table for the category_id, joining the products table on products_id looking at products_status. If the result set is exactly 1; there is 1 product in the category. Do your thing. If the result set is bigger than 1...do nothing. Is it possible that two products can have the same ID in the same category? IE, a linked product? Does anyone use linked products? You don't need this brace, but you do need the tep_redirect: if($product) {} Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.