Jump to content
Sign in to follow this  
Timber

Собственный контроллер и SEO-модули

Recommended Posts

Например есть контроллер mycatalog/mycontroller, который вызывается как:

 

mysite.my/index.php?route=mycatalog/mycontroller&mypath_id=3&my_id=5

 

В таблице url_alias прописаны красивые ссылки для mypath_id и my_id

 

SEO-модуль ничего про mycatalog/mycontroller не знает и ссылки этого вида не обрабатывает. Существует ли универсальный способ добавить собственный обработчик для преобразования ссылок, или единственный вариант это вручную вносить изменения в SEO-модуль?

 

Т.е. один раз написать обработчик, который можно было бы подключать к разным SEO-модулям.

 

Вопрос про opencart 2

Edited by Timber

Share this post


Link to post
Share on other sites

Если у вас нет динамических параметров - то реализуется очень просто через seopro, с помощью добавления нужной записи в БД.

Если есть - то конечно необходимо дописывать правила для роутов.

Share this post


Link to post
Share on other sites

Я неделю мучался с написанием своего контроллера для модуля фотогалерей, это был для меня тот еще путь страданий (неделю свободного времени убил). Так же знаю, что пользователь @markimax делал то же самое для своих мега модулей и помог мне в некоторых моментах. За что ему отдельное Спасибо. Вот Вам мой сео контроллер из модуля фотогалерей на базе кэшируемого seo_pro от @freelancer:

У меня там все проще, иерархии и категорий нет. В модуле есть всего 2 раздела

  1. gallery/gallery - список галерей
  2. gallery/photos&album_id=1 - галерея

Но думаю, в контроллер добавить функцию getPathByMyId($id) не составит труда (по аналогии смотрите как сделаны запросы ЧПУ категорий, там есть такая же иерархия). Хранятся ключи и значения SEO в своей таблице, которую нужно создать, чтобы не было конфликтов с другими seo контроллерами.

Для 1.5.x

<?php
/**
* @author Shashakhmetov Talgat <talgatks@gmail.com>
*/
class ControllerCommonSeoGallery extends Controller
{
    private $cache_data = null;
    private $current_store_id = 0;
    public function __construct($registry)
    {
        parent::__construct($registry);
        $this->current_store_id = $this->config->get('config_store_id');
        $cache_name = 'seo_pro_gallery.' . $this->current_store_id;
        $this->cache_data = $this->cache->get($cache_name);
        if (!$this->cache_data) {
            $query            = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias_gallery WHERE store_id = " . $this->current_store_id);
            $this->cache_data = array();
            foreach ($query->rows as $row) {
                $this->cache_data['keywords'][$row['keyword']] = $row['query'];
                $this->cache_data['queries'][$row['query']]    = $row['keyword'];
            }
            
            $query            = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias_gallery WHERE query LIKE '%album_id=%'");
            foreach ($query->rows as $row) {
                $this->cache_data['keywords'][$row['keyword']] = $row['query'];
                $this->cache_data['queries'][$row['query']]    = $row['keyword'];
            }

            $this->cache->set($cache_name, $this->cache_data);
        }
    }
    public function index()
    {
        if ($this->config->get('config_seo_url')) {
            $this->url->addRewrite($this);
        }else{
            return;
        }
        
        if (isset($_GET['_route_']))
            $this->request->get['_route_'] = $_GET['_route_'];
        if (isset($_GET['route']))
            $this->request->get['route'] = $_GET['route'];

        if (isset($this->request->get['album_id'])) {
            $this->request->get['route'] = 'gallery/photos';
            if (isset($this->request->get['_route_'])) {
                $_route_ = $this->request->get['_route_'];
                unset($this->request->get['_route_']);
            }

            $this->validate();
            if (isset($this->request->get['_route_'])) {
                $this->request->get['_route_'] = $_route_;
            }
            $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
            return $this->gallery_flag = 'photos';
        }
        
        if (isset($this->request->get['_route_'])) {
            $route = $this->request->get['_route_'];
            $parts = explode('/', trim(utf8_strtolower($route), '/'));
            list($last_part) = explode('.', array_pop($parts));
            array_push($parts, $last_part);
            // var_dump($parts);
            foreach ($parts as $part) {
                $rows = array();
				foreach ($parts as $keyword) {
					if (isset($this->cache_data['keywords'][$keyword])) {
						$rows[] = array('keyword' => $keyword, 'query' => $this->cache_data['keywords'][$keyword]);
					}
				}
				if (count($rows) == sizeof($parts)) {
					$queries = array();
					foreach ($rows as $row) {
						$queries[utf8_strtolower($row['keyword'])] = $row['query'];
					}

					reset($parts);
					foreach ($parts as $part) {
						$url = explode('=', $queries[$part], 2);

						if (isset($url[0]) && $url[0] == 'album_id') {
	                        $this->request->get['album_id'] = $url[1];
	                        $this->gallery_flag                     = 'photos';
	                    } elseif (isset($url[0]) && $url[0] == 'gallery/gallery') {
	                        $this->gallery_flag = 'gallery';
	                        if (!isset($this->request->get['gallery/gallery'])) {
	                            $this->request->get['route'] = 'gallery/gallery';
	                        } else {
	                            $this->request->get['route'] = 'gallery/gallery';
	                        }
	                    } elseif (isset($url[0]) && $url[0] == 'route') {
	                        $this->request->get['route'] = $url[1];
	                    } elseif (count($url) > 1) {
							$this->request->get[$url[0]] = $url[1];
						}
					}
				}

            }
            if (isset($this->request->get['album_id'])) {
                $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
                $this->request->get['route'] = 'gallery/photos';
            } elseif (isset($this->request->get['gallery/gallery'])) {
                $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
                $this->request->get['route'] = 'gallery/gallery';
            }else{
            	if (isset($queries[$parts[0]])) {
					$this->request->get['route'] = $queries[$parts[0]];
				}
            }
            // var_dump($this->request);
            $_route_ =$this->request->get['_route_'];
			unset($this->request->get['_route_']);
            $this->validate();
            $this->request->get['_route_'] = $_route_;

			if (isset($this->request->get['route'])) {
				$this->request->get['_route_'] = $this->request->get['route'];
			}
            return $this->gallery_flag;
        }
    }
    public function rewrite($link)
    {
        if (!$this->config->get('config_seo_url'))
            return $link;
        $seo_url = '';

        $component = parse_url(str_replace('&', '&', $link));
        $data      = array();
        
        if (isset($component['query'])) {
            parse_str($component['query'], $data);
            if (!isset($data['route'])) {
                return $link;
            }
            $route = $data['route'];

            unset($data['route']);
			
			$postfix = false;
            
            if ($route == 'gallery/photos') {
                if (isset($data['album_id'])) {
                    $tmp              = $data;
                    $data             = array();
                    $data['album_id'] = $tmp['album_id'];
                    if (isset($tmp['limit'])) {
						$data['limit'] = $tmp['limit'];
					}
					if (isset($tmp['page'])) {
						$data['page'] = $tmp['page'];
					}
					$postfix = true;
                }
            } elseif ($route == 'gallery/gallery') {
            	
            } else {
            	return $link;
            }

            if ($component['scheme'] == 'https') {
                $link = $this->config->get('config_ssl');
            } else {
                $link = $this->config->get('config_url');
            }
            $link .= 'index.php?route=' . $route;
            if (count($data)) {
                $link .= '&' . urldecode(http_build_query($data, '', '&'));
            }
            $queries = array();
            foreach ($data as $key => $value) {
                switch ($key) {
                    case 'album_id':
                        $config_gallery_galleries_include_seo_path = $this->config->get('config_gallery_galleries_include_seo_path');
                        if ($config_gallery_galleries_include_seo_path[$this->current_store_id]) {
                            $queries[] = 'gallery/gallery';
                        }
                        $queries[] = $key . '=' . $value;
                        unset($data[$key]);
                        $postfix = true;
                        break;
                    default:
                        break;
                }
            }
            if (empty($queries)) {
                $queries[] = $route;
            }
            $rows = array();
            foreach ($queries as $query) {
                if (isset($this->cache_data['queries'][$query])) {
                    $rows[] = array(
                        'query' => $query,
                        'keyword' => $this->cache_data['queries'][$query]
                    );
                }
            }
            reset($data);
            if (count($rows) == count($queries)) {
                $aliases = array();
                foreach ($rows as $row) {
                    $aliases[$row['query']] = $row['keyword'];
                }
                foreach ($queries as $query) {
                    $seo_url .= '/' . rawurlencode($aliases[$query]);
                }
            }
            if ($seo_url == '')
                return $link;
            if ($seo_url) {
				unset($data['route']);
				$query = '';
				if ($data) {
					foreach ($data as $key => $value) {
						$query .= '&' . $key . '=' . $value;
					}
					if ($query) {
						$query = '?' . trim($query, '&');
					}
				}

				$devider = $this->config->get('config_seo_url_postfix');
				if (empty($devider) || !$postfix) {
					$devider = "/";	
				}


				$link = $component['scheme'] . '://' . $component['host'] . (isset($component['port']) ? ':' . $component['port'] : '') . str_replace('/index.php', '', $component['path']) . $seo_url . $devider . $query;
				return $link;
			} else {
				return $link;
			}
        } else {
            return $link;
        }
    }
    private function validate()
    {
        if (empty($this->request->get['route']) || $this->request->get['route'] == 'error/not_found') {
            return;
        }
        if (isset($this->request->server['HTTP_X_REQUESTED_WITH']) && strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
            return;
        }
        if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
            $url = str_replace('&', '&', $this->config->get('config_ssl') . ltrim($this->request->server['REQUEST_URI'], '/'));
            $seo = str_replace('&', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array(
                'route'
            )), 'SSL'));
        } else {
            $url = str_replace('&', '&', $this->config->get('config_url') . ltrim($this->request->server['REQUEST_URI'], '/'));
            $seo = str_replace('&', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array(
                'route'
            )), 'NONSSL'));
        }
        if (rawurldecode($url) != rawurldecode($seo)) {
            header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
            $this->response->redirect($seo);
        }
    }
    private function getQueryString($exclude = array())
    {
        if (!is_array($exclude)) {
            $exclude = array();
        }
        return urldecode(http_build_query(array_diff_key($this->request->get, array_flip($exclude))));
    }
}
?> 

