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

MVC или полная ересь? Давайте разберемся.

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

Итак. Я потратил почти все воскресенье на изучение структуры opencart 3.0. 

Моя задача была понять, с какого контроллера передаются переменные в twig шаблоны.  Казалось бы очевидно, что для шаблона:

/catalog/view/theme/storeflex/template/product/category.twig

Спойлер

{{ header }}
<div id="product-category" class="container">
	<ul class="breadcrumb">
		{% for breadcrumb in breadcrumbs %}
			<li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
		{% endfor %}
	</ul>
	<div>
	{% if thumb or description %}
		<div class="row">
			{% if thumb %}
				<div class="col-sm-4">
					<span id="image-category" class="image-category"><img src="{{ thumb }}" alt="{{ heading_title }}" title="{{ heading_title }}" class="img-thumbnail" /></span>
				</div>
			{% endif %}
			{% if description %}
				<div id="description-category" class="description description-category {{ thumb ? 'col-sm-8' : 'col-sm-12' }}">
					<div class="description-category__cont">
						<h2>{{ heading_title }}</h2>
						{{ description }} 
					</div>
					<div class="description-category__links" style="margin-top: 40px;">
						<a href="#" class="link show-desc" data-text-open="{{ text_data_open }}" data-text-close="{{ text_data_close }}">{{ text_data_open }}</a>
					</div>
				</div>
			{% endif %}
		</div>
	{% endif %}
	{% if (categories) %}
		<h3>{{ text_refine }}</h3>

		<div class="row">
			<ul class="box-subcat">
				{% for category in categories %}
					<li class="col-sm-3">
						<div class="thumb">
							{% if (category['thumb']) %}
								<div class="image">
									<a href="{{ category['href'] }}">
										<img width="{{ thumb_width }}" height="{{ thumb_height }}" src="{{ category['thumb'] }}" alt="{{ category['name'] }}" />
									</a>
								</div>
							{% endif %}
							<div class="name subcatname">
								<a href="{{ category['href'] }}">{{ category['name'] }}</a>
							</div>
						</div>
					</li>
				{% endfor %}
			</ul>
		</div>
	{% endif %}
	</div>
	<div class="row">
		{{ column_left }}
		{% if column_left and column_right %}
			{%set class = 'col-sm-6' %}
		{% elseif column_left or column_right %}
			{%set class = 'col-sm-9' %}
		{% else %}
			{%set class = 'col-sm-12' %}
		{% endif %}
		<div id="content" class="{{ class }}">
			{{ content_top }}
			{% if products %}
				<div class="product-filter clearfix">
					<div class="product-filter_elem">
						<div class="button-view">						
							<button type="button" id="grid-view" data-toggle="tooltip" title="{{ button_grid }}"><i class="material-design-two375"></i></button>
							<button type="button" id="list-view" data-toggle="tooltip" title="{{ button_list }}"><i class="material-design-view12"></i></button>
						</div>
					</div>
					<div class="product-filter_elem sort">
						<label class="control-label"  for="input-sort">
							{{ text_sort }}
						</label>
						<select id="input-sort" onchange="location = this.value;">
							{% for sorts in sorts %}
								{% if sorts.value == '%s-%s'|format(sort, order) %}
									<option value="{{ sorts['href'] }}" selected="selected">
										{{ sorts['text'] }}
									</option>
								{% else %}
									<option value="{{ sorts['href'] }}">
										{{ sorts['text'] }}
									</option>
								{% endif %}
							{% endfor %}
						</select>
					</div>
					<div class="product-filter_elem show pull-right">
						<label class="control-label"  for="input-limit">
							{{ text_limit }}
						</label>
						<select id="input-limit" onchange="location = this.value;">
							{% for limits in limits %}
								{% if (limits['value'] == limit) %}
									<option value="{{ limits['href'] }}" selected="selected">
										{{ limits['text'] }}
									</option>
								{% else %}
									<option value="{{ limits['href'] }}">
										{{ limits['text'] }}
									</option>
								{% endif %}
							{% endfor %}
						</select>
					</div>
					
				</div>
				<div class="row">
					{%set option_index = 5000 %}
					{% for product in products %}
						<div class="product-layout product-list">
							<div class="product-thumb transition {% if product.options and product.options|length <= 3 %} {{ 'options' }} {% endif %}">
								{% if product.options and product.options|length <= 3 %}
									<div class="product-option-wrap">
										<div class="product-options form-horizontal">
											<div class="options">
												<a class="ajax-overlay_close" href='#'></a>
												<input type="text" name="product_id" value="{{ product.product_id }}" class="form-control hidden"/>
												<h3>{{ text_option }}</h3>
												{% for option in product.options %}
													{% if option.type == 'select' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">
																{{ option.name }}
															</label>
															<div class="col-sm-12">
																<select name="option[{{ option.product_option_id }}]" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control">
																	<option value="">{{ text_select }}</option>
																	{% for option_value in option.product_option_value %}
																		<option value="{{ option_value.product_option_value_id }}">{{ option_value.name }}
																			{% if option_value.price %}
																				({{ option_value.price_prefix }}{{ option_value.price }})
																			{% endif %}
																		</option>
																	{% endfor %}
																</select>
															</div>
														</div>
													{% endif %}													
													
													{% if option.type == 'radio' %} 
													{% set option_image = constant('false') %} {% for option_value in option.product_option_value %} 
													{% if (option_value.image) %} {% set option_image = constant('true') %}{% endif %} 
													{% endfor %} 
													<div class="form-group {{ option_image ? 'option-color' : '' }} {{option['required'] ? ' required' : '' }}">
														<label class="control-label col-sm-12">{{ option.name }}</label>
														<div class="col-sm-12">
															<div id="input-option{{ option.product_option_id ~ option_index }}">
																{% for option_value in option.product_option_value %} 
																{% if (option_image) %} 
																<div class="radio">
																	<label>
																		<input type="radio" name="option[{{ option.product_option_id }}]" value="{{ option_value.product_option_value_id }}" />
																		<img width="21" height="21" data-toggle="tooltip" title="{{ option_value.name }}{% if (option_value.price) %} ({{ option_value.price_prefix }}{{ option_value.price }}) {% endif %}" src="{{ option_value.image }}" alt="{{ option_value.name ~ option_value.price ? ' ' ~ option_value.price_prefix ~ option_value.price : '' }}" class="img-thumbnail" />
																	</label>
																</div>
																{% else %} 
																<div class="radio">
																	<label for="option[{{ option.product_option_id ~ option_value.product_option_value_id ~ option_index }}]">
																		<input type="radio" name="option[{{ option.product_option_id }}]" id="option[{{ option.product_option_id ~ option_value.product_option_value_id ~ option_index }}]" value="{{ option_value.product_option_value_id }}"/>
																		{{ option_value.name }} 
																		{% if (option_value.price) %} 
																		({{ option_value.price_prefix }}{{ option_value.price }})
																		{% endif %} 
																	</label>
																</div>
																{% endif %} 
																{% endfor %} 
															</div>
														</div>
													</div>
													{% endif %}
													
													{% if option.type == 'checkbox' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12" >{{ option.name }}</label>
															<div class="col-sm-12">
																<div id="input-option{{ option.product_option_id ~ module ~ option_index }}">
																	{% for option_value in option.product_option_value %}
																		<div class="checkbox">
																			<label>
																				<input type="checkbox" name="option[{{ option.product_option_id }}][]" value="{{ option_value.product_option_value_id }}" />
																				{% if option_value.image %}
																					<img src="{{ option_value.image }}" alt="{{ option_value.name }} {% if option_value.price %} {{ option_value.price_prefix }} {{ option_value.price }} {% endif %}" class="img-thumbnail" />
																				{% endif %}
																				{{ option_value.name }}
																				{% if option_value.price %}
																					({{ option_value.price_prefix }}{{ option_value.price }})
																				{% endif %}
																			</label>
																		</div>
																	{% endfor %}
																</div>
															</div>
														</div>
													{% endif %}
													{% if option.type == 'text' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">
																{{ option.name }}
															</label>
															<div class="col-sm-12">
																<input type="text" name="option[{{ option.product_option_id }}]" value="{{ option.value }}" placeholder="{{ option.name }}" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control" />
															</div>
														</div>
													{% endif %}
													{% if option.type == 'textarea' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">{{ option.name }}</label>
															<div class="col-sm-12">
																<textarea name="option[{{ option.product_option_id }}]" rows="5" placeholder="{{ option.name }}" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control">{{ option.value }}</textarea>
															</div>
														</div>
													{% endif %}
													{% if option.type == 'file' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12" >{{ option.name }}</label>
															<div class="col-sm-12">
																<button type="button" id="button-upload{{ option.product_option_id }}" data-loading-text="{{ text_loading }}" class="btn btn-default btn-block"><i class="fa fa-upload"></i> {{ button_upload }}</button>
																<input type="hidden" name="option[{{ option.product_option_id }}]" value="" id="input-option{{ option.product_option_id ~ module ~ option_index }}" />
															</div>
														</div>
													{% endif %}
													{% if option.type == 'date' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">{{ option.name }}</label>
															<div class="col-sm-12">
																<div class="input-group date">
																	<input type="text" name="option[{{ option.product_option_id }}]" value="{{ option.value }}" data-date-format="YYYY-MM-DD" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control" />
																	<span class="input-group-btn">
																		<button class="btn btn-default" type="button"><i class="fa fa-calendar"></i></button>
																	</span>
																</div>
															</div>
														</div>
													{% endif %}
													{% if option.type == 'datetime' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">{{ option.name }}</label>
															<div class="col-sm-12">
																<div class="input-group datetime">
																	<input type="text" name="option[{{ option.product_option_id }}]" value="{{ option.value }}" data-date-format="YYYY-MM-DD HH:mm" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control" />
																	<span class="input-group-btn">
																		<button type="button" class="btn btn-default"><i class="fa fa-calendar"></i></button>
																	</span>
																</div>
															</div>
														</div>
													{% endif %}
													{% if option.type == 'time' %}
														<div class="form-group{% if option.required %} required {% endif %}">
															<label class="control-label col-sm-12"  for="input-option{{ option.product_option_id ~ module ~ option_index }}">{{ option.name }}</label>
															<div class="col-sm-12">
																<div class="input-group time">
																	<input type="text" name="option[{{ option.product_option_id }}]" value="{{ option.value }}" data-date-format="HH:mm" id="input-option{{ option.product_option_id ~ module ~ option_index }}" class="form-control" />
																	<span class="input-group-btn">
																		<button type="button" class="btn btn-default"><i class="fa fa-calendar"></i></button>
																	</span>
																</div>
															</div>
														</div>
													{% endif %}
												{% endfor %}
												<button type="button" class="btn" onclick="cart.addPopup($(this), {{ product.product_id }});">
													<span>{{ button_cart }}</span>
												</button>

											</div>
										</div>
									</div>
								{% endif %}
								<div class="image">
									<a class="lazy" href="{{ product.href }}" style="padding-bottom: {{ product['img-height'] / product['img-width'] * 100 ~ '%' }}">
										{% if product.additional_thumb %}
											<img width="{{ product['img-width'] }}" height="{{ product['img-height'] }}" alt="{{ product['name'] }}" title="{{ product['name'] }}" class="img-primary" data-src="{{ product['thumb'] }}" src="#"/>
											<img width="{{ product['img-width'] }}" height="{{ product['img-height'] }}" alt="{{ product['name'] }}" title="{{ product['name'] }}" class="img-secondary" data-src="{{ product['additional_thumb'] }}" src="#"/>
										{% else %}
											<img width="{{ product['img-width'] }}" height="{{ product['img-height'] }}" alt="{{ product['name'] }}" title="{{ product['name'] }}" class="img" data-src="{{ product['thumb'] }}" src="#"/>
										{% endif %}
									</a>
									<div class="cart-button">
										<button class="btn-icon quickview" type="button" data-toggle="tooltip" title="{{ text_quick }}" data-rel="details" data-product="{{ product['product_id'] }}"><i class="fa fa-search-plus"></i></button>
										<button type="button" class="btn-icon" data-toggle="tooltip" title="{{ button_wishlist }}" onclick="wishlist.add('{{ product.product_id }}');"><i class="fa fa-heart-o"></i></button>
										<button type="button" class="btn-icon" data-toggle="tooltip" title="{{ button_compare }}" onclick="compare.add('{{ product.product_id }}');"><i class="fa fa-random"></i></button>
									</div>
									{% if product.rating %}
										<p class="rating">
											{% for i in 1..5 %}
												{% if product.rating < i %}
													<span class="fa fa-stack"><i class="fa fa-star-o"></i></span>
												{% else %}
													<span class="fa fa-stack"><i class="fa fa-star star"></i></span>
												{% endif %}
											{% endfor %}
										</p>
									{% endif %}
									{% if product.price %}
										{% if product.special %}
											{% if (label_sale) %}
												<div class="sale">
													<span>{{ text_sale }}</span>
												</div>
											{% endif %}
											{% if (label_discount) %}
												<div class="discount">
													<span>{{ product.label_discount }}</span>
												</div>
											{% endif %}
										{% endif %}
									{% endif %}
									{% if (product.label_new) %}
										<div class="new-pr"><span>{{ text_new }}</span></div>
									{% endif %}
								</div>
								<div class="caption">


                                    {#<span>{{ product.href }}</span>#}


                                    {#<span>{{ product.price2 }}#}
{#</span>#}


									<div class="name"><a href="{{ product.href }}">{{ product.name }}</a></div>
									{% if product.price %}
										<p class="price">
											{% if not product.special %}
												{{ product.price }}


                                            {% else %}
												<span class="price-old">{{ product.price }}</span> <span class="price-new">{{ product.special }}</span> 
											{% endif %}
											{% if product.tax %}
												<span class="price-tax">{{ text_tax }} {{ product.tax }}</span>
											{% endif %}
										</p>
									{% endif %}
									<button type="button" class="btn-primary" {% if (product.options|length > 3) %} onclick="cart.add('{{ product.product_id }}');" {% else %} onclick="ajaxAdd($(this),{{ product.product_id }});" {% endif %}>{{ button_cart }}</button>									
								</div>
								
								<div class="aside">
									<div class="name"><a href="{{ product.href }}">{{ product.name }}</a></div>
									{% if product.rating %}
										<p class="rating">
											{% for i in 1..5 %}
												{% if product.rating < i %}
													<span class="fa fa-stack"><i class="fa fa-star-o"></i></span>
												{% else %}
													<span class="fa fa-stack"><i class="fa fa-star star"></i></span>
												{% endif %}
											{% endfor %}
										</p>
									{% endif %}
									<p class="description">{{ product.description }}</p>
									{% if product.price %}
										<p class="price">
											{% if not product.special %}
												{{ product.price }}
											{% else %}											
												<span class="price-old">{{ product.price }}</span> <span class="price-new">{{ product.special }}</span> 
											{% endif %}
											{% if product.tax %}
												<span class="price-tax">{{ text_tax }} {{ product.tax }}</span>
											{% endif %}
										</p>
									{% endif %}
									<button class="btn-primary" type="button" {% if (product.options|length > 3) %} onclick="cart.add('{{ product.product_id }}');" {% else %} onclick="ajaxAdd($(this),{{ product.product_id }});" {% endif %}>{{ button_cart }}</button>
									<div class="clear"></div>
									<button class="product-btn" type="button" onclick="wishlist.add('{{ product['product_id'] }}');"><i class="fa fa-heart-o"></i><span>{{ button_wishlist }}</span></button>
									<button class="product-btn" type="button" onclick="compare.add('{{ product['product_id'] }}');"><i class="fa fa-random"></i><span>{{ button_compare }}</span></button>
								</div>								
							</div>
							<div class="clear"></div>
						</div>
						{%set option_index = option_index + 1 %}
					{% endfor %}
				</div>
				{% if (pagination) %} 
					<div id="product-preloader" data-last="{{ pagination_last }}">
						<span class="preloader"></span>
						<button class='load-more btn-primary ani'>{{ text_load_more }}</button>
					</div>
					<div class="pagination-block text-center">{{ pagination }}</div>
				{% endif %}
			{% endif %}
			{% if not categories and not products %}
				<p>{{ text_empty }}</p>
				<div class="buttons">
					<div class="pull-right"><a href="{{ continue }}" class="btn-primary">{{ button_continue }}</a></div>
				</div>
			{% endif %}
			{{ content_bottom }}
		</div>
		{{ column_right }}
	</div>
</div>
<script type="text/javascript">
	;(function ($) {
		$(document).ready(function(){
			var imgHeight,
			descContHeight,
			desc = $('#description-category'),
			descLink = $('#description-category .link');

			$(window).on('load resize', function(){
				imgHeight = $('#image-category').outerHeight(),
				descContHeight = $('#description-category .description-category__cont').outerHeight() + $('#description-category .description-category__links').outerHeight() + 15;
			});

			$(window).on('load', function(){
				desc.css({
					"height" : imgHeight
				});
			});

			$(window).on('resize', function(){

				if (!desc.hasClass('open')) {
					desc.css({
						"height" : imgHeight
					});
				} else {
					desc.css({
						"height" : descContHeight
					});
				}
			});

			descLink.on('click touchstart', function(e){
				e.preventDefault();
				if (desc.hasClass('open')) {
					desc.css({
						"height" : imgHeight
					})
					.removeClass('open');
					descLink.html($(this).data('textOpen'));
				} else {
					desc.css({
						"height" : descContHeight
					})
					.addClass('open');
					descLink.html($(this).data('textClose'));
				}
			});
		});
	})(jQuery);
</script>
{{ footer }}

 

 

Используется контроллер:

/catalog/controller/product/category.php

Спойлер

<?php
class ControllerProductCategory extends Controller {
	public function index() {
		$this->load->language('product/category');

		$this->load->model('catalog/category');

		$this->load->model('catalog/product');

		$this->load->model('tool/image');

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

		if (isset($this->request->get['sort'])) {
			$sort = $this->request->get['sort'];
		} else {
			$sort = 'p.sort_order';
		}

		if (isset($this->request->get['order'])) {
			$order = $this->request->get['order'];
		} else {
			$order = 'ASC';
		}

		if (isset($this->request->get['page'])) {
			$page = $this->request->get['page'];
		} else {
			$page = 1;
		}

		if (isset($this->request->get['limit'])) {
			$limit = (int)$this->request->get['limit'];
		} else {
			$limit = $this->config->get('theme_' . $this->config->get('config_theme') . '_product_limit');
		}

		$data['breadcrumbs'] = array();

		$data['breadcrumbs'][] = array(
			'text' => $this->language->get('text_home'),
			'href' => $this->url->link('common/home')
		);

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

			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['limit'])) {
				$url .= '&limit=' . $this->request->get['limit'];
			}

			$path = '';

			$parts = explode('_', (string)$this->request->get['path']);

			$category_id = (int)array_pop($parts);

			foreach ($parts as $path_id) {
				if (!$path) {
					$path = (int)$path_id;
				} else {
					$path .= '_' . (int)$path_id;
				}

				$category_info = $this->model_catalog_category->getCategory($path_id);

				if ($category_info) {
					$data['breadcrumbs'][] = array(
						'text' => $category_info['name'],
						'href' => $this->url->link('product/category', 'path=' . $path . $url)
					);
				}
			}
		} else {
			$category_id = 0;
		}

		$category_info = $this->model_catalog_category->getCategory($category_id);

		if ($category_info) {
			$this->document->setTitle($category_info['meta_title']);
			$this->document->setDescription($category_info['meta_description']);
			$this->document->setKeywords($category_info['meta_keyword']);

			$data['heading_title'] = $category_info['name'];

			$data['text_compare'] = sprintf($this->language->get('text_compare'), (isset($this->session->data['compare']) ? count($this->session->data['compare']) : 0));

			// Set the last category breadcrumb
			$data['breadcrumbs'][] = array(
				'text' => $category_info['name'],
				'href' => $this->url->link('product/category', 'path=' . $this->request->get['path'])
			);

			if ($category_info['image']) {
				$data['thumb'] = $this->model_tool_image->resize($category_info['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_category_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_category_height'));
			} else {
				$data['thumb'] = '';
			}

			$data['description'] = html_entity_decode($category_info['description'], ENT_QUOTES, 'UTF-8');
			$data['compare'] = $this->url->link('product/compare');

			$url = '';

			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['limit'])) {
				$url .= '&limit=' . $this->request->get['limit'];
			}

			$data['categories'] = array();

			$results = $this->model_catalog_category->getCategories($category_id);

			foreach ($results as $result) {
				$filter_data = array(
					'filter_category_id'  => $result['category_id'],
					'filter_sub_category' => true
				);

				$data['categories'][] = array(
					'name' => $result['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
					'href' => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '_' . $result['category_id'] . $url)
				);
			}

			$data['products'] = array();

			$filter_data = array(
				'filter_category_id' => $category_id,
				'filter_filter'      => $filter,
				'sort'               => $sort,
				'order'              => $order,
				'start'              => ($page - 1) * $limit,
				'limit'              => $limit
			);

			$product_total = $this->model_catalog_product->getTotalProducts($filter_data);

			$results = $this->model_catalog_product->getProducts($filter_data);

			foreach ($results as $result) {
				if ($result['image']) {
					$image = $this->model_tool_image->resize($result['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_product_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_product_height'));
				} else {
					$image = $this->model_tool_image->resize('placeholder.png', $this->config->get('theme_' . $this->config->get('config_theme') . '_image_product_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_product_height'));
				}

				if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
					$price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
				} else {
					$price = false;
				}

				if ((float)$result['special']) {
					$special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
				} else {
					$special = false;
				}

				if ($this->config->get('config_tax')) {
					$tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
				} else {
					$tax = false;
				}

				if ($this->config->get('config_review_status')) {
					$rating = (int)$result['rating'];
				} else {
					$rating = false;
				}

				$data['products'][] = array(
					'product_id'  => $result['product_id'],
					'thumb'       => $image,
					'name'        => $result['name'],
					'description' => utf8_substr(trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8'))), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..',
					'price'       => $price,
					'special'     => $special,
					'tax'         => $tax,
					'minimum'     => $result['minimum'] > 0 ? $result['minimum'] : 1,
					'rating'      => $result['rating'],
					'href'        => $this->url->link('product/product', 'path=' . $this->request->get['path'] . '&product_id=' . $result['product_id'] . $url)

                );
			}

			$url = '';

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

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

			$data['sorts'] = array();

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_default'),
				'value' => 'p.sort_order-ASC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.sort_order&order=ASC' . $url)
			);

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_name_asc'),
				'value' => 'pd.name-ASC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=pd.name&order=ASC' . $url)
			);

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_name_desc'),
				'value' => 'pd.name-DESC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=pd.name&order=DESC' . $url)
			);

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_price_asc'),
				'value' => 'p.price-ASC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.price&order=ASC' . $url)
			);

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_price_desc'),
				'value' => 'p.price-DESC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.price&order=DESC' . $url)
			);

			if ($this->config->get('config_review_status')) {
				$data['sorts'][] = array(
					'text'  => $this->language->get('text_rating_desc'),
					'value' => 'rating-DESC',
					'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=rating&order=DESC' . $url)
				);

				$data['sorts'][] = array(
					'text'  => $this->language->get('text_rating_asc'),
					'value' => 'rating-ASC',
					'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=rating&order=ASC' . $url)
				);
			}

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_model_asc'),
				'value' => 'p.model-ASC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.model&order=ASC' . $url)
			);

			$data['sorts'][] = array(
				'text'  => $this->language->get('text_model_desc'),
				'value' => 'p.model-DESC',
				'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.model&order=DESC' . $url)
			);

			$url = '';

			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'];
			}

			$data['limits'] = array();

			$limits = array_unique(array($this->config->get('theme_' . $this->config->get('config_theme') . '_product_limit'), 25, 50, 75, 100));

			sort($limits);

			foreach($limits as $value) {
				$data['limits'][] = array(
					'text'  => $value,
					'value' => $value,
					'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . $url . '&limit=' . $value)
				);
			}

			$url = '';

			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['limit'])) {
				$url .= '&limit=' . $this->request->get['limit'];
			}

			$pagination = new Pagination();
			$pagination->total = $product_total;
			$pagination->page = $page;
			$pagination->limit = $limit;
			$pagination->url = $this->url->link('product/category', 'path=' . $this->request->get['path'] . $url . '&page={page}');

			$data['pagination'] = $pagination->render();

			$data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, ceil($product_total / $limit));

			// http://googlewebmastercentral.blogspot.com/2011/09/pagination-with-relnext-and-relprev.html
			if ($page == 1) {
			    $this->document->addLink($this->url->link('product/category', 'path=' . $category_info['category_id']), 'canonical');
			} else {
				$this->document->addLink($this->url->link('product/category', 'path=' . $category_info['category_id'] . '&page='. $page), 'canonical');
			}

			if ($page > 1) {
			    $this->document->addLink($this->url->link('product/category', 'path=' . $category_info['category_id'] . (($page - 2) ? '&page='. ($page - 1) : '')), 'prev');
			}

			if ($limit && ceil($product_total / $limit) > $page) {
			    $this->document->addLink($this->url->link('product/category', 'path=' . $category_info['category_id'] . '&page='. ($page + 1)), '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');

			$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)
			);

			$this->document->setTitle($this->language->get('text_error'));

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

			$this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . ' 404 Not Found');

			$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');

			$this->response->setOutput($this->load->view('error/not_found', $data));
		}
	}
}

 

 

