Post by loki_racer » Mon Feb 06, 2012 12:27 am

I have read forum discussions covering SEO links for categories. The replies were shameful. Some people said "two objects can occupy the same space at the same time" referring to child categories not being able to have the same SEO URL. This is just plain silly. It's not an issue of two categories having the same SEO URL. The issue is that OpenCart simply looks for the first SEO URL match it fines and runs with that. This is not acceptable. Hopefully in the future we will see OpenCart move categories to a real tree model, but until then, here is my fix.

I need child categories of different parent categories to be able to have the same URL. Example:

Code: Select all

Adult -> Tacos
Child -> Tacos
URL's should be build as
  • /adult/tacos/
  • /child/tacos/
With the stock implementation of OpenCart, it will route both of these URL's to Adult -> Tacos. Some of the forum responses are that we should run these URL's instead
  • /adult/adult_tacos/
  • /child/child_tacos/
This effectively could make for some extremely long URL's if your parent category has a long name.

The following code will fix the URL lookups for OpenCart 1.5.13 (and maybe other versions, I have no interest in testing on other versions). This modification will allow children categories of different parent categories have the same SEO URL. Replace the top part of your /catalog/controller/common/seo_url.php with:

Code: Select all

<?php
class ControllerCommonSeoUrl extends Controller {
    public function index() {
        // Add rewrite to url class
        if ($this->config->get('config_seo_url')) {
            $this->url->addRewrite($this);
        }

        // Decode URL
        if (isset($this->request->get['_route_'])) {
            $parts = explode('/', $this->request->get['_route_']);

            $this_route = $parts;
            $this_route_multistore = $parts;
            array_shift($this_route_multistore);

            $tree = array();  //  this is going to store the last parent category id

            foreach ($parts as $part) {
                $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $this->db->escape($part) . "'");

                if ($query->num_rows) {
                	/*  CUSTOM CODE  this if/else  */
                	if($query->num_rows > 1) {
						//  loop these cats until we find the one that is the sub cat
						foreach($query->rows as $category) {
	                		$url = explode('=', $category['query']);

							$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "category WHERE category_id = '" . $this->db->escape($url[1]) . "' AND parent_id = '" . $this->db->escape(array_pop(array_values($tree))) . "'");

                			if ($query->num_rows) {
                				$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE query = 'category_id=" . $this->db->escape($query->row['category_id']) . "'");
//                				echo '<pre>';print_r($query);echo '</pre>';exit;
								break;
							}
						}
					}
					/*  end CUSTOM CODE  */

	                $url = explode('=', $query->row['query']);

	                if ($url[0] == 'product_id') {
	                    $this->request->get['product_id'] = $url[1];
	                }

	                if ($url[0] == 'category_id') {
	                    if (!isset($this->request->get['path'])) {
	                        $this->request->get['path'] = $url[1];
	                    } else {
	                        $this->request->get['path'] .= '_' . $url[1];
	                    }
                		/*  CUSTOM CODE  */
	                    $tree[] = $url[1];
                		/*  end CUSTOM CODE  */
	                }

	                if ($url[0] == 'manufacturer_id') {
	                    $this->request->get['manufacturer_id'] = $url[1];
	                }

	                if ($url[0] == 'information_id') {
	                    $this->request->get['information_id'] = $url[1];
	                }
                } else {

                        if (is_file(DIR_APPLICATION . 'controller/' . implode("/", $this_route) . '.php') || is_file(DIR_APPLICATION . 'controller/' . implode("/", $this_route_multistore) . '.php')) {
                        $this->request->get['route'] = $this->request->get['_route_'];
                        break;
                        } else {
                        $this->request->get['route'] = 'error/not_found';
                        array_pop($this_route);
                        }

                }
            }

NOTICE - This code should be thoroughly testing in a development environment before implementing it. My implementation is limited to a single store, with categories that are only two levels deep, with only English in use.

Newbie

Posts

Joined
Tue Dec 13, 2011 6:37 pm
Who is online

Users browsing this forum: No registered users and 4 guests