Jump to content

Категории в Компании, или логика задом наперед


Go to solution Solved by Noxter,

Recommended Posts

Привет ребята, возникла второй раз уже необходимость сделать так,
чтобы человек зайдя в бренд, тем самым заполнив переменную $brand
мог увидеть какие категории содержит сие бренд.
 

Например: http://felicita63.ru/brands/kuppersbusch

Решил поделиться решением, возможно и не самым красивым в
плане производительности, хотя ухудшения на практике не заметил.
Решение работало в 2.24, в 2.3.5 тоже нормалек.


Первым делом добавим в низовья файла /api/Products.php

//функция позволяет узнать все категории, в которых есть товары определенной компании
    public function brands_category($bandd_id) 
        {
        $this->db->query("
            SELECT c.id, c.name, c.url, b.url AS brand
            FROM s_categories AS c
            LEFT JOIN s_products_categories AS pc
            ON pc.category_id = c.id
            LEFT JOIN s_products AS p
            ON p.id = pc.product_id
            LEFT JOIN s_brands AS b
            ON b.id = p.brand_id
            WHERE b.id=? 
            AND c.visible = 1
            GROUP BY c.id
            ORDER BY c.name ASC
        ", $bandd_id); 
        $brand_categories = $this->db->results();
        return $brand_categories;
        }    

// Спасибо за быстрый код пользователю Noxter

 

Думаю всем все ясно чего тут и куда, научились получать необходимую информацию,

опозжее сия момента произведите следующую манипуляцию с файлом /view/ProductsView.php

Примерно с 32 строки переделываем функцию в вот такую:

// Если задан бренд, выберем его из базы
if (!empty($brand_url))
{	
$brand = $this->brands->get_brand((string)$brand_url);
	if (empty($brand))
		return false;
	
	$this->design->assign('brand', $brand);
	$filter['brand_id'] = $brand->id;
	
	//Получаем категории бренда и передаем их в шаблон
	$brand_cat= $this->products->brands_category($brand->id);
	$this->design->assign('brand_cat', $brand_cat);
}

 

Собственно почти все, почти готово, имеем нужную информацию, можно пользоваться в шаблонах:

{if ($brand)}

<div class="sort companysort">
	<h2 style="margin-bottom: 10px;">Товары компании представлены в категориях</h2>
	<a href="brands/{$brand->url}{if !($smarty.server.REQUEST_URI|strstr:'brands')}&show=1{/if}"><div {if ($smarty.server.REQUEST_URI|strstr:'brands')}class="selected"{/if}>Все категории</div></a>
	{foreach $brand_cat as $bc}
		<a href="catalog/{$bc->url}/{$brand->url}"><div {if $category->url == $bc->url}class="selected"{/if}>{$bc->name}</div></a>
	{/foreach}
</div>

{/if}
Или иными, более изощренными методами, для коих у вас нынче есть инструментарий.

 

Надеюсь будет полезно, пользуйтесь на здоровье(счастье).

 

Если не поскупитесь за полезность - +7 937 204-69-07.

Link to post
Share on other sites

Я делал такое только не таким топорным методом.

Напомните на днях напишу урок.

 

Ну вы то вон какой козырь острый, я и написал, что метод не из прекрасных. Заранее спасибо за прекрасный)

 

x_c3c194ef.jpg

Link to post
Share on other sites

Метод не только "топорный", но просто таки вредительский в плане создания тормозов.

Если данных в магазине немного, но, может, и незаметно.

А с возрастанием количества товаров у бренда нагрузка будет возрастать в арифметической прогрессии.

Первый пост - характерный пример того, как НЕЛЬЗЯ делать.

 

А уж намекать на деньги за такую откровенную халтуру - совсем нехорошо...

На месте владельца серьезного магазина можно смело отдать 3000 руб, только чтобы такое НЕ устанавливать. Ибо в случае установки убытки будут куда больше...

 

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

Привет товарисч, я и написал, что все бесплатно, давайте вы сделаете все прекрасненько.

При 1800 товарах ничего не изменилось со временем построения страницы) 

Link to post
Share on other sites

 