Но это не так.  В шаблон *.twig используются переменные, которые непонятно где определены, я не нашел, я комментировал все файлы с совпадениями названий переменных и не нашел где инициализиюутся переменные. Вот так.

 

К слову контроллер указанный выше я полностью закомментировал, и вывод данных прекрасно работает на сайте. 

Так вот, друзья, подскажите, где в opencart 3.0 инициализируются переменные, к примеру  product.price или stock_status, которые используются в шаблонах category.twig и product.twig 

Цель - научиться передавать переменные в шаблоны *.twig. 

Заранее спасибо.

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

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


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

я не знаком с ОС 3, но возможно переменные передаются через ocmod ? Смотрите модификаторы дополнений, есть ли там они. И кстати в шабе я не нашел того же stock_status , а price - есть в контроллере в массиве products, опять же - возможно изменений Вы не увидели из-за особенностей кэширования ocmod в ОС (правда хз есть ли он в ОС 3)

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


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

С какой целью такой кричащий заголовок.

Контроллер используется не для шаблона, а скорее наоборот, из контроллера "вызываешь" какой надо шаблон.

Все параметры передаются из контроллера в массиве $data.

product.price берется из цикла массива products (

{% for product in products %}

), который заполняется в данном месте в коде контроллера

$data['products'][] = array(
                    'product_id'  => $result['product_id'],
                    'thumb'       => $image,
                    'name'        => $result['name'],
                    'description' => utf8_substr(...
                    'price'       => $price,

...                );

потратив аж целое одно воскресенье не можешь себя считать гуру опенкарта

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


Ссылка на сообщение
Поделиться на другие сайты
15 часов назад, prukon сказал:

Но это не так.  В шаблон *.twig используются переменные, которые непонятно где определены, я не нашел, я комментировал все файлы с совпадениями названий переменных и не нашел где инициализиюутся переменные. Вот так.

 

там кеширование встроенное

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


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

Если изменения были сделаны в шаблоне
То нужно очистить кеш твига

Если не включить автоапдейт

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


Ссылка на сообщение
Поделиться на другие сайты
15 hours ago, prukon said:

К слову контроллер указанный выше я полностью закомментировал, и вывод данных прекрасно работает на сайте. 

Какие данные выводятся в шаблоне если они закомментированы в контроллере?

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


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

вообще искать контроллер для шаблона неверно потому как контроллер определяет, который файл рендерить

а там всё понятно

$this->response->setOutput($this->load->view('product/product', $data));
$output = $template->render($this->registry->get('config')->get('template_directory') . $route, $this->registry->get('config')->get('template_cache'));
$template = $this->twig->loadTemplate($template . '.twig');

 

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


Ссылка на сообщение
Поделиться на другие сайты
1 минуту назад, lexxkrt сказал:

Какие данные выводятся в шаблоне если они закомментированы в контроллере?

это магия

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


Ссылка на сообщение
Поделиться на другие сайты
3 часа назад, lexxkrt сказал:

Какие данные выводятся в шаблоне если они закомментированы в контроллере?

 

 

Я комментирую контроллер (ctrl+a и все закомментить) http://joxi.ru/8Anp0Mbsz19jWm

А здесь я благополучно использую переменные типа {{ stock_status }} http://joxi.ru/12MZQ85FlqdMWA 

Все данные в шаблоне выводятся:  http://joxi.ru/MAjbMNBsjR34yA

 

Вероятно действительно кэширование используется. Уточните, где хранится кэш, надо удалять его при каждом изменении для чистоты тестирования. 

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


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

в верхнем правом углу настройки и там выключаешь кэш.

верний выключаешь, а нижний можно оставить

19 часов назад, prukon сказал:

используются переменные, которые непонятно где определены

элемент массива $data['exemple'] превращается в переменную $exemple (котрорая может быть массивом или объектом)

гугли док. Там об этом подробнее.

 

P. S. Я поймал несколько багов в 3-ей ветке и скачал 2.3. Третья пусть еще поварится. Сырая :) 

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


