Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Automatic redirect to product page for categories with single product


estrich

Recommended Posts

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

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

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

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

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

@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

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

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

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

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
}

 

:blink:
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

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

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

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

@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.
 

:blink:
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

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

         $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

@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

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...