Для 2.x

<?php
/**
* @author Shashakhmetov Talgat <talgatks@gmail.com>
*/
class ControllerCommonSeoGallery extends Controller
{
    private $cache_data = null;
    private $current_store_id = 0;
    public function __construct($registry)
    {
        parent::__construct($registry);
        $this->current_store_id = $this->config->get('config_store_id');
        $cache_name = 'seo_pro_gallery.' . $this->current_store_id;
        $this->cache_data = $this->cache->get($cache_name);
        if (!$this->cache_data) {
            $query            = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias_gallery WHERE store_id = " . $this->current_store_id);
            $this->cache_data = array();
            foreach ($query->rows as $row) {
                $this->cache_data['keywords'][$row['keyword']] = $row['query'];
                $this->cache_data['queries'][$row['query']]    = $row['keyword'];
            }
            
            $query            = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias_gallery WHERE query LIKE '%album_id=%'");
            foreach ($query->rows as $row) {
                $this->cache_data['keywords'][$row['keyword']] = $row['query'];
                $this->cache_data['queries'][$row['query']]    = $row['keyword'];
            }

            $this->cache->set($cache_name, $this->cache_data);
        }
    }
    public function index()
    {
        if ($this->config->get('config_seo_url')) {
            $this->url->addRewrite($this);
        }else{
            return;
        }
        
        if (isset($_GET['_route_']))
            $this->request->get['_route_'] = $_GET['_route_'];
        if (isset($_GET['route']))
            $this->request->get['route'] = $_GET['route'];

        if (isset($this->request->get['album_id'])) {
            $this->request->get['route'] = 'gallery/photos';
            if (isset($this->request->get['_route_'])) {
                $_route_ = $this->request->get['_route_'];
                unset($this->request->get['_route_']);
            }

            $this->validate();
            if (isset($this->request->get['_route_'])) {
                $this->request->get['_route_'] = $_route_;
            }
            $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
            return $this->gallery_flag = 'photos';
        }
        
        if (isset($this->request->get['_route_'])) {
            $route = $this->request->get['_route_'];
            $parts = explode('/', trim(utf8_strtolower($route), '/'));
            list($last_part) = explode('.', array_pop($parts));
            array_push($parts, $last_part);
            // var_dump($parts);
            foreach ($parts as $part) {
                $rows = array();
				foreach ($parts as $keyword) {
					if (isset($this->cache_data['keywords'][$keyword])) {
						$rows[] = array('keyword' => $keyword, 'query' => $this->cache_data['keywords'][$keyword]);
					}
				}
				if (count($rows) == sizeof($parts)) {
					$queries = array();
					foreach ($rows as $row) {
						$queries[utf8_strtolower($row['keyword'])] = $row['query'];
					}

					reset($parts);
					foreach ($parts as $part) {
						$url = explode('=', $queries[$part], 2);

						if (isset($url[0]) && $url[0] == 'album_id') {
	                        $this->request->get['album_id'] = $url[1];
	                        $this->gallery_flag                     = 'photos';
	                    } elseif (isset($url[0]) && $url[0] == 'gallery/gallery') {
	                        $this->gallery_flag = 'gallery';
	                        if (!isset($this->request->get['gallery/gallery'])) {
	                            $this->request->get['route'] = 'gallery/gallery';
	                        } else {
	                            $this->request->get['route'] = 'gallery/gallery';
	                        }
	                    } elseif (isset($url[0]) && $url[0] == 'route') {
	                        $this->request->get['route'] = $url[1];
	                    } elseif (count($url) > 1) {
							$this->request->get[$url[0]] = $url[1];
						}
					}
				}

            }
            if (isset($this->request->get['album_id'])) {
                $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
                $this->request->get['route'] = 'gallery/photos';
            } elseif (isset($this->request->get['gallery/gallery'])) {
                $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 200 OK');
                $this->request->get['route'] = 'gallery/gallery';
            }else{
            	if (isset($queries[$parts[0]])) {
					$this->request->get['route'] = $queries[$parts[0]];
				}
            }
            // var_dump($this->request);
            $_route_ =$this->request->get['_route_'];
			unset($this->request->get['_route_']);
            $this->validate();
            $this->request->get['_route_'] = $_route_;

			if (isset($this->request->get['route'])) {
				$this->request->get['_route_'] = $this->request->get['route'];
			}
            return $this->gallery_flag;
        }
    }
    public function rewrite($link)
    {
        if (!$this->config->get('config_seo_url'))
            return $link;
        $seo_url = '';

        $component = parse_url(str_replace('&', '&', $link));
        $data      = array();
        
        if (isset($component['query'])) {
            parse_str($component['query'], $data);
            if (!isset($data['route'])) {
                return $link;
            }
            $route = $data['route'];

            unset($data['route']);
			
			$postfix = false;
            
            if ($route == 'gallery/photos') {
                if (isset($data['album_id'])) {
                    $tmp              = $data;
                    $data             = array();
                    $data['album_id'] = $tmp['album_id'];
                    if (isset($tmp['limit'])) {
						$data['limit'] = $tmp['limit'];
					}
					if (isset($tmp['page'])) {
						$data['page'] = $tmp['page'];
					}
					$postfix = true;
                }
            } elseif ($route == 'gallery/gallery') {
            	
            } else {
            	return $link;
            }

            if ($component['scheme'] == 'https') {
                $link = $this->config->get('config_ssl');
            } else {
                $link = $this->config->get('config_url');
            }
            $link .= 'index.php?route=' . $route;
            if (count($data)) {
                $link .= '&' . urldecode(http_build_query($data, '', '&'));
            }
            $queries = array();
            foreach ($data as $key => $value) {
                switch ($key) {
                    case 'album_id':
                        $config_gallery_galleries_include_seo_path = $this->config->get('config_gallery_galleries_include_seo_path');
                        if ($config_gallery_galleries_include_seo_path[$this->current_store_id]) {
                            $queries[] = 'gallery/gallery';
                        }
                        $queries[] = $key . '=' . $value;
                        unset($data[$key]);
                        $postfix = true;
                        break;
                    default:
                        break;
                }
            }
            if (empty($queries)) {
                $queries[] = $route;
            }
            $rows = array();
            foreach ($queries as $query) {
                if (isset($this->cache_data['queries'][$query])) {
                    $rows[] = array(
                        'query' => $query,
                        'keyword' => $this->cache_data['queries'][$query]
                    );
                }
            }
            reset($data);
            if (count($rows) == count($queries)) {
                $aliases = array();
                foreach ($rows as $row) {
                    $aliases[$row['query']] = $row['keyword'];
                }
                foreach ($queries as $query) {
                    $seo_url .= '/' . rawurlencode($aliases[$query]);
                }
            }
            if ($seo_url == '')
                return $link;
            if ($seo_url) {
				unset($data['route']);
				$query = '';
				if ($data) {
					foreach ($data as $key => $value) {
						$query .= '&' . $key . '=' . $value;
					}
					if ($query) {
						$query = '?' . trim($query, '&');
					}
				}

				$devider = $this->config->get('config_seo_url_postfix');
				if (empty($devider) || !$postfix) {
					$devider = "/";	
				}


				$link = $component['scheme'] . '://' . $component['host'] . (isset($component['port']) ? ':' . $component['port'] : '') . str_replace('/index.php', '', $component['path']) . $seo_url . $devider . $query;
				return $link;
			} else {
				return $link;
			}
        } else {
            return $link;
        }
    }
    private function validate()
    {
        if (empty($this->request->get['route']) || $this->request->get['route'] == 'error/not_found') {
            return;
        }
        if (isset($this->request->server['HTTP_X_REQUESTED_WITH']) && strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
            return;
        }
        if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
            $url = str_replace('&', '&', $this->config->get('config_ssl') . ltrim($this->request->server['REQUEST_URI'], '/'));
            $seo = str_replace('&', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array(
                'route'
            )), 'SSL'));
        } else {
            $url = str_replace('&', '&', $this->config->get('config_url') . ltrim($this->request->server['REQUEST_URI'], '/'));
            $seo = str_replace('&', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array(
                'route'
            )), 'NONSSL'));
        }
        if (rawurldecode($url) != rawurldecode($seo)) {
            header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
            $this->response->redirect($seo);
        }
    }
    private function getQueryString($exclude = array())
    {
        if (!is_array($exclude)) {
            $exclude = array();
        }
        return urldecode(http_build_query(array_diff_key($this->request->get, array_flip($exclude))));
    }
}
?> 