Примерно так:



    //функция позволяет узнать все категории, в которых есть товары определенной компании
    public function brands_category($brand_id)
    {
    $this->db->query("SELECT DISTINCT c.id, c.name, c.url FROM s_products p, s_products_categories pc, s_categories c WHERE pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?", $brand_id);
    $brand_categories = $this->db->results();
    return $brand_categories;
    }	

 

Я считаю, что какой то тут не совсем правильный запрос получается... 

 

Как вариант:

"SELECT c.id, c.name, c.url FROM s_products AS p LEFT JOIN s_products_categories AS pc ON (pc.product_id=p.id) LEFT JOIN s_categories AS c ON (c.id=pc.category_id) WHERE p.brand_id = ? GROUP BY c.id"

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

Link to post
Share on other sites

Я считаю, что какой то тут не совсем правильный запрос получается... 

 

Как вариант:

"SELECT c.id, c.name, c.url FROM s_products AS p LEFT JOIN s_products_categories AS pc ON (pc.product_id=p.id) LEFT JOIN s_categories AS c ON (c.id=pc.category_id) WHERE p.brand_id = ? GROUP BY c.id"

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

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

Link to post
Share on other sites

Я не говорил что результаты будут не правельным... Дело в оптимизации.

Запрос kors сгружает все строки с таблиц s_products p, s_products_categories pc, s_categories.

Затем начинает сравнение pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?

А после отсеивает повторы - DISTINCT

 

Тот запрос что я дал - быстрее. Он должен пройти по уже проставленным индексам и проверить только на совпадение с p.brand_id 

Link to post
Share on other sites

Я не говорил что результаты будут не правельным... Дело в оптимизации.

Запрос kors сгружает все строки с таблиц s_products p, s_products_categories pc, s_categories.

Затем начинает сравнение pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?

А после отсеивает повторы - DISTINCT

 

Тот запрос что я дал - быстрее. Он должен пройти по уже проставленным индексам и проверить только на совпадение с p.brand_id 

Ваш запрос занял 0.0018 сек. в то время как запрос корса занял 0.0011 сек., проверял в phpmyadmin со стандартной базой товаров симплы.

Link to post
Share on other sites
  • Solution

Мой запрос занял 0.0007 сек.  :) выглядит громоздко но выполняется быстрее представленных вариантов

 

 

SELECT c.id, c.name, c.url, b.url AS brand
FROM s_categories AS c
LEFT JOIN s_products_categories AS pc
ON pc.category_id = c.id
LEFT JOIN s_products AS p
ON p.id = pc.product_id
LEFT JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC
Link to post
Share on other sites

 

Мой запрос занял 0.0007 сек.  :) выглядит громоздко но выполняется быстрее представленных вариантов

 

 

SELECT c.id, c.name, c.url, b.url AS brand
FROM s_categories AS c
LEFT JOIN s_products_categories AS pc
ON pc.category_id = c.id
LEFT JOIN s_products AS p
ON p.id = pc.product_id
LEFT JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC

 

Ребята, красота, блеск, шик.

Вот этот вариант действительно быстрее всех, мой самый по бичу.

 

Ваши различаются очень мало, но этот стабильно быстрее строит конечную страничку.

 

Закину этот вариант в инструкцию?

Про оплату уберу.

Link to post
Share on other sites

Если заменить LEFT JOIN на INNER JOIN, то запрос должен стать еще легче.

 

LEFT JOIN s_brands AS b - также можно удалить для облегчения

Link to post
Share on other sites

Noxter Ну этого никак не может быть. Попробуйте через profiler. http://habrahabr.ru/post/70435/

Ну малые базы это не точно... Нужно пробовать на больших БД. Там сразу должно быть видно разницу

 

Чего не может быть? Если Вы о скорости, то прочтите мое сообщение еще раз в котором я четко написал:

Ваш запрос занял 0.0018 сек. в то время как запрос корса занял 0.0011 сек., проверял в phpmyadmin со стандартной базой товаров симплы.

 

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

Link to post
Share on other sites

Я ж и протестировал! 1-корс 2-мой 3-ваш

И выложил скрин теста. Где сам себвер БД сказал что и как выполняется..

