[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Строка навигации
Shurick
Доброго времени суток!

Начинаю создавать свой первый каталог для магазина. Существует куча подкаталогов. Хочу упростить запрос для вывода строки навигации в каталоге но не хватает опыта.

вот код запроса к БД

PHP
$result_cat mysql_query("SELECT id,name FROM shop_groups WHERE parent='0'");
      while (
$row_cat mysql_fetch_array($result_cat)) {
      if(
$cat == $row_cat['id']){$nav[] = array($row_cat['id'], $row_cat['name'], "/catalog/".$row_cat['id'].".html");}

      
$result_poda mysql_query("SELECT id,name FROM shop_groups WHERE parent='".$row_cat['id']."'");
      while (
$row_poda mysql_fetch_array($result_poda)) {
      if(
$cat == $row_poda['id']){
      
$stop_menu $row_poda['id'];
      
$nav[] = array($row_cat['id'], $row_cat['name'], "/catalog/".$row_cat['id'].".html");
      
$nav[] = array($row_poda['id'], $row_poda['name'], "/catalog/".$row_poda['id'].".html");}

      
$result_podb mysql_query("SELECT id,name FROM shop_groups WHERE parent='".$row_poda['id']."'");
      while (
$row_podb mysql_fetch_array($result_podb)) {
      if(
$cat == $row_podb['id']){
      
$stop_menu $row_poda['id'];
      
$pod_menu $row_podb['id'];
      
$nav[] = array($row_cat['id'], $row_cat['name'], "/catalog/".$row_cat['id'].".html");
      
$nav[] = array($row_poda['id'], $row_poda['name'], "/catalog/".$row_poda['id'].".html");
      
$nav[] = array($row_podb['id'], $row_podb['name'], "/catalog/".$row_podb['id'].".html");}

      
$result_podc mysql_query("SELECT id,name FROM shop_groups WHERE parent='".$row_podb['id']."'");
      while (
$row_podc mysql_fetch_array($result_podc)) {
      if(
$cat == $row_podc['id']){
      
$stop_menu $row_poda['id'];
      
$pod_menu $row_podb['id'];
      
$nav[] = array($row_cat['id'], $row_cat['name'], "/catalog/".$row_cat['id'].".html");
      
$nav[] = array($row_poda['id'], $row_poda['name'], "/catalog/".$row_poda['id'].".html");
      
$nav[] = array($row_podb['id'], $row_podb['name'], "/catalog/".$row_podb['id'].".html");
      
$nav[] = array($row_podc['id'], $row_podc['name'], "/catalog/".$row_podc['id'].".html");}
      }
      }}}


      
$navigation "<table cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href='/'>Главная</a></td>";
      for(
$i=0$i<count($nav); $i++){

      if(
$cat !== $nav[$i][0]) {$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><a href='".$nav[$i][2]."'>".$nav[$i][1]."</a></td>"; }
      else { 
$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><h1>".$nav[$i][1]."</h1></td>"; }
      }
$navigation .= "</tr></table>";
echo 
$navigation;



Как то так....

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

Что можно сделать для того что бы как то автоматизировать этот процесс?!



Спустя 37 минут, 46 секунд (5.06.2009 - 01:56) twin написал(а):
Пытался, ниасилил. Проще напиши что есть и что нужно.

Спустя 5 часов, 48 минут, 59 секунд (5.06.2009 - 07:45) glock18 написал(а):
Ему нужно выбрать все категории. Сейчас так идет выборка:
1. собрал самую старшую категорию.
2. в цикле для каждой из категорий по запросу на ее потомков.
3. для каждого из потомков то же самое blink.gif

Жээээсть - три вложенных цикла с запросами на каждой итерации blink.gif

Цитата
Хочу упростить запрос для вывода строки


Поправлю - у тебя оочень простые запросы, просто их у тебя много)))

Тут уже огромное количество таких тем. Смотри использрование IN в запросах.

Спустя 3 часа, 50 минут, 21 секунда (5.06.2009 - 11:35) Shurick написал(а):
Цитата (glock18 @ 5.06.2009 - 04:45)
Сейчас так идет выборка:
1. собрал самую старшую категорию.
2. в цикле для каждой из категорий по запросу на ее потомков.
3. для каждого из потомков то же самое blink.gif

Жээээсть - три вложенных цикла с запросами на каждой итерации blink.gif


Тут уже огромное количество таких тем. Смотри использрование IN в запросах.