Таблица:

$sql[] = "CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "url_alias_gallery` (
  `url_alias_id` int(11) NOT NULL AUTO_INCREMENT,
  `query` varchar(255) NOT NULL,
  `keyword` varchar(255) NOT NULL,
  `store_id` int(11) NOT NULL,
  PRIMARY KEY (`url_alias_id`),
  KEY `query` (`query`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;";

Edited by halfhope

Share this post


Link to post
Share on other sites

Еще забыл упомянуть, что должен быть модуль, размещенный на странице ошибки (схема error/not_found). Он должен получить флаг о том, что seo_контроллер отработал свое, обработал УРЛ выдал правильную ссылку, затем слелал на нее редирект, запустился снова и поставил флаг. Грубо говоря сайт отправляет посетителя на страницу ошибки, но с нее не поступает 404, а поступает 301 на правильный УРЛ. Затем он проверяет УРЛ и ставит флаг о том, что пользователь находится в разделе списка галерей или в разделе галареи.

 

Вот так выглядит код модуля, который нужно размещать на странице ошибки:

if ($this->config->get("seogallery") != 1) {

    $this->load->controller('common/seo_gallery');
    $this->config->set("seogallery", 1);

    if ($this->gallery_flag == 'photos') {
        $this->load->controller('gallery/photos');
        $this->response->output();
        exit();
    }

    if ($this->gallery_flag == 'gallery') {
        $this->load->controller('gallery/gallery');
        $this->response->output();
        exit();
    }
}

Share this post


Link to post
Share on other sites

Отличные вы оба два с Марком парни, только вот не задумываетесь о том, что создание дополнительных отдельных seo-контроллеров, вынесеных из общего контекста базового seo-класса в случае с исползованием сео про создают совершенно непонятно зачем дополнительную нагрузку на работу системы в виде запроса на чтение всей (еще одной) таблицы  с с новыми seo-урлами, потом укладывание ее в кеш с сериализацией. Не совсем легкие процедуры, которые вы дублируете.

Почему нельзя путем модификаторов внедрить логику формирования нужны роутов в тот же базовый класс SeoPro - для меня большая загадка. Кроме как "а посмотрите как мы умеем" другого объяснения я не вижу. А то что при этом + 50-500 миллисекунд отбирается у сервера. Так это ж никого не волнует.

  • +1 1

Share this post


Link to post
Share on other sites

 

Еще забыл упомянуть, что должен быть модуль, размещенный на странице ошибки (схема error/not_found). Он должен получить флаг о том, что seo_контроллер отработал свое, обработал УРЛ выдал правильную ссылку, затем слелал на нее редирект, запустился снова и поставил флаг. Грубо говоря сайт отправляет посетителя на страницу ошибки, но с нее не поступает 404, а поступает 301 на правильный УРЛ. Затем он проверяет УРЛ и ставит флаг о том, что пользователь находится в разделе списка галерей или в разделе галареи.

 

Вот так выглядит код модуля, который нужно размещать на странице ошибки:

if ($this->config->get("seogallery") != 1) {

    $this->load->controller('common/seo_gallery');
    $this->config->set("seogallery", 1);

    if ($this->gallery_flag == 'photos') {
        $this->load->controller('gallery/photos');
        $this->response->output();
        exit();
    }

    if ($this->gallery_flag == 'gallery') {
        $this->load->controller('gallery/gallery');
        $this->response->output();
        exit();
    }
}

А еще в роутере index() вашего ЧПУ формирователя

Можно вставлять расширение для "виджетов" ваших путей контроллера 

Что то типа такого:

            foreach ($this->data['agoo_widgets'] as $nm => $agoo_widget) {
                if (!empty($module_data) &&  $type == $agoo_widget) {
                    if (file_exists(DIR_APPLICATION . "controller/agoo/".$agoo_widget."/".$agoo_widget.".php")) {
                        $this->cont('agoo/'.$agoo_widget.'/'.$agoo_widget);
                        $controller_agoo = 'controller_agoo_'.$agoo_widget.'_'.$agoo_widget;
                         if (method_exists($this->registry->get($controller_agoo), 'seourl'))
                         $this->data = $this->$controller_agoo->seourl($this->data);
                     }
                }
            }

И описывать их отдельно в контроллерах

Share this post


Link to post
Share on other sites

Отличные вы оба два с Марком парни....

Нет - ты не прав. Не создает никакой нагрузки, просто ты еще не разбирался с этим вопросом ;)

Seo_pro отработал - не нашел ссылки у себя и передал управление другому ЧПУ формирователю

Так что архитектурно - все правильно и логично

Какая разница кто обработает ЧПУ - никакой

"Отбирается" всего ничего 0.00... это вообще не критично. К тому же вся таблица "новых" URL кешируется

Т е запросов НЕТ вообще

 

А вот модификаторы - это проблема.

Постоянные проблемы слета. Код модификаторами меняется иногда до не узнаваемости ЧУЖИМИ модулями, привязка может быть изменена и ЧПУ слетают все из-за кривых рук других.

Вы хотите зависеть в ЧПУ от других - флаг в руки и постоянные траблы

Модификаторы - путь к не стабильности.

Спасибо её нам не надо

Share this post


Link to post
Share on other sites

Нет - ты не прав. Не создает никакой нагрузки, просто ты еще не разбирался с этим вопросом ;)

"Отбирается" всего ничего 0.00... это вообще не критично. К тому же вся таблица "новых" URL кешируется

Т е запросов НЕТ вообще

 

А вот модификаторы - это проблема.

Постоянные проблемы слета. Код модификаторами меняется иногда до не узнаваемости ЧУЖИМИ модулями и привязка может быть изменена и ЧПУ слетают все из-за кривых рук других.

Вы хотите зависеть в ЧПУ от других - флаг в руки и постоянные траблы

 

Т.е. если у нас 35 000 товаров к примеру. При старте системы - даже если мы из кеша берем готовый файл со всем урлами, потом unserialize его в массив....

И считаем скорость поиска файла + скорость чтения файла (а он будет около 10-12мб) + unserialize массива и потом еще одна подобная операция, но уже на меньшем количестве данных...

К чему нужна еще одна абсолютно однотипная операция?

Хоть прав я, хоть не прав, я никогда не пойму write less, do more.

 

Это же однотипные операции, зачем им создавать паралельный класс? Потому что так круто ?

Share this post


Link to post
Share on other sites
Я не хотел еб*ть себе мозг ни себе ни клиентам, чтобы патчить у каждого клиента его seo контроллер, который еще и из под pav вообще шаблонов не работает. Да еще и с введением модификаций в 2.0 это вообще геморрой. Так проще, быстрей и более правильно, раз архитектура OpenCart сама позволяет это делать. Марк прав, он не грузит систему, попробуйте сами. 

  • +1 1

Share this post


Link to post
Share on other sites

Т.е. если у нас 35 000 товаров к примеру.

:) Да в opencart сколько классов за раз отрабатывает ? Вот то то же. На один класс больше из более сотен

Закроем этот вопрос - ты в нем не разбирался до конца.

В отличии от костылей vqmod и модификаторов - работает стабильно, никогда не вылетает, не зависит от ДРУГИХ ЧПУ (не имеет значения seo_url, seo_pro, seo_gallery, ....) формирователей  и работает так же быстро.

Ты наверно знаешь сколько за раз кеширует opencart файлов и то что на один больше - роли не играет совершено.

Просто все ленятся по правильному делать - и сандалят костыли. А потом во всех темах пользователи задают вопросы... у меня не работает ЧПУ, у меня слетели ЧПУ, у меня ЧПУ ... Это все из-за ленивых костылей.

Share this post


Link to post
Share on other sites

:) Да в opencart сколько классов за раз отрабатывает ? Вот то то же. На один класс больше из более сотен

Закроем этот вопрос - ты в нем не разбирался до конца.

В отличии от костылей vqmod и модификаторов - работает стабильно, никогда не вылетает, не зависит от ДРУГИХ ЧПУ (не имеет значения seo_url, seo_pro, seo_gallery, ....) формирователей  и работает так же быстро.

Ты наверно знаешь сколько за раз кеширует opencart файлов и то что на один больше - роли не играет совершено.

Просто все ленятся по правильному делать - и сандалят костыли. А потом во всех темах пользователи задают вопросы... у меня не работает ЧПУ, у меня слетели ЧПУ, у меня ЧПУ ... Это все из-за ленивых костылей.

 

Да хоть сто миллионов раз оно будет беспроблемно работать. Но выносить типизированную логику за рамки контекста основного класса - я считаю полным бредом.

Share this post


Link to post
Share on other sites

Да хоть сто миллионов раз оно будет беспроблемно работать. Но выносить типизированную логику за рамки контекста основного класса - я считаю полным бредом.

 

Бред = OpenCart

Share this post


Link to post
Share on other sites

Кстати для этого Даниэль и сделал  в url.php

    public function addRewrite($hook) {
        $this->hook[] = $hook;
    }

    public function rewrite($url) {
        foreach ($this->hook as $hook) {
            $url = $hook->rewrite($url);
        }

        return $url;
    }

Можно где хочешь вызвать обработчик

require_once(DIR_CATALOG . 'controller/common/seo.....php');
$seo... = new ControllerCommonSeo.... ($this->registry);
$this->url->addRewrite($seo...);

Так что всё согласно культуры архитектуры opencart

 

А вот костыли модификаторов и vqmod - это 3.14ц как грубо и не правильно

  • +1 1

Share this post


Link to post
Share on other sites

Да хоть сто миллионов раз оно будет беспроблемно работать. Но выносить типизированную логику за рамки контекста основного класса - я считаю полным бредом.

 

Бред - это патчить ЧПУ формирователь стандартный, когда для этого есть инструментарий opencart!

https://opencartforum.com/topic/53294-собственный-контроллер-и-seo-модули/?do=findComment&comment=469231

Постом выше

так что "не надо"

Не разобрался - лучше ...

Share this post


Link to post
Share on other sites

Кстати для этого в этого и сделал  в url.php

    public function addRewrite($hook) {
        $this->hook[] = $hook;
    }

    public function rewrite($url) {
        foreach ($this->hook as $hook) {
            $url = $hook->rewrite($url);
        }

        return $url;
    }

Можно где хочешь вызвать обработчик

require_once(DIR_CATALOG . 'controller/common/seo.....php');
$seo... = new ControllerCommonSeo.... ($this->registry);
$this->url->addRewrite($seo...);

Так что всё согласно культуры архитектуры opencart

 

А вот костыли модификаторов и vqmod - это 3.14ц как грубо и не правильно

 

Можно из Opencart сделать WorPress - вопросов нет.

Share this post


Link to post
Share on other sites

Можно из Opencart сделать WorPress - вопросов нет.

 

Причем здесь эта демагогия...

 

Так задумал разработчик opencart

Он специально сделал url = $hook->rewrite($url); для этого (обработки ЧПУ), он специально сделал контроллер not_found (правда роутер там забыл поставить, но и так всё отлично). Специально сделал addHeader($header) $this->headers[] = $header;

А то что разработчики балбесы и ленятся сделать согласно культуре opencart, просто говорит об их низкой квалификации или лени.

Из-за чего потом opencart ругают про не стабильность и т.п. Необоснованно кстати, из-за лени разработчиков модулей

 

 

 

Бред = OpenCart

 

Не правда ваша - opencart на сегодня имеет самую лучшую архитектуру

Share this post


Link to post
Share on other sites

url = $hook->rewrite($url);  - это все равно повторная цепочка однотипных операций.

Модификаторы же позволяют делать все на уровне базового кода.

 

Сколько угодно можем спорить. Но если есть возможность не переписывать целиком каждый раз весь класс, я его переписывать не буду.

 

Хуки - это может кому то и хорошо, но это спагетти, в которых отсутсвует возможность контроля выполнения модификаций и в случае их наслоения на выходе мы можем получить еще большие сюрпризы, чем необходимость поправить привязки модификаторов.

Share this post


Link to post
Share on other sites
....

 

Сколько угодно можем спорить. ...

Да никто и спорить не будет. То что написал это полный бред. Извини, но из песни слов не выкинешь

Какие к моНАХам однотипные операции...

Вызов класса - это однотипная операция ?  :-D  :ugeek:  Давай вообще ООП отменим, будем только костылями все делать. "Напишем" cms без ООП

Патчить модификаторами это бред и 3.14ц как не правильно согласно культуре opencart

Что сказать.

Заблуждайся дальше.

Постоянные сюрпризы только от vqmod патчей и модификаторов, которые до неузнаваемости пропатчивают ЧПУ формирователь, что потом некуда "привязаться" или что еще хуже начинается каша и каждый тянет одеяло в свою сторону

От грамотной архитектуры - сюрпризов нет вообще

Это в других темах только - "у меня не работают чпу модуля, хотя vqmod стоит" и т п

90% вот таких запросов на простых модулях. У меня и  halfhope (можешь посмотреть в темах поддержки) нет таких запросов априори. Потому что ЧПУ формирователь модуля не зависимый

Share this post


Link to post
Share on other sites

У halfhope не могу спрашивать, религия не позволяет, в личку напишу если что, почему.

 

Но где я говорил про отмену ООП.

У нас есть класс seo_pro - зачем еще один диспетчер роутов внедрять совершенно однотипный ?
В том коде, который вы привели, добавок в три строки.

ВЫ же написали целые простыни.

И кто говорит про пишем меньше и проще ?

Share this post


Link to post
Share on other sites

У halfhope не могу спрашивать, религия не позволяет, в личку напишу если что, почему.

 

Но где я говорил про отмену ООП.

Почти намекаешь ;)

А теперь задача такая - для каждого языка свой URL ;)

Ну и где уже однотипный уже ЧПУ формирователь

Лишний вызов класса из СОТНИ вызов никак не отражается ни на чем.

Наоборот - только стабильнее система.

Это культура opencart

snastik - извини, но из песни слов не выкинешь :-D

Просто нас читают начинающие разработчики, а ты им советуешь наплевать на культуру кода архитектуры opencart

Если делать как задумывал Даниэль - то все будет отлично и стабильно работать

99% модулей можно вообще без vqmod и патчей сделать

Просто все ленятся и сандалят костыли

Отсюда и не стабильность opencart, не из-за него самого, а из-за разработчиков модулей

Share this post


Link to post
Share on other sites

Люди добрые помогите)))
 

Написал свой функционал "Линии товаров" контроллер product/product_line
Которые у своей таблице в БД привязаны к определенному manufacturer_id

Как на seo_pro сделать формирование ссылки у product_line относительно производителя

Аналогично производителю я дописал product_line в seo_pro и сами по себе линии товаров работают

 

Ссылка на производителя https://deadseainbaku.az/ahava
Ссылка на линию товаров https://deadseainbaku.az/dead-sea-osmotertm-concentrate
 
А нужно получить ссылку https://deadseainbaku.az/ahava/dead-sea-osmotertm-concentrate

How to?

Share this post


Link to post
Share on other sites

Я как-то делал похожее, только Вам нужно вместо zzzz поставить производителя, а его, в свою очередь, взять из БД. И вместо категорий у вас будет использоваться линия товаров. Нет там ничего сложного. просто прочтите и поймете что да как. Вот еще похожая тема, но там решения пока что нет.

Edited by afwollis

Share this post


Link to post
Share on other sites

Вот так выглядит код модуля, который нужно размещать на странице ошибки:

if ($this->config->get("seogallery") != 1) {

    $this->load->controller('common/seo_gallery');
    $this->config->set("seogallery", 1);

    if ($this->gallery_flag == 'photos') {
        $this->load->controller('gallery/photos');
        $this->response->output();
        exit();
    }

    if ($this->gallery_flag == 'gallery') {
        $this->load->controller('gallery/gallery');
        $this->response->output();
        exit();
    }
}

 

Спасибо всем за подсказку. Правильно я понимаю, что этот код надо размещать в контроллере error/not_found.php?

 

То есть преобразуем mysite.ext/path/entity => mysite.ext/index.php?route=mycatalog/mycontroller&mypath=3&myitem=5

 

Соответственно получается, что в том случае, если mypath=3 myitem=5 не существует, то уже mycatalog/mycontroller отправит пользователя на error/not_found

 

Может тогда имеет смысл скопировать оригинальный error/not_found.php и, в случае ошибки, вызывает из своего контроллера уже его? Соответственно можно избавиться от флагов.

Share this post


Link to post
Share on other sites

Это код контроллера hook модуля, который будет размещен в шапке сайта страницы ошибки, а не код контроллера страницы ошибки.

 

Короче пользователь переходит по ссылке mysite.ext/path/entity, стандартный SEO контроллер видит, что ее не существует и выводит содержимое страницы ошибки, но если в шапке страницы ошибки поставить подгрузку своего SEO контроллера (через модуль и тот код, что я прислал) он проверит ссылку, выставит флаг о том что страница есть и она принадлежит модулю и в соответствии с тем какой флаг выставили - загрузит тот или иной раздел. А если ссылка не прошла проверку, то выводится стандартная страница ошибки.

Share this post


Link to post
Share on other sites

А где тогда этот код размещать? Просто не пойму, что значит "шапка страницы ошибки"

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
You are posting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Similar Content

    • By 29aleksey
      Адаптивный универсальный шаблон PixelShop 2x

      Все архивы подписаны согласно версиям движка !
      Админка
      Логин: demo
      Пароль: demo



      Обязательная установка IonCube Loader.
      Cписок функционала и модулей (Все эти модули есть в шаблоне)
      Управление торговлей 6 Персональный редактор ++ 1.1 Описание модуля Управление торговлей 3 - быстрый заказ Описание модуля Управление торговлей 1 - Обатный звонок Описание модуля Управление торговлей 7 - Product any Описание модуля Быстрая обработка заказов Описание модуля Быстрый просмотр товара Описание модуля Popup c Подтвержением | Информацией Описание Модуля Баннеры блоки (модуль баннеров) Стена категорий + производители Цена закупки поле в админке Слайдер для Категорий Мультиязычный (для каждой категории можно задать свой слайдер) Мега меню Вкладки модулей TABS (5 в 1) 3 вид Прайс - лист Показать еще товар (ajax загрузка товара) 29 дополнительных позиций для главной страницы + 3 позиции с возможностью задать фон или заливку одним цветом 11 дополнительных позиций для страницы Категорий Стикеры товара(4 вида стикера - акция, хит продаж, новинки, топ продаж. все они настраиваются как Вам угодно) Контактная информация в шапке сайта Контактная информация в подвал сайта Способ оплаты Социальные сети Дополнительные картинки товара во всех модулях, страницах при наведении, можно отключить в настройках, изменить на другую анимацию. Кнопки быстрый заказ, в закладки, в сравнение можно отключить для каждого модуля и для каждой старницы, Описание товара можно отключить для каждого модуля(страницы отдельно) Модель товара можно отключить для каждого модуля(страницы отдельно) Рейтинг товара - можно отключить Количество отзывов - можно включить / выключить в настройках модуля по клику на количество отзывов открываются отзывы товара в карточке товара. Предустановлены 3 цветовые схемы Основное меню постоянно открыто либо закрыто (Настраивается в настройках шаблона) Google Map + Кластеризация меток и Описанием Магазина Popup Авторизация на сайте ! One Page Checkout Нашли дешевле Дополнительные вкладки для товара Отзывы Покупателей Опция (Цвет) Продукты из категорий + баннеры Дополнительные изображения (слайдер или смена изображения при наведении ну и выкл) 3 вид прайс лист для страниц акций поиска производителя Основной меню всегда открыто(Главная / Категории/ Поиск / Производитель / Информация) Вывод Опций в модулях Вывод Опций на страницах: Категории , Поиск, Акция, Производители Отображать только обязательные опции Кнопка купить когда товара нет в наличии менять текст на любой который задали в админке (да / нет ) Отображение статуса товара когда товара отсутствует (да / нет) Фиксированная панель в шапке при прокрутке страницы Оптимизация Стилей и Скриптов + Кеш этих файлов Отзывы(добавил Достоинства, недостатки, уже купил ) Автоматическое создание категорий для меню Возможность открывать ссылку с баннера в popup окне дополнительные ссылки в верхнем меню Упрощенное оформление заказа
    • By 29aleksey
      1 000.00 руб
      Скачать/Купить дополнение


      Адаптивный универсальный шаблон - PixelShop
      Адаптивный универсальный шаблон PixelShop 2x

      Все архивы подписаны согласно версиям движка !
      Админка
      Логин: demo
      Пароль: demo



      Обязательная установка IonCube Loader.
      Cписок функционала и модулей (Все эти модули есть в шаблоне)
      Управление торговлей 6 Персональный редактор ++ 1.1 Описание модуля Управление торговлей 3 - быстрый заказ Описание модуля Управление торговлей 1 - Обатный звонок Описание модуля Управление торговлей 7 - Product any Описание модуля Быстрая обработка заказов Описание модуля Быстрый просмотр товара Описание модуля Popup c Подтвержением | Информацией Описание Модуля Баннеры блоки (модуль баннеров) Стена категорий + производители Цена закупки поле в админке Слайдер для Категорий Мультиязычный (для каждой категории можно задать свой слайдер) Мега меню Вкладки модулей TABS (5 в 1) 3 вид Прайс - лист Показать еще товар (ajax загрузка товара) 29 дополнительных позиций для главной страницы + 3 позиции с возможностью задать фон или заливку одним цветом 11 дополнительных позиций для страницы Категорий Стикеры товара(4 вида стикера - акция, хит продаж, новинки, топ продаж. все они настраиваются как Вам угодно) Контактная информация в шапке сайта Контактная информация в подвал сайта Способ оплаты Социальные сети Дополнительные картинки товара во всех модулях, страницах при наведении, можно отключить в настройках, изменить на другую анимацию. Кнопки быстрый заказ, в закладки, в сравнение можно отключить для каждого модуля и для каждой старницы, Описание товара можно отключить для каждого модуля(страницы отдельно) Модель товара можно отключить для каждого модуля(страницы отдельно) Рейтинг товара - можно отключить Количество отзывов - можно включить / выключить в настройках модуля по клику на количество отзывов открываются отзывы товара в карточке товара. Предустановлены 3 цветовые схемы Основное меню постоянно открыто либо закрыто (Настраивается в настройках шаблона) Google Map + Кластеризация меток и Описанием Магазина Popup Авторизация на сайте ! One Page Checkout Нашли дешевле Дополнительные вкладки для товара Отзывы Покупателей Опция (Цвет) Продукты из категорий + баннеры Дополнительные изображения (слайдер или смена изображения при наведении ну и выкл) 3 вид прайс лист для страниц акций поиска производителя Основной меню всегда открыто(Главная / Категории/ Поиск / Производитель / Информация) Вывод Опций в модулях Вывод Опций на страницах: Категории , Поиск, Акция, Производители Отображать только обязательные опции Кнопка купить когда товара нет в наличии менять текст на любой который задали в админке (да / нет ) Отображение статуса товара когда товара отсутствует (да / нет) Фиксированная панель в шапке при прокрутке страницы Оптимизация Стилей и Скриптов + Кеш этих файлов Отзывы(добавил Достоинства, недостатки, уже купил ) Автоматическое создание категорий для меню Возможность открывать ссылку с баннера в popup окне дополнительные ссылки в верхнем меню Упрощенное оформление заказа Добавил 29aleksey Добавлено 22.11.2016 Категория Платные шаблоны Системные требования Ioncube Loader Сайт разработчика Старая цена Метод активации По запросу в ЛС Ioncube Loader Требуется OpenCart 2.3
      2.2
      2.1 ocStore 2.3
      2.2
      2.1 OpenCart.Pro, ocShop Opencart.pro 2.3
      Opencart.pro 2.1 Обращение к серверу разработчика Да  
    • By xds
      Обратите внимание! Вышел новый шаблон Frame Theme для OpenCart 3. Все владельцы лицензии на Coloring могут получить лицензию на Frame на льготных условиях. За подробностями обращайтесь в ЛС
       
      ----------------------------------------
       
      Coloring Theme - это современный адаптивный шаблон для опенкарт 2.x, включающий в себя комплекс дополнительных модулей и настроек, необходимых для полноценной работы современного интернет магазина. Шаблон построен на базе популярного фреймворка Bootstrap 3 и максимально использует его возможности в своей работе. Шаблон обладает продуманными юзабилити и интуитивно понятным интерфейсом, от которых, как известно, напрямую зависит конверсия интернет магазина.
       
      Демонстрация
       
      Главная страница: открыть в новой вкладке Страница товара: открыть в новой вкладке Страница категории: открыть в новой вкладке Администрирование: открыть в новой вкладке, доступ: demo / demo Тестовый доступ для для покупателя: demo@xds.by / demo  
      Услуги автора шаблона
       
      Установка движка, шаблона на ваш хостинг Установка шаблона на действующий магазин Индивидуальные доработки шаблона Создание магазина "под ключ" на базе шаблона   
      По всем вопросам обращайтесь в ЛС или на почту info@xds.by
       
      Описание шаблона
       
      Помимо базовых возможностей движка, шаблон несет в себе целый комплекс дополнительных настроек и модулей, таких как: форма заказа обратного звонка, быстрый заказ товаров, быстрый просмотр товаров, всплывающая корзина, дополнительные модули-карусели товаров с расширенными настройками, настраиваемые контакты в шапке сайта, 2 дополнительных меню в шапке сайта, настраиваемое меню категорий с функцией “амазон-меню”, иконки платежных систем в подвале сайта, интерактивная карта в подвале сайта, микро разметка в карточке товара и пр. Функционал шаблона постоянно расширяется и дополняется, поэтому нету смысла перечислять здесь все его возможности. Лучше один раз увидеть, чем 100 раз услышать прочитать)
       
      Конечно, можно попытаться собрать подобный функционал самостоятельно из сторонних модулей, но это обойдется вам в приличную сумму в разы превышающую стоимость шаблона. А ведь все эти модули нужно еще заставить работать вместе. И работать корректно и быстро. А потом все это надо оформить в едином стиле, со вкусом и знанием дела. В шаблоне все эти модули работают как “единый организм” и максимально задействуют базовый набор плагинов, предоставляемый движком opencart, что положительно сказывается на производительности и скорости работы шаблона.
       
      Системные требования
       
      Для корректной работы шаблона начиная с версии 1.3.0 на вашем хостинге должен быть установлен IonCube Loader версии не ниже 4.4 с PHP не ниже 5.3. У подавляющего большинства современных хостингов с этим проблем нет, но, на всякий случай, уточняйте эту информацию у вашего хостера перед покупкой. В остальном, системные требования шаблона идентичны требованиям opencart.
       
      Совместимость
       
      Шаблон тестировался и точно работает с оригинальной сборкой opencart а так же со сборкой от myopencart.com и ocstore. На других сборках шаблон не тестировался и за его работоспособность на них, я не отвечаю. Обратите внимание, что как правило, версии шаблона для более ранних версий движка имеют более ограниченный функционал, чем для новых. Обычно в названии архива с шаблоном обозначено для какой версии opencart он предназначен.
       
      Лицензия / условия использования
       
      Шаблон реализуется по принципу: “1 копия на 1 домен + 1 тестовый домен”. Шаблон лицензируется путем внесения вашего домена в лицензионную базу данных. После покупки, вам необходимо сообщить мне домены для активации через личные сообщения на этом форуме. Если вы не можете написать мне личное сообщение, то вероятнее всего вы не активировали вашу учетную запись на данном форуме. Возможность писать ЛС появится только после ее активации.
       
      Техническая поддержка
       
      Обязательным условием получения технической поддержки является соблюдение системных требований шаблона и Openсart!!! Техническая поддержка покупателей шаблона осуществляется только через личные сообщения на данном форуме и доступна только пользователям, числящимся в списке покупателей шаблона. Без исключений! При обращении за поддержкой указывайте версию движка, версию шаблона и прилагайте ссылку на проблемную страницу
       
      Условия покупки шаблона
       
      Предметом сделки является шаблон в том виде, в котором он существует на момент покупки. Все последующие обновления и техническая поддержка доступны покупателям бесплатно, но являются бонусом-дополнением к покупке, а не составной частью этой покупки. Шаблон, как и любые другие цифровые товары, не подлежит возврату и обмену. Покупая шаблон в любом из официальных источников вы соглашаетесь со всем вышеизложенным.
      .
    • By xds
      990.00 руб
      Скачать/Купить дополнение


      Coloring Theme - адаптивный шаблон для OpenСart 2.x
      Обратите внимание! Вышел новый шаблон Frame Theme для OpenCart 3. Все владельцы лицензии на Coloring могут получить лицензию на Frame на льготных условиях. За подробностями обращайтесь в ЛС
       
      ----------------------------------------
       
      Coloring Theme - это современный адаптивный шаблон для опенкарт 2.x, включающий в себя комплекс дополнительных модулей и настроек, необходимых для полноценной работы современного интернет магазина. Шаблон построен на базе популярного фреймворка Bootstrap 3 и максимально использует его возможности в своей работе. Шаблон обладает продуманными юзабилити и интуитивно понятным интерфейсом, от которых, как известно, напрямую зависит конверсия интернет магазина.
       
      Демонстрация
       
      Главная страница: открыть в новой вкладке Страница товара: открыть в новой вкладке Страница категории: открыть в новой вкладке Администрирование: открыть в новой вкладке, доступ: demo / demo Тестовый доступ для для покупателя: demo@xds.by / demo  
      Услуги автора шаблона
       
      Установка движка, шаблона на ваш хостинг Установка шаблона на действующий магазин Индивидуальные доработки шаблона Создание магазина "под ключ" на базе шаблона   
      По всем вопросам обращайтесь в ЛС или на почту info@xds.by
       
      Описание шаблона
       
      Помимо базовых возможностей движка, шаблон несет в себе целый комплекс дополнительных настроек и модулей, таких как: форма заказа обратного звонка, быстрый заказ товаров, быстрый просмотр товаров, всплывающая корзина, дополнительные модули-карусели товаров с расширенными настройками, настраиваемые контакты в шапке сайта, 2 дополнительных меню в шапке сайта, настраиваемое меню категорий с функцией “амазон-меню”, иконки платежных систем в подвале сайта, интерактивная карта в подвале сайта, микро разметка в карточке товара и пр. Функционал шаблона постоянно расширяется и дополняется, поэтому нету смысла перечислять здесь все его возможности. Лучше один раз увидеть, чем 100 раз услышать прочитать)
       
      Конечно, можно попытаться собрать подобный функционал самостоятельно из сторонних модулей, но это обойдется вам в приличную сумму в разы превышающую стоимость шаблона. А ведь все эти модули нужно еще заставить работать вместе. И работать корректно и быстро. А потом все это надо оформить в едином стиле, со вкусом и знанием дела. В шаблоне все эти модули работают как “единый организм” и максимально задействуют базовый набор плагинов, предоставляемый движком opencart, что положительно сказывается на производительности и скорости работы шаблона.
       
      Системные требования
       
      Для корректной работы шаблона начиная с версии 1.3.0 на вашем хостинге должен быть установлен IonCube Loader версии не ниже 4.4 с PHP не ниже 5.3. У подавляющего большинства современных хостингов с этим проблем нет, но, на всякий случай, уточняйте эту информацию у вашего хостера перед покупкой. В остальном, системные требования шаблона идентичны требованиям opencart.
       
      Совместимость
       
      Шаблон тестировался и точно работает с оригинальной сборкой opencart а так же со сборкой от myopencart.com и ocstore. На других сборках шаблон не тестировался и за его работоспособность на них, я не отвечаю. Обратите внимание, что как правило, версии шаблона для более ранних версий движка имеют более ограниченный функционал, чем для новых. Обычно в названии архива с шаблоном обозначено для какой версии opencart он предназначен.
       
      Лицензия / условия использования
       
      Шаблон реализуется по принципу: “1 копия на 1 домен + 1 тестовый домен”. Шаблон лицензируется путем внесения вашего домена в лицензионную базу данных. После покупки, вам необходимо сообщить мне домены для активации через личные сообщения на этом форуме. Если вы не можете написать мне личное сообщение, то вероятнее всего вы не активировали вашу учетную запись на данном форуме. Возможность писать ЛС появится только после ее активации.
       
      Техническая поддержка
       
      Обязательным условием получения технической поддержки является соблюдение системных требований шаблона и Openсart!!! Техническая поддержка покупателей шаблона осуществляется только через личные сообщения на данном форуме и доступна только пользователям, числящимся в списке покупателей шаблона. Без исключений! При обращении за поддержкой указывайте версию движка, версию шаблона и прилагайте ссылку на проблемную страницу
       
      Условия покупки шаблона
       
      Предметом сделки является шаблон в том виде, в котором он существует на момент покупки. Все последующие обновления и техническая поддержка доступны покупателям бесплатно, но являются бонусом-дополнением к покупке, а не составной частью этой покупки. Шаблон, как и любые другие цифровые товары, не подлежит возврату и обмену. Покупая шаблон в любом из официальных источников вы соглашаетесь со всем вышеизложенным.
      .
      Добавил xds Добавлено 19.04.2015 Категория Платные шаблоны Системные требования Сайт разработчика http://xds.by Старая цена 2990 Метод активации По запросу в ЛС Ioncube Loader Требуется OpenCart 2.3
      2.2
      2.1 ocStore 2.3
      2.2
      2.1 OpenCart.Pro, ocShop Не проверялось Обращение к серверу разработчика Да  
    • By mister12
      1 290.00 руб
      Скачать/Купить дополнение


      Шаблон магазина автозапчастей ExlusiveTuning 2.X
      Шаблон работает на Opencart и ocStore 2.1.X / 2.3.X / 3.0.X!!! (версия для 1.5.X находится тут)
       
      Описание шаблона "Магазин автозапчастей ExlusiveTuning 2.X":
      Индивидуальный, стильный, адаптивный шаблон. Является доработанной версией шаблона, созданного под предыдущие версии OpenCart. 
       
      Как показала практика, шаблон магазина автозапчастей прекрасно подходит под следующие тематики:
      Автозапчасти, автотовары, автокосметика, автохимия, автомагнитолы и т.д. Продажа тактического снаряжения и амуниции (охотничье снаряжение, все для страйкбола) Продажа запчастей для электроинструментов (дрели, перфораторы, УШМ, шуруповерты и т.д.) Продажа отопительного оборудования (тепловентиляторы, тепловые пушки и т.п.) Продажа насосов и газовых пружин Продажа велосипедов и аксессуаров для них Продажа ножей для охоты Продажа оборудования для лодок (лодочные электромоторы, эхолоты, датчики)  
      Это далеко не исчерпывающий список тематик, для которых шаблон удачно подходит. 
       
      В отличии от предыдущей версии шаблона сделан ряд изменений. Самое главное из которых - это, конечно же, поддержка самой свежей версии Opencart Store, которую многие спрашивали. Внесены еще ряд изменений в дизайн, чтобы повысить его универсальность. Корзина теперь стала без автомобильной иконки, у слайдера были убраны иконки колес, частично отрисованы новые баннеры и т.п. В целом же основная концепция шаблона все так же осталась автомобильной. 
       
      ШАБЛОН ДОСТУПЕН В ДВУХ ЦВЕТОВЫХ ВАРИАНТАХ НА ВАШ ВЫБОР! 

       
      Демо магазина автозапчастей ExlusiveTuning 2.X (темный стиль):
      Главная страница: http://opencart.demo1.bget.ru/autov2/
      Страница категории: http://opencart.demo1.bget.ru/autov2/kuzov/
      Страница товара: http://opencart.demo1.bget.ru/autov2/podveska/torm_diski/rn1335
       
      Демо магазина автозапчастей ExlusiveTuning 2.X (светлый стиль):
      Главная страница: http://opencart.demo1.bget.ru/autov2_white/
      Страница категории: http://opencart.demo1.bget.ru/autov2_white/kuzov/
      Страница товара: http://opencart.demo1.bget.ru/autov2_white/kuzov/kapot/780986gef
       
      Демо-админка магазина автозапчастей:
      http://opencart.demo1.bget.ru/autov2/admin/
      Логин: demo
      Пароль: demo
       
      Шаблон тестировался на ocStore ocStore 2.1.0.2.1, 2.3.0.2.3,  а также на версиях Opencart 2.1.0.2, Opencart 2.3.0.2, Opencart 3.0.2.0!
       

       
      Совместимость/валидация шаблона магазина автозапчастей ExlusiveTuning 2.X:
      Шаблон прошел полную оптимизацию кода. Google pagespeed оценивает уровень оптимизации на 99/100!!!!! Это очень высокий результат! В мобильной версии 93/100.
      Ссылка на pagespeed - https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fopencart.demo1.bget.ru%2Fautov2%2F&tab=desktop
      Шаблон тестировался во всех современных браузерах, проходит проверку валидатора кода без единой ошибки.
      Ссылка на валидатор - https://validator.w3.org/nu/?doc=http%3A%2F%2Fopencart.demo1.bget.ru%2Fautov2%2F
      Корректно отображается на любых мобильных устройствах с любыми размерами экранов.
      Адаптивная верстка легко проходит проверку от Google Mobile Friendly Websites, благодаря чему исключены потери поискового трафика.
      Ссылка на mobile-friendly - https://search.google.com/test/mobile-friendly?id=tH-hu3PVSdy09TpAWs4HvQ
       
      ПРЕДСТАВЛЕННЫЙ ШАБЛОН БАЗОВЫЙ И ПРИ ЖЕЛАНИИ ДОРАБАТЫВАЕТСЯ ПОД КЛИЕНТА

       

       
      Совместимость с автомобильными модулями:
      Есть совместимость с модулем Additional Hover Images, который используется на таких площадках как Auto.ru, сервисе объявлений Avito.
       
      Лицензия магазина автозапчастей ExlusiveTuning 2.X:
      1. В стоимость шаблона также ВКЛЮЧЕНА ПОМОЩЬ по установке и настройке данного шаблона (помощь согласно инструкции).
      2. Приобретая шаблон вы получаете неограниченный доступ ко всем последующим обновлениям шаблона.
      3. Запрещается распространять файлы шаблона.
      4. Покупатель имеет право использовать приобретенный шаблон только для установки на собственный интернет-магазин, либо (если это разработчик) на интернет-магазин клиента.
      5. Шаблон реализуется по принципу "1 покупатель – 1 домен"
      6. Если покупатель будет уличен в нарушении правил описанных выше – он автоматически лишается всякой технической поддержки и подлежит обнародованию.
       
      Обратите внимание!
      По шаблону магазина автозапчастей ExlusiveTuning 2.X осуществляется дальнейшая доработка и расширение возможностей, которые появятся в ближайшее время!
      Добавил mister12 Добавлено 23.11.2017 Категория Платные шаблоны Системные требования Сайт разработчика Старая цена Метод активации Без активации Ioncube Loader Нет OpenCart 3.0
      2.3
      2.1 ocStore 3.0
      2.3
      2.1 OpenCart.Pro, ocShop Не проверялось Обращение к серверу разработчика Нет  
  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

On our site, cookies are used and personal data is processed to improve the user interface. To find out what and what personal data we are processing, please go to the link. If you click "I agree," it means that you understand and accept all the conditions specified in this Privacy Notice.