phpmyadmin в этом деле - не точный. Поскольку он возвращает результат за сколько выполнялось все. От вызова функции до получения результата. А я выложил прямые результаты с самого сервера БД

 

Если заменить LEFT JOIN на INNER JOIN, то запрос должен стать еще легче.

 

LEFT JOIN s_brands AS b - также можно удалить для облегчения

На счет INNER - согласен. Возможно даже лучше будет...
Link to post
Share on other sites
  • 1 month later...

Запрос для тех, кому нужно сделать вывод количества товаров бренда в категории:

SELECT c.id, c.name, c.url, b.url AS brand, count(p.id) as `products`
FROM s_categories AS c
INNER JOIN s_products_categories AS pc
ON pc.category_id = c.id
INNER JOIN s_products AS p
ON p.id = pc.product_id
INNER JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC

Результат находится в ячейке products

 

PS: доработанный запрос от Noxter

Link to post
Share on other sites
  • 1 year later...

Вставил код в /api/Products.php

 

на локальном сервере выдает ошибку

 

Parse error: syntax error, unexpected T_PUBLIC in Z:\home\localhost\www\site\api\Products.php on line 549

Edited by crab
Link to post
Share on other sites

Видимо, вставил код не тот. Или не в то место вставил.

Для Вас написано сообщение об ошибке, расшифровано так, что понятнее уже некуда.

Можно предположить, что вставили в самый конец, а надо перед финальной скобкой "}"...

Link to post
Share on other sites

Видимо, вставил код не тот. Или не в то место вставил.

Для Вас написано сообщение об ошибке, расшифровано так, что понятнее уже некуда.

Можно предположить, что вставили в самый конец, а надо перед финальной скобкой "}"...

Так и есть, вставил в самый конец, сейчас работает )

Link to post
Share on other sites
  • 2 years later...

Всем доброго времени суток! Так был рад что нашёл способ осуществить эту идею (Огромная благодарность
PS-SIMPLA за помощь и уделённое время), но только что обломался немного...  :( 
Сделал в точности как описано в первом посте, но бренды не выводятся в шаблоне. 
С первым и вторым шагом косяки с моей стороны исключены, сомневаюсь касательно третего шага (добавления в шаблон). Уже как только не крутил этот кусок кода, пытался в тупую в индексный файл дефолтного шаблона прилепить, но полнейший ноль. Может подскажете в чём может быть трабл?
 

Edited by SimplaUser
Link to post
Share on other sites

//функция позволяет узнать все категории, в которых есть товары определенной компании

public function brands_category($bandd_id)

{

$this->db->query("

SELECT c.id, c.name, c.url, b.url AS brand

FROM s_categories AS c

LEFT JOIN s_products_categories AS pc

ON pc.category_id = c.id

LEFT JOIN s_products AS p

ON p.id = pc.product_id

LEFT JOIN s_brands AS b

ON b.id = p.brand_id

WHERE b.id=?

AND c.visible = 1

GROUP BY c.id

ORDER BY c.name ASC

", $bandd_id);

$brand_categories = $this->db->results();

return $brand_categories;

}

 

// Спасибо за быстрый код пользователю Noxter

Это ведь не ошибки? Уже и их пытался исправлять. :lol:  :unsure:

Edited by SimplaUser
Link to post
Share on other sites

С первым и вторым шагом косяки с моей стороны исключены, сомневаюсь касательно третего шага (добавления в шаблон). Уже как только не крутил этот кусок кода, пытался в тупую в индексный файл дефолтного шаблона прилепить, но полнейший ноль.

 

По моим наблюдениям, в подобных ситуациях в 90% случаев ошибка оказывается очень далеко от того места, где ее настойчиво ишут...

 

Может подскажете в чём может быть трабл?

 

Еше могут быть  сотни мест и сотни причин. Хотите все предположения - читайте книги по PHP, Smarty, WEB-строительству. В интернете Вам  материала для чтения на тысячу лет точно хватит...

 

Обычно, если хотят решить вопрос, дают ТОЧНЫЕ сведения о своих действиях, а не размытыми ничего не значащими фразами типа "как только не крутил"...

Link to post
Share on other sites
  • 3 weeks later...

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

Loading...
×
×
  • Create New...