Ссылка на сообщение
Поделиться на другие сайты
8 часов назад, freelancer сказал:

вообще искать контроллер для шаблона неверно потому как контроллер определяет, который файл рендерить

а там всё понятно


$this->response->setOutput($this->load->view('product/product', $data));

$output = $template->render($this->registry->get('config')->get('template_directory') . $route, $this->registry->get('config')->get('template_cache'));

$template = $this->twig->loadTemplate($template . '.twig');

 

 

Уважаемый freelancer. Этих строк нет в моем контроллере, который я приложил в листиге. 

Скажите как я могу в передать переменную  stock_status в шаблон category.twig?

 

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

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


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

@prukon это пример product

stock_status так же как и любую другую переменную

$data['stock_status'] = $stock_status;

переменные не превращаются в шаблоне, а импортируются 

extract($this->data);

 

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


Ссылка на сообщение
Поделиться на другие сайты
12 часов назад, freelancer сказал:

@prukon это пример product

stock_status так же как и любую другую переменную


$data['stock_status'] = $stock_status;

переменные не превращаются в шаблоне, а импортируются 


extract($this->data);

 

 

Сделал все, как вы сказали http://joxi.ru/VrwbQLzs7VQx7A

В шаблоне добавил вывод: http://joxi.ru/DmBzEaZSJdObPm

