Перейти к содержанию
Timber

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

Рекомендуемые сообщения

Например есть контроллер 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

Изменено пользователем Timber

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я неделю мучался с написанием своего контроллера для модуля фотогалерей, это был для меня тот еще путь страданий (неделю свободного времени убил). Так же знаю, что пользователь @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 ;";

Изменено пользователем halfhope

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще забыл упомянуть, что должен быть модуль, размещенный на странице ошибки (схема 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();
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

  • +1 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Еще забыл упомянуть, что должен быть модуль, размещенный на странице ошибки (схема 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);
                     }
                }
            }

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

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

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

 

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

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

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

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

 

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

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

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

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

 

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

Поделиться сообщением


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

  • +1 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Бред = OpenCart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати для этого Даниэль и сделал  в 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

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

Постом выше

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати для этого в этого и сделал  в 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 - вопросов нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

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

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

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

 

 

 

Бред = OpenCart

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
....

 

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

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

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

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

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

Что сказать.

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

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

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

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

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

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

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

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Написал свой функционал "Линии товаров" контроллер 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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Изменено пользователем afwollis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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 и, в случае ошибки, вызывает из своего контроллера уже его? Соответственно можно избавиться от флагов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Похожий контент

    • От 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, которую многие спрашивали. Внесены еще ряд изменений в дизайн, чтобы повысить его универсальность. Корзина теперь стала без автомобильной иконки, у слайдера были убраны иконки колес, частично отрисованы новые баннеры и т.п. В целом же основная концепция шаблона все так же осталась автомобильной. 
       
      ШАБЛОН ДОСТУПЕН В ДВУХ ЦВЕТОВЫХ ВАРИАНТАХ НА ВАШ ВЫБОР! 

       
      Демо магазина автозапчастей ExusiveTuning 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
       
      Демо магазина автозапчастей ExusiveTuning 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 оценивает уровень оптимизации на 90/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=6hAkVQGT9-mAtjnPtROnqg
       
      ПРЕДСТАВЛЕННЫЙ ШАБЛОН БАЗОВЫЙ И ПРИ ЖЕЛАНИИ ДОРАБАТЫВАЕТСЯ ПОД КЛИЕНТА

       

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

       
      Демо магазина автозапчастей ExusiveTuning 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
       
      Демо магазина автозапчастей ExusiveTuning 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 оценивает уровень оптимизации на 90/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=6hAkVQGT9-mAtjnPtROnqg
       
      ПРЕДСТАВЛЕННЫЙ ШАБЛОН БАЗОВЫЙ И ПРИ ЖЕЛАНИИ ДОРАБАТЫВАЕТСЯ ПОД КЛИЕНТА

       

       
      Лицензия магазина автозапчастей ExusiveTuning 2.X:
      1. В стоимость шаблона также ВКЛЮЧЕНА ПОМОЩЬ по установке и настройке данного шаблона (помощь согласно инструкции).
      2. Приобретая шаблон вы получаете неограниченный доступ ко всем последующим обновлениям шаблона.
      3. Запрещается распространять файлы шаблона.
      4. Покупатель имеет право использовать приобретенный шаблон только для установки на собственный интернет-магазин, либо (если это разработчик) на интернет-магазин клиента.
      5. Шаблон реализуется по принципу "1 покупатель – 1 домен"
      6. Если покупатель будет уличен в нарушении правил описанных выше – он автоматически лишается всякой технической поддержки и подлежит обнародованию.
       
      Обратите внимание!
      По шаблону магазина автозапчастей ExlusiveTuning 2.X осуществляется дальнейшая доработка и расширение возможностей, которые появятся в ближайшее время!
    • От mister12
      1 290.00 руб
      Скачать/Купить дополнение


      Многоцветный шаблон зоомагазина PetShop для Opencart 2.X
      Шаблон, адаптивный, легкий, быстрый и уникальный в своём роде, созданный под тематику зоотоваров для зоомагазинов и для всего, что связано с миром животных.
      Шаблон не требует замены файлов, максимально быстро установится на любой, даже только что установленный Opencart.
       
      Шаблон работает на Opencart и ocStore 2.3.X!!! (версия для 1.5.X находится тут)
      Совместим с ЛЮБЫМИ дополнительными модулями.
       
      Как показала практика, шаблон использовать можно не только для зоомагазина, но и совершенно легко (заменив товары, баннеры и изображения) как:
      - шаблон для магазина игрушек (яркий, броский, оригинальный, очень нестандартный - идеальный вариант для детской тематики)
      - шаблон для магазина кондитерских изделий
      - шаблон для кафе/пиццерий
       
      Шесть цветовых решений на ваш выбор!


      Вторая версия шаблона PetShop для Opencart 2.X, значительно доработанная и расширенная, по сравнению с предыдущей.  Что изменилось:
      У шаблона появилось 5 НОВЫХ цветовых оттенков, помимо классического оранжевого (фиолетовый, синий, голубой, зеленый, розовый), благодаря чему возможность применения шаблона возросла многократно! Основная область шаблона увеличена с 1000px до 1140px. Новые тематические изображения в элементах сайта (слайдер, баннеры). Переделана шапка шаблона, теперь валюта/языки/личный кабинет имеют свои всплывающие окна для выбора. Изменён внешний вид корзины, изменено положение элементов. В миниатюрах товаров добавлены кнопки "В закладки" и "В сравнение". Хлебные крошки поменяли свой вид под стилистику opencart 2. Значительно сокращено количество картинок, используемых при верстке. Большая часть переведена на CSS-градиенты, а также FA-иконки. Что еще больше упрощает адаптацию шаблона под конкретные нужды. Во многих элементах увеличен шрифт для лучшей читаемости.  В карточке товара изменены кнопки (в корзину/в закладки/в сравнения/поделиться в соц.сетях) При внешней схожести шаблона с предыдущим, от прежнего кода шаблона ничего не осталось, все сделано заново.  
      Демо шаблон зоомагазина:
      Главная страница: http://opencart.demo1.bget.ru/zoo2/
      Страница категории: http://opencart.demo1.bget.ru/zoo2/cats/
      Страница товара: http://opencart.demo1.bget.ru/zoo2/cats/filler/kuzma
      Демо-админка:
      http://opencart.demo1.bget.ru/zoo2/admin/
      Логин: demo
      Пароль: demo
       

       
      Совместимость/валидация шаблона зоомагазина PetShop:
      Шаблон прошел полную оптимизацию кода. Google pagespeed оценивает уровень оптимизации на 90/100. 
      Ссылка на pagespeed - https://developers.google.com/speed/pagespeed/insights/?hl=ru&url=http%3A%2F%2Fopencart.demo1.bget.ru%2Fzoo2%2F&tab=desktop
      Шаблон тестировался во всех современных браузерах, проходит проверку валидатора кода без единой ошибки.
      Ссылка на валидатор - https://validator.w3.org/nu/?doc=http%3A%2F%2Fopencart.demo1.bget.ru%2Fzoo2%2F
      Корректно отображается на любых мобильных устройствах с любыми размерами экранов. Адаптивная верстка легко проходит проверку от Google Mobile Friendly Websites, благодаря чему исключены потери поискового трафика.
      Ссылка на mobile-friendly - https://search.google.com/test/mobile-friendly?id=2PPmVz-NCAbVfQo6TWFNPA

      Шаблон тестировался на ocStore 2.3.0.2.3


       


      Лицензия шаблона зоомагазина PetShop:
      1. В стоимость шаблона также ВКЛЮЧЕНА ПОМОЩЬ по установке и настройке данного шаблона (помощь согласно инструкции).
      2. Приобретая шаблон вы получаете неограниченный доступ ко всем последующим обновлениям шаблона.
      3. Запрещается распространять файлы шаблона.
      4. Покупатель имеет право использовать приобретенный шаблон только для установки на собственный интернет-магазин, либо (если это разработчик) на интернет-магазин клиента.
      5. Шаблон реализуется по принципу "1 покупатель – 1 домен"
      6. Если покупатель будет уличен в нарушении правил описанных выше – он автоматически лишается всякой технической поддержки и подлежит обнародованию.
       
      Обратите внимание!
      По шаблону зоомагазина PetShop планируется дальнейшая доработка и расширение возможностей!
      Обо всех своих предложениях и вопросах обращайтесь в тему поддержки шаблона.
       
      Добавил mister12 Добавлено 29.11.2017 Категория Платные шаблоны Системные требования Сайт разработчика Старая цена Метод активации Без активации Ioncube Loader Нет OpenCart 2.3 ocStore 2.3 OpenCart.Pro, ocShop Не проверялось  
    • От mister12
      Шаблон, адаптивный, легкий, быстрый и уникальный в своём роде, созданный под тематику зоотоваров для зоомагазинов и для всего, что связано с миром животных.
      Шаблон не требует замены файлов, максимально быстро установится на любой, даже только что установленный Opencart.
       
      Шаблон работает на Opencart и ocStore 2.3.X!!! (версия для 1.5.X находится тут)
      Совместим с ЛЮБЫМИ дополнительными модулями.
       
      Как показала практика, шаблон использовать можно не только для зоомагазина, но и совершенно легко (заменив товары, баннеры и изображения) как:
      - шаблон для магазина игрушек (яркий, броский, оригинальный, очень нестандартный - идеальный вариант для детской тематики)
      - шаблон для магазина кондитерских изделий
      - шаблон для кафе/пиццерий
       
      Шесть цветовых решений на ваш выбор!


      Вторая версия шаблона PetShop для Opencart 2.X, значительно доработанная и расширенная, по сравнению с предыдущей.  Что изменилось:
      У шаблона появилось 5 НОВЫХ цветовых оттенков, помимо классического оранжевого (фиолетовый, синий, голубой, зеленый, розовый), благодаря чему возможность применения шаблона возросла многократно! Основная область шаблона увеличена с 1000px до 1140px. Новые тематические изображения в элементах сайта (слайдер, баннеры). Переделана шапка шаблона, теперь валюта/языки/личный кабинет имеют свои всплывающие окна для выбора. Изменён внешний вид корзины, изменено положение элементов. В миниатюрах товаров добавлены кнопки "В закладки" и "В сравнение". Хлебные крошки поменяли свой вид под стилистику opencart 2. Значительно сокращено количество картинок, используемых при верстке. Большая часть переведена на CSS-градиенты, а также FA-иконки. Что еще больше упрощает адаптацию шаблона под конкретные нужды. Во многих элементах увеличен шрифт для лучшей читаемости.  В карточке товара изменены кнопки (в корзину/в закладки/в сравнения/поделиться в соц.сетях) При внешней схожести шаблона с предыдущим, от прежнего кода шаблона ничего не осталось, все сделано заново.  
      Демо шаблон зоомагазина:
      Главная страница: http://opencart.demo1.bget.ru/zoo2/
      Страница категории: http://opencart.demo1.bget.ru/zoo2/cats/
      Страница товара: http://opencart.demo1.bget.ru/zoo2/cats/filler/kuzma
      Демо-админка:
      http://opencart.demo1.bget.ru/zoo2/admin/
      Логин: demo
      Пароль: demo
       

       
      Совместимость/валидация шаблона зоомагазина PetShop:
      Шаблон прошел полную оптимизацию кода. Google pagespeed оценивает уровень оптимизации на 90/100. 
      Ссылка на pagespeed - https://developers.google.com/speed/pagespeed/insights/?hl=ru&url=http%3A%2F%2Fopencart.demo1.bget.ru%2Fzoo2%2F&tab=desktop
      Шаблон тестировался во всех современных браузерах, проходит проверку валидатора кода без единой ошибки.
      Ссылка на валидатор - https://validator.w3.org/nu/?doc=http%3A%2F%2Fopencart.demo1.bget.ru%2Fzoo2%2F
      Корректно отображается на любых мобильных устройствах с любыми размерами экранов. Адаптивная верстка легко проходит проверку от Google Mobile Friendly Websites, благодаря чему исключены потери поискового трафика.
      Ссылка на mobile-friendly - https://search.google.com/test/mobile-friendly?id=2PPmVz-NCAbVfQo6TWFNPA

      Шаблон тестировался на ocStore 2.3.0.2.3


       


      Лицензия шаблона зоомагазина PetShop:
      1. В стоимость шаблона также ВКЛЮЧЕНА ПОМОЩЬ по установке и настройке данного шаблона (помощь согласно инструкции).
      2. Приобретая шаблон вы получаете неограниченный доступ ко всем последующим обновлениям шаблона.
      3. Запрещается распространять файлы шаблона.
      4. Покупатель имеет право использовать приобретенный шаблон только для установки на собственный интернет-магазин, либо (если это разработчик) на интернет-магазин клиента.
      5. Шаблон реализуется по принципу "1 покупатель – 1 домен"
      6. Если покупатель будет уличен в нарушении правил описанных выше – он автоматически лишается всякой технической поддержки и подлежит обнародованию.
       
      Обратите внимание!
      По шаблону зоомагазина PetShop планируется дальнейшая доработка и расширение возможностей!
      Обо всех своих предложениях и вопросах обращайтесь в тему поддержки шаблона.
       
    • От 29aleksey
      1 200.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 Сайт разработчика Старая цена 1200 Метод активации По запросу в ЛС 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  
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×

Важная информация

На нашем сайте используются файлы cookie и происходит обработка некоторых персональных данных пользователей, чтобы улучшить пользовательский интерфейс. Чтобы узнать для чего и какие персональные данные мы обрабатываем перейдите по ссылке. Если Вы нажмете «Я даю согласие», это означает, что Вы понимаете и принимаете все условия, указанные в этом Уведомлении о Конфиденциальности.