Вот и не могу придумать как это можно сделать иначе.

Передается одно значение (http://mysite.ru/catalog/48.html), определяю все старшие категории, если нашлось совпадение то формирую ссылки (Начало / Для дома / Утюги).

huh.gif unsure.gif А вот как реализовать запрос через IN?? ведь все равно необходимо использовать как минимум 3 запроса (на сколько я понимаю).


Спустя 1 час, 17 минут, 35 секунд (5.06.2009 - 12:53) glock18 написал(а):
Ну самая простая оптимизация - да. 3 запроса. уже неплохо, я думаю.
Если добавить чуть-чуть логики, то можно и одним все это дело собрать (потом в php разобрать).

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

Спустя 5 часов, 5 минут, 45 секунд (5.06.2009 - 17:59) Shurick написал(а):
Вот! 3 запроса...

PHP
$result_cat mysql_query("SELECT id,name,parent FROM shop_groups");
      while (
$row_cat mysql_fetch_array($result_cat)) {
      
$cat_arr[] = array($row_cat['id'], $row_cat['parent'], $row_cat['name']);
      }

      function 
parent_name($a)
      {
      
$query mysql_query("SELECT * FROM shop_groups WHERE id='".$a."' ");
      
$res mysql_fetch_array($query);
      if(
$a == $res['id'])
      return 
$arr = array($res['id'], $res['name']);
      }

      function 
parent_id($a)
      {
      
$query mysql_query("SELECT * FROM shop_groups WHERE id='".$a."' ");
      
$res mysql_fetch_array($query);
      if(
$a == $res['id'])
      return 
$res['parent'];
      }

      for(
$i=0$i<count($cat_arr); $i++){

      if(
$cat == $cat_arr[$i][0]) {

      
$id_podcat parent_id($cat_arr[$i][1]);
      
$id_podcata parent_id($id_podcat);

      
$arr_menua parent_name($id_podcata);
      
$arr_menub parent_name($id_podcat);
      
$arr_menuc parent_name($cat_arr[$i][1]);

      
$echo_nav $arr_menua[1].$arr_menub[1].$arr_menuc[1]."<h1>".$cat_arr[$i][2]."</h1>";

      echo 
$echo_nav;

        }
      }


Ничего лучше придумать как то не смог. Выводит строку до 4-х подкаталогов

Спустя 26 минут, 30 секунд (5.06.2009 - 18:25) Shurick написал(а):
Ура! Прогрес! 2 запроса


PHP
$result_cat mysql_query("SELECT id,name,parent FROM shop_groups");
      while (
$row_cat mysql_fetch_array($result_cat)) {
      
$cat_arr[] = array($row_cat['id'], $row_cat['parent'], $row_cat['name']);
      }

      function 
parent_name($a)
      {
$query mysql_query("SELECT * FROM shop_groups WHERE id='".$a."' ");
       
$res mysql_fetch_array($query);
       if(
$a == $res['id'])return $arr = array($res['id'], $res['name'], $res['parent'],);}

      for(
$i=0$i<count($cat_arr); $i++){
      if(
$cat == $cat_arr[$i][0]) {
      
$arr_menuc parent_name($cat_arr[$i][1]);
      
$arr_menub parent_name($arr_menuc[2]);
      
$arr_menua parent_name($arr_menub[2]);

      if(
$arr_menua[0] != 0){$nav[] = array($arr_menua[0], $arr_menua[1], "/catalog/".$arr_menua[0].".html");}
      if(
$arr_menub[0] != 0){$nav[] = array($arr_menub[0], $arr_menub[1], "/catalog/".$arr_menub[0].".html");}
      if(
$arr_menuc[0] != 0){$nav[] = array($arr_menuc[0], $arr_menuc[1], "/catalog/".$arr_menuc[0].".html");}
      
$nav[] = array($cat_arr[$i][0], $cat_arr[$i][2], "/catalog/".$cat_arr[$i][2].".html");
        }
      }

      
$navigation "<table cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href='/'>Главная</a></td>";
      for(
$i=0$i<count($nav); $i++){

      if(
$cat !== $nav[$i][0]) {$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><a href='".$nav[$i][2]."'>".$nav[$i][1]."</a></td>"; }
      else { 
$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><h1>".$nav[$i][1]."</h1></td>"; }
      }
$navigation .= "</tr></table>";


Может что не так в коде!? может кто вынести вердикт - можно использовать?!

Ну по сравнению с первоначальным вариантом это просто ЛАЙТ версия smile.gif

Спустя 2 часа, 54 минуты, 10 секунд (5.06.2009 - 21:19) glock18 написал(а):
smile.gif похвально старание.

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

Я тебя сначала неправильно понял - думал, ты выбираешь всю иерархию, а тебе нужны только хлебные крошки...

Тогда убери свой первый запрос подальше, а также все циклы которые сейчас есть))).

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