На сайте, увы, ничего не хочет выводится http://joxi.ru/5mdvWxBI34MXYA

 

Мне надо как-то передать остатки товаров на страницу категорий (т.е. переменную stock_status).

Кэш чистил. Модификаторы обновлял.

 

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

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


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

 

7 часов назад, prukon сказал:

Мне надо как-то передать остатки товаров на страницу категорий (т.е. переменную stock_status).

 

В таком случае переменную нужно добавить в массив $data['products']

 

Чтобы понять принцип работы, советую сделать так:

Посмотрите сразу в контролере что вам покажет метод getProducts

print_r($results)

если в массиве есть нужный вам элемент, то добавьте его в $data['products']

и выведите его в цикле с товарами

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


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

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

 

Нужно twig кеширует все и вся, поэтому во время разработки кеширование необходимо ВЫКЛЮЧИТЬ

Снимок экрана 2018-04-11 в 12.44.56.png

Снимок экрана 2018-04-11 в 12.45.12.png

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

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


Ссылка на сообщение
Поделиться на другие сайты
18 минут назад, ReaZzon сказал:

Нужно twig кеширует все и вся, поэтому во время разработки кеширование необходимо ВЫКЛЮЧИТЬ

 

первое что я сделал перед разработкой на этой версии 

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


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

