Как создать отдельный шаблон страницы товара, категории, статьи?

Тема в разделе "Инструкции и FAQ", создана пользователем solunski.d, 22 ноя 2016.

  1. solunski.d

    solunski.d Эксперт

    Сообщения:
    1.569
    Симпатии:
    432
    Всем приуэт! :) В данной статье мы рассмотрим создание отдельного шаблона для определенной страницы. Затрагивать админку мы не будем, так как это уже удобство, а за удобство нужно платить.

    * Использовать я буду OpenCart версии 2.3, не важно какая это сборка, будет работать на всех.
    * Для работы нам понадобиться редактор, для новичков notepad++(бесплатная) или Sublime(платная), для опытных - они сами знают что им юзать.
    * Для примера я буду изменять страницу товара, возьму демо данные, а товаром будет Iphone.
    * Сперва читаем, потом делаем, а не наоборот.

    1. В начале мы должны определиться с шаблонами и начну я с шапки сайта (header)
    1.1 Идем в папку catalog/view/название темы/template/common/ и создаем дубликат файла header.tpl, я назову его header_iphone.tpl
    1.2 Изменяем его как Вам нужно, для новичков советую делать изменения после тега <body>, а в <head> лишь добавлять стили или скрипты ну и прочие мета данные.

    2. Теперь займемся основной частью страницы продукта, серединкой (main)
    2.1 Идем в папку catalog/view/название темы/template/product/ и создаем дубликат файла product.tpl, я назову его product_iphone.tpl
    2.2 Изменяем его как Вам нужно, для новичков советую не трогать скрипты, так как накосячить это ваши способности.

    3. Последние изменения в шаблона, это подвал сайта, футер (footer)
    3.1 Идем в папку catalog/view/название темы/template/common/ и создаем дубликат файла footer.tpl, я назову его footer_iphone.tpl

    * Какие либо пункты вы можете пропустить, в зависимости от задачи, кому то шапку нужно изменить, кому то main подправить, а кому то переделать и вовсе всю страницу и сварганить Landing Page.

    После продленной работы, нам нужно подправить контроллер, OpenCart разработан по MVC структуре, кому надо тот найдет ответы в Google или Yandex, контроллер - это логика.

    4. Как всегда начинаем с шапки
    4.1 Идем в папку catalog/controller/common/ и открывает для редактирования файл header.php
    4.2 Находим функцию которая занимается выводом шаблонов, такая функция имеет вид:
    PHP:
    return $this->load->view('common/header'$data);
    Первый аргумент это путь до файла, а второй это массив, который содержит в себе данные.
    4.3 Изменяем данную функцию:
    PHP:
    // Шаблон шапки по умолчанию
    $template 'common/header';

    if (isset(
    $this->request->get['product_id'])) {
      
    // Проверяем это страница какого либо продукта
       
    if ($this->request->get['product_id'] == 40) {
        
    // Проверяем это страница товара с идентификатором 40, если да, передаем переменной строку с новым путем до нового шаблона
          
    $template 'common/header_apple';
       }
    }
    // Функция которая возвращает наш макет
    return $this->load->view($template$data);
    * У каждой страницы есть свой идентификатор, с помощью его мы можем делать вот такие вот проверки и изменять как нам угодно шаблон той или иной части сайта.
    * Чтобы узнать какой id(идентификатор) принадлежит данной страницы, достаточно отключить в настройках сайта формирователь ЧПУ и в адресной строке вы увидите нечто подобное:
    Код:
    index.php?route=product/product&product_id=40
    По данной ссылке, мы можем узнать, что за работу по выводу страницы отвечает контроллер product, а идентификатором страницы является число 40. Второй способ более удобный, но нужно работать глазками усерднее, открываем нужную нам страницу и нажав комбинацию клавиш CTRL + U вы откроете страницу в которой содержится разметка данной страницы. Нас интересует тег <body>, так как его класс нам подсказывает все тоже самое что и при отключении ЧПУ на сайте.

    5. Main
    5.1 Идем в папку catalog/controller/product/ и открывает для редактирования файл product.php
    5.2 Находим функцию которая занимается выводом шаблонов, такая функция имеет вид:
    PHP:
    $this->response->setOutput($this->load->view('product/product'$data));
    5.3 Изменяем её, как нам удобно, тут я представил 2 варианта
    5.3.1
    PHP:
    if ($product_id == 40 ) {
       
    $this->response->setOutput($this->load->view('product/product_apple'$data));
    } else {
       
    $this->response->setOutput($this->load->view('product/product'$data));
    }
    PHP:
    $template 'product.tpl';
    /* $prouduct_id уже содержит в себе id текущей страницы,
     для категории это будет $category_id,
    для статьи $information_id,
    для производителя $manufacturer_id и так далее.
    */
    if ($product_id == 27) {
       
    $template 'product_1.tpl';
    }
    if (
    $product_id == 28) {
       
    $template 'product_2.tpl';
    }

    $this->response->setOutput($this->load->view($template$data));
    6. Footer, здесь исполняться тот же принцип что и в header
    6.1 Идем в папку catalog/controller/common/ и открывает для редактирования файл footer.php
    6.2 Находим нашу функцию и изменяем её:
    PHP:
    $template 'common/footer';

    if (isset(
    $this->request->get['product_id'])) {
        if (
    $this->request->get['product_id'] == 40) {
            
    $template 'common/footer_apple';
        }
    }

    return 
    $this->load->view($template$data);
    Вот собственно и все, по поводу как изменить страницу категории или производителя или статьи, то принцип тот же. Если у вас встанут вопросы, а как же все таки изменить данные страницы, то это значит что вы просто тупа "copy paste", мне не о чем с вами разговаривать. О желаниях, которые возможно у вас появятся, типа хочу шапку красного цвета, тут не писать!
     
    Последнее редактирование: 27 ноя 2016
    kukumberg, Zlata Jesen, Ivan777 и 5 другим нравится это.
  2. Nikola

    Nikola Новичок

    Сообщения:
    1
    Симпатии:
    0
    Отлично. Спасибо за более чем исчерпывающую статью.
    От себя добавлю - заработало только после того как обновил КЭШ модификаторов.
     
  3. jaffagold

    jaffagold Новичок

    Сообщения:
    4
    Симпатии:
    2
    Принцип понятен.
    Но возник вопрос.
    Если использовать для нестандартной Категории такой вариант:
    Создаем дубликат catalog\view\theme\my-theme\template\product\category.tpl
    называем category-2.tpl (правим его как хотим)
    Дизайн-Макеты-Новый макет ( можно копировать стандартный) в нем указываем в верхней строке Путь:
    product/category-2

    То в базе данных
    в таблице
    oc_category_to_layout

    category_id
    layout_id

    в столбце layout_id появится отличное от нуля значение ( допустим 19). На дефолтных макетах стоит значение ноль.

    в таблице
    oc_layout_route
    появятся такие данные
    layout_id 19
    route =product/category-2

    То есть, на самом деле все данные уже есть для вывода кастомизированного макета категории.
    Но он выводится без учета этих изменений (как вы указали в п.5).
    Мне кажется, что есть возможность сделать этот вывод с помощью запросов к базе данных? ( не специалист, но мне кажется, что 2 тут явно запроса: взять id_layout и к нему route

    Извините, если что напутал по незнанию.
     
    Fortoons нравится это.
  4. solunski.d

    solunski.d Эксперт

    Сообщения:
    1.569
    Симпатии:
    432
    Вы читали документацию? Дизайн -> макеты - там указывается путь до контроллера, а не tpl файл.
     
  5. jaffagold

    jaffagold Новичок

    Сообщения:
    4
    Симпатии:
    2
    Понял ошибку.
    Документацию читал, но не все сразу укладывается в голове.
    Хотя, не исключено, что работать будет, т.к. не найдя контроллера обрабатывается контролером по умолчанию, а данные можно использовать.
    Кстати, если сильно захотеть, то можно и контроллер продублировать.
    Просто в этом случае нет никакой привязки к ID категории.
    И самое главное, нет риска повредить рабочий контроллер для всего.
    То есть, оригинальные файлы не затрагиваются вообще, правятся только дубликаты.
    Конечно, если изменений много, то лучше списком по условию. А если одна какая-то причудливая категория, то работает и так.
     
    Последнее редактирование: 31 дек 2016
  6. kukumberg

    kukumberg Пользователь

    Сообщения:
    130
    Симпатии:
    3
    Код:
    if ($category_id == 61 ) {
       $this->response->setOutput($this->load->view('product/category1', $data));
    } else {
       $this->response->setOutput($this->load->view('product/category', $data));
    }
    
    Такой вариант у меня получился на версии 2.3. А как быть если у меня 5 категорий связаны одним макетом product/category1 ?
     
  7. solunski.d

    solunski.d Эксперт

    Сообщения:
    1.569
    Симпатии:
    432
    PHP:
    if ($category_id == 61 || $category_id == 62 )
     
    kukumberg нравится это.
  8. kukumberg

    kukumberg Пользователь

    Сообщения:
    130
    Симпатии:
    3
    Спасибо, уже подсказали такое решение:
    Код:
    if (in_array($category_id, array(61, 62, 63, 12, 5)))
     
  9. megaCart

    megaCart Пользователь

    Сообщения:
    78
    Симпатии:
    4
    Трогать системные контроллеры вообще логично? возможно ли изменить или добавить свою функцию в контроллере не трогая системные?
     
  10. karpov

    karpov Продвинутый пользователь

    Сообщения:
    1.519
    Симпатии:
    241
    Иногда очень даже. Не нравится прямое вмешательство, то применяйте модификаторы.
     
  11. Valerinskaya

    Valerinskaya Новичок

    Сообщения:
    2
    Симпатии:
    0
    Приветствую! Спасибо за решение, но подскажите пожалуйста что делать, если есть несколько страниц категорий, которым нужно поменять индивидуальные макеты страниц?
    Допустим, есть 2 страницы категорий, для которых созданы разные макеты.
    Сначала попробовала так:
    if ($category_id == 59) {
    $this->response->setOutput($this->load->view('product/vwpage', $data));
    }
    if ($category_id == 60) {
    $this->response->setOutput($this->load->view('product/skodapage', $data));
    }
    else {
    $this->response->setOutput($this->load->view('product/category', $data));
    }
    Не помогло.

    Затем попробовала так:
    if ($category_id == 59) {
    $this->response->setOutput($this->load->view('product/vwpage', $data));
    }
    else {
    $this->response->setOutput($this->load->view('product/category', $data));
    }
    if ($category_id == 60) {
    $this->response->setOutput($this->load->view('product/skodapage', $data));
    }
    else {
    $this->response->setOutput($this->load->view('product/category', $data));
    }
    Тоже не помогло.
    Вариант с $template вообще не работает.
    Заметала что в первых двух попытках в результате шаблон все-таки назначается категории, но только той, которая стоит ниже в функции, то есть в моем случае 60. При проверке работает ли вообще способ - работает. При назначении шаблона только к одной категории все корректно отображается.

    Может я где-то скобочки неверно ставлю? Или какой есть способ решить эту задачу? Заранее спасибо за ответ
     
  12. solunski.d

    solunski.d Эксперт

    Сообщения:
    1.569
    Симпатии:
    432
    1. Версия OpenCart?
    2. Если у вас стоят доп. расширения, то возможно все дело в модификатор, вот и не срабатывает. Так же не забывайте чистить кэш CTRL + F5
    3. Также, действительно ли именно те ID вы указываете?

    PHP:
    // в array() помещаем список категорий
    if (in_array($category_id, array(59,60))) {
        
    $this->response->setOutput($this->load->view('product/custom'$data));
    } else {
        
    $this->response->setOutput($this->load->view('product/category'$data));
    }
     
  13. Valerinskaya

    Valerinskaya Новичок

    Сообщения:
    2
    Симпатии:
    0

    Opencart PRO Версия 2.3.0.2.2
    Кэш каждый раз перед проверкой обновляю и модификаторов в том числе. Проверяла на локалке и на сервере. На локалке все доступные расширения отключила - не сработало. ID точно верный. Перепроверяла несколько раз , и все равно, при проверке всегда срабатывает последний ID функции. Для эксперимента подставляла разные ID в конец - и каждая из них срабатывала. Прикрепляю фрагмент кода, который выставляю и то, что после него находится. Может действительно что-то не так в синтаксисе?

    Начало функции, в которой производятся изменения
    if ($limit && ceil($product_total / $limit) > $page) {
    $this->document->addLink($this->url->link('product/category', 'path=' . $category_info['category_id'] . '&page='. ($page + 1), true), 'next');
    }

    $data['sort'] = $sort;
    $data['order'] = $order;
    $data['limit'] = $limit;

    $data['continue'] = $this->url->link('common/home');

    $data['column_left'] = $this->load->controller('common/column_left');
    $data['column_right'] = $this->load->controller('common/column_right');
    $data['content_top'] = $this->load->controller('common/content_top');
    $data['content_bottom'] = $this->load->controller('common/content_bottom');
    $data['footer'] = $this->load->controller('common/footer');
    $data['header'] = $this->load->controller('common/header');
    сами изменения
    if ($category_id == 59) {
    $this->response->setOutput($this->load->view('product/vwpage', $data));
    }
    if ($category_id == 60) {
    $this->response->setOutput($this->load->view('product/skodapage', $data));
    }
    if ($category_id == 61) {
    $this->response->setOutput($this->load->view('product/audi', $data));
    }
    if ($category_id == 63) {
    $this->response->setOutput($this->load->view('product/seat', $data));
    }
    else {
    $this->response->setOutput($this->load->view('product/category', $data));
    }
    продолжение функции
    } else {
    $url = '';

    if (isset($this->request->get['path'])) {
    $url .= '&path=' . $this->request->get['path'];
    }

    if (isset($this->request->get['filter'])) {
    $url .= '&filter=' . $this->request->get['filter'];
    }

    if (isset($this->request->get['sort'])) {
    $url .= '&sort=' . $this->request->get['sort'];
    }

    if (isset($this->request->get['order'])) {
    $url .= '&order=' . $this->request->get['order'];
    }

    if (isset($this->request->get['page'])) {
    $url .= '&page=' . $this->request->get['page'];
    }

    if (isset($this->request->get['limit'])) {
    $url .= '&limit=' . $this->request->get['limit'];
    }

    $data['breadcrumbs'][] = array(
    'text' => $this->language->get('text_error'),
    'href' => $this->url->link('product/category', $url)
    );
     
  14. solunski.d

    solunski.d Эксперт

    Сообщения:
    1.569
    Симпатии:
    432
    У вас не оригинальная версия движка, а измененная, поэтому без анализа работы, нечем не помочь. Возможно там стоит переопределение методов, поэтому и не срабатывает...
     
  15. mr_denis

    mr_denis Новичок

    Сообщения:
    5
    Симпатии:
    0
    Подскажите пожалуйста а этим способом можно запилить отдельный tpl для страницы тегов опенкарт 2.3, а то она как поиск, а хочется убрать лишнее что бы выглядело прилично как самостоятельная страничка?
     
  16. Ravilr

    Ravilr Специалист

    Сообщения:
    3.879
    Симпатии:
    1.065
    Ваш контроллер \catalog\controller\product\search.php

    код где можно подсмотреть
    PHP:
    if (isset($this->request->get['tag'])) {
    далее по принципу указанному выше.
     
  17. slavok

    slavok Новичок

    Сообщения:
    1
    Симпатии:
    0
    Пробуйте вот так,


    if ($category_id == 59 ) {
    $this->response->setOutput($this->load->view('product/vwpage', $data));
    } else
    if ($category_id == 60 ) {
    $this->response->setOutput($this->load->view('product/skodapage', $data));
    }
    else {
    $this->response->setOutput($this->load->view('product/category', $data));
    }
     
  18. Burboss

    Burboss Новичок

    Сообщения:
    2
    Симпатии:
    0
    Подскажите, как на отдельно взятую страницу категории вывести определенный модуль?
     
  19. Blast

    Blast Продвинутый пользователь

    Сообщения:
    212
    Симпатии:
    74
    в Дизайн / Макеты создать макет, указать там вывод модуля. При редактировании категории присвоить этот макет нужной категории на вкладке Дизайн
     
    lexxkrt нравится это.
  20. Burboss

    Burboss Новичок

    Сообщения:
    2
    Симпатии:
    0
    Спасибо, добрый человек! Я какой-то сложный путь искал через ... А всё просто)