SQL
SELECT t.id AS tid, t.name AS tname FROM ta_category t
LEFT JOIN ta_category t1 ON t.parent_id = t1.id
LEFT JOIN ta_category t2 ON t1.parent_id = t2.id
LEFT JOIN ta_category t3 ON t2.parent_id = t3.id
WHERE t.id = 77;


1. вместо 77 подставь переданный id.
2. Названия таблиц и полей тоже замени.
3. Смысл такой: в этом запросе чем больше циферка после t - тем более далекий это предок.
4. Перечисли все поля "ручками" как я начал указывать. php - не запишет тебе их все в ассоциативный массив (ключи одинаковые) - надо указать для каждого уникальный псеводним (после AS).
5. Если родительских категорий меньше 3 - значения полей, начиния с t3, будут null - это значит, что у предыдущей категории нет родителя и она самая старшая.

6. Способ не универсальный, чем мне не нравится, но тебе пойдет вполне. Не универсален тем, что если нужно будет добавить еще один уровень, то придется дописывать еще одну строку:

SQL
LEFT JOIN ta_category tn ON t(n-1).parent_id = tn.id


Если не сможешь разобраться - пиши.

Спустя 1 час, 17 минут, 25 секунд (5.06.2009 - 22:37) Shurick написал(а):
хм... сложно признаться, но не могу разобраться с тем как вывести значения. sad.gif код выводит только одно значение

скорее всего чет где то я недопонял... ща буду лазать!

Спустя 8 часов, 32 минуты, 4 секунды (6.06.2009 - 07:09) glock18 написал(а):
полазь)) советую запрос проверить не в php, а каком-нибудь mysql-клиенте, который используешь. Наверняка, это phpmyadmin. Посмотри что этот запрос тебе вернет для разных категорий, и сразу станет понятно.

Спустя 3 часа, 31 минута, 13 секунд (6.06.2009 - 10:40) Shurick написал(а):
Просидел до 4-х ночи, но все мои манипуляции оказались безнадежными. Если бы кроме метода ТЫКА я понимал в SQL чуть больше у меня бы все получилось. Увы... smile.gif

забросил в phpmyadmin - выдал одну запрашиваемую по иду строку

SQL
SELECT t.id AS tid, t.name AS tname, t.parent AS tparent
FROM shop_groups t
LEFT JOIN shop_groups t1 ON t.parent = t1.id
LEFT JOIN shop_groups t2 ON t1.parent = t2.id
LEFT JOIN shop_groups t3 ON t2.parent = t3.id
WHERE t.id =64
LIMIT 0, 30


SQL
tid tname tparent
64 мешки 58


в запрос не надо вписывать каждый из уровней?

Спустя 6 часов, 3 минуты, 47 секунд (6.06.2009 - 16:44) glock18 написал(а):
SQL
SELECT t.id AS tid, t.name AS tname, t.parent AS tparent

Если вставляешь в phpmyadmin, а не в скрипт, то можешь поставить в списке полей *, чтобы увидеть что ты можешь вообще получить оттуда.

Цитата
в запрос не надо вписывать каждый из уровней?

Правильно, тебе просто в списке полей нужно перечислить поля для каждого из уровней отдельно:

SQL
SELECT t.id AS tid, t.name AS tname, t.parent AS tparent
t1.id AS t1id, t1.name AS t1name, t1.parent AS t1parent
t2.id AS other_id, t2.name AS somename, t.parent AS ...

Спустя 20 часов, 14 минут, 54 секунды (7.06.2009 - 12:59) Shurick написал(а):
Разобрался!!!
SQL
$resultta = mysql_query("

SELECT
t.id AS tid, t.name AS tname, t.parent AS tparent,
t1.id AS tida, t1.name AS tnamea, t1.parent AS tparenta,
t2.id AS tidb, t2.name AS tnameb, t2.parent AS tparentb,
t3.id AS tidc, t3.name AS tnamec, t3.parent AS tparentc

FROM shop_groups t
LEFT JOIN shop_groups t1 ON t.parent=t1.id
LEFT JOIN shop_groups t2 ON t1.parent=t2.id
LEFT JOIN shop_groups t3 ON t2.parent=t3.id

WHERE t.id=$cat");
$rowta = mysql_fetch_array($resultta);

if($rowta['tidc'] != 0){$nav[] = array($rowta['tidc'], $rowta['tnamec'], "/catalog/".$rowta['tidc'].".html");}
if($rowta['tidb'] != 0){$nav[] = array($rowta['tidb'], $rowta['tnameb'], "/catalog/".$rowta['tidb'].".html");}
if($rowta['tida'] != 0){$nav[] = array($rowta['tida'], $rowta['tnamea'], "/catalog/".$rowta['tida'].".html");}
if($rowta['tid'] != 0){$nav[] = array($rowta['tid'], $rowta['tname'], "/catalog/".$rowta['tid'].".html");}

$navigation = "<table cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href='/'>Главная</a></td>";
for($i=0; $i<count($nav); $i++){
if($focus !== $nav[$i][0]) {$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><a href='".$nav[$i][2]."'>".$nav[$i][1]."</a></td>"; }
else { $navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><h1>".$nav[$i][1]."</h1></td>"; }
}$navigation .= "</tr></table>";

echo $navigation;


Да, есть неудобство с добавлением уровней.... Но она была актуальна и в моем случае smile.gif

Спустя 6 часов, 26 минут, 34 секунды (7.06.2009 - 19:25) glock18 написал(а):
Да, конечно. Здесь оно даже проще, чем было бы у тебя.

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

Спустя 27 минут, 16 секунд (7.06.2009 - 19:52) Shurick написал(а):
Цитата (glock18 @ 7.06.2009 - 16:25)
Да, конечно. Здесь оно даже проще, чем было бы у тебя.

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

Ну так возможно есть смысл добавить в БД этот параметр!? я думаю он не особо утяжелит базу?!

Спустя 12 минут, 58 секунд (7.06.2009 - 20:05) glock18 написал(а):
Он должен быть не в базе. Этот параметр надо функции передавать. Можешь его в конфиге поставить, если максимальная глубина не будет особо меняться. Тут задача не в добавлении параметра, а в написании функции.

Спустя 1 день, 4 часа, 29 секунд (9.06.2009 - 00:06) Shurick написал(а):
все же добавил параметр глубины каталога в БД. (подсмотрел в БД abocms)

написал следующее :


PHP
$catalog mysql_query("SELECT * FROM shop_groups WHERE id='".$cat."' ");
      
$rowc mysql_fetch_array($catalog);

      
for ($i = 0; $i < $rowc['level']; $i++) {
      if($i == 0)$i="";
      $tlj = $i-1;
      if($tlj == 0){$tlj="";}
      $f = $rowc['level']-1;
      if($i == $f){$s="";}else{$s=",";}
      $t .= "t".$i.".id AS tid".$i.", t".$i.".name AS tname".$i.", t".$i.".parent AS tparent".$i."$s ";
      if($i != 0)$left_join  .= "LEFT JOIN shop_groups t".$i." ON t".$tlj.".parent=t".$i.".id ";
      }

      $resultta = mysql_query("SELECT $t FROM shop_groups t $left_join where t.id = ".$cat." order by t.level desc");
      $rowta = mysql_fetch_array($resultta);

      for ($i = 0; $i < $rowc['level']; $i++) {
      if($i == 0)$i="";
      $conid = "tid".$i."";
      $conname = "tname".$i."";
      if($rowta[$conid] != 0){$nav[] = array("id" => $rowta[$conid], "name" => $rowta[$conname], "link" => "/catalog/".$rowta[$conid].".html");}
      sort($nav);
      }

      $navigation = "<table cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href='/'>Главная</a></td>";
      for($i=0; $i<count($nav); $i++){
      if($focus !== $nav[$i]["id"]) {$navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><a href='".$nav[$i]['link']."'>".$nav[$i]['name']."</a></td>"; }
      else { $navigation .= "<td width=\"29\"><img src=\"/templates/images/style_img_1/ico/arst.gif\" width=\"29\" height=\"15\" alt=\"\" /></td><td><h1>".$nav[$i]['name']."</h1></td>"; }
      }$navigation .= "</tr></table>";


работает ё-ма-ё! сам в ШОКЕ! biggrin.gif

Спустя 8 часов, 8 минут, 43 секунды (9.06.2009 - 08:15) glock18 написал(а):
smile.gif

Спустя 14 минут, 49 секунд (9.06.2009 - 08:29) Shurick написал(а):
ну как код? нет косяков?! все смотрел в исходники abocms. ну эт пока не для меня. там слишком все сложно.

проверял до 10-ти подкаталогов - все работает.

Спустя 1 час, 52 минуты, 34 секунды (9.06.2009 - 10:22) glock18 написал(а):
Вроде должно работать, но все таки это более запутанно, чем я себе представлял smile.gif Попробуй вот это (глубина в базе не нужна):

PHP
function GetCategoriesBreadCrumbs($categoryID$currentItem$depth 3)
    {
        
$fields 't.id AS tid, t.name AS tname, t.parent AS tparent';
        
$joins '';
        
$idAlias 'tid';
        
$nameAlias 'tname';
        
$parentAlias 'tparent';
        for (
$i 1$i <= $depth$i++)
        {
            
$tableAlias 't' $i;
            
$joins .= ('LEFT JOIN shop_groups ' $tableAlias ' ON t.parent=' $tableAlias '.id ');
            
$fields .= (', ' $tableAlias '.id AS ' $idAlias $i .
                        
', ' $tableAlias '.name AS ' $nameAlias $i .
                        
', ' $tableAlias '.parent AS ' $parentAlias $i);
        }
        
$query 'SELECT ' $fields 
                    
'FROM shop_groups t ' 
                    
$joins .
                    
'WHERE t.id = ' $categoryID ' ' .
                    
'LIMIT 1';
                    
        
$result mysql_query($query);
        
$nav = array();
        if (
$row mysql_fetch_assoc($result))
        {
            for (
$i depth$i 0$i--)
            {
                if (
$row['tid' $i])
                    
$nav[] = array($row[$idAlias $i], $row[$nameAlias $i], "/catalog/".$row[$idAlias $i].".html");
            }
            if (
$row['tid'])
                
$nav[] = array($row[$idAlias], $row[$nameAlias], "/catalog/".$row[$idAlias].".html");
        }
        
ob_start(); // то что идет после для лучшей читаемости вынести в отдельный файл, который здесь просто подключать
        
include ('table.php');
        
$navigation ob_get_contents();
        
ob_end_clean();
        return 
$navigation;
    }


Эта функция вернет тебе html, который вывести надо.

Table.php такой:
PHP
<table cellpadding="0" cellspacing="0">
            <
tr>
                <
td><a href='/'>Главная</a></td>
                <?
php foreach ($nav as $item) :?>
                    <td width="29">
                        <img src="/templates/images/style_img_1/ico/arst.gif" width="29" height="15" alt="" /></td>
                    </td>
                    <?php if ($currentItem !== $item[0]) :?>
                        <td><a href="<?php echo $item[2];?>"><?php echo $item[1];?></a></td>
                    <?php else: ?>
                        <td><h1><?php echo $item[1];?></h1></td>
                    <?php endif;?>
                <?php endforeach;?>
            </tr>
   


А использование функции такое:
PHP
$categoryID 15// нужная категория
$currentCategory 15// категория, которую нужно не ссылкой
echo GetCategoriesBreadCrumbs($categoryID$currentCategory); // 3 параметр можно не передавать. он по умолчанию 3.


Вот такое. Один запрос всего. И строится в одной функции вне зависимости от количества элементов, которые нужно вывести.

Я не тестировал, так что если будет что-то не так, то скажи. у меня базы подходящей под рукой сейчас нет, чтобы проверить smile.gif

Спустя 46 минут, 41 секунда (9.06.2009 - 11:09) Shurick написал(а):
Доходчиво, профессионально, блин и вообще тож так хочу unsure.gif smile.gif

И вообще огромное спасибо за помощь!!!!!!

Слудеющая задача для меня это карта каталога....

Спустя 20 минут, 11 секунд (9.06.2009 - 11:29) glock18 написал(а):
Пожалуйста. И большое спасибо за
Цитата (Shurick @ 9.06.2009 - 08:09)
Доходчиво, профессионально

я еще молодой, чтобы всерьез себя считать профессионалом, но это приятно smile.gif

С картой если что не получится, обращайся.


_____________
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.