Всем спасибо. Оказывается кэш сохранялся еще в одном месте, в папке storage. Он не чистится через админку. 

В этом была вся проблема.

Спасибо всем за помощь.

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


Ссылка на сообщение
Поделиться на другие сайты
В 11.04.2018 в 13:07, freelancer сказал:

первое что я сделал перед разработкой на этой версии 

ЗАчем?

 

<file path="system/library/template/twig.php">
	<operation>
		<search><![CDATA[$this->twig = new \Twig_Environment($loader, $config);]]></search>
		<add position="before"><![CDATA[
		$config['auto_reload'] = true;
		//$config['strict_variables'] = true;
		$config['debug'] = true;
		
		]]></add>
	</operation>
	
</file>

 

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


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

зачем что из админки проще выключить

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


Ссылка на сообщение
Поделиться на другие сайты
On 4/13/2018 at 8:34 PM, chukcha said:

ЗАчем?

 


<file path="system/library/template/twig.php">
	<operation>
		<search><![CDATA[$this->twig = new \Twig_Environment($loader, $config);]]></search>
		<add position="before"><![CDATA[
		$config['auto_reload'] = true;
		//$config['strict_variables'] = true;
		$config['debug'] = true;
		
		]]></add>
	</operation>
	
</file>

 

тогда уж так, расширение Debug по умолчанию не загружается

<file path="system/library/template/twig.php">
    <operation>
        <search><![CDATA[$this->twig = new \Twig_Environment($loader, $config);]]></search>
        <add position="replace"><![CDATA[
		$config['auto_reload'] = true;
		$config['strict_variables'] = true;
		$config['debug'] = true;
		$this->twig = new \Twig_Environment($loader, $config);
		$this->twig->addExtension(new \Twig_Extension_Debug());
        ]]></add>
    </operation>
</file>

 

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


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

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

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

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

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

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

Войти

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

Войти

  • Последние посетители   0 пользователей онлайн

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

×

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

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