@3dben

Почему скрипт срабатывает всего 1 раз?

Дело такое. Разрабатываю с нуля на php интернет-магазин(ради получения опыта и наполнения портфолио). Дошел до реализации каталога товаров.

Давайте по порядку. У меня есть скрипт который строит многоуровневое меню. Скрипт работает, но теперь мне нужно сгенерировать правильные URL моего каталога, а именно получить id главной категории и если есть дочерние то получить и их.

Поехали...
Структура таблицы меню категорий выглядит так:
CREATE TABLE `main_menu` (
  `id` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `parent` int(11) NOT NULL,
  `alias` varchar(255) NOT NULL
) E


Наполнил таблицу такими данными:
INSERT INTO `main_menu` (`id`, `title`, `parent`, `alias`) VALUES
(1, 'Мужское', 0, 'mens'),
(2, 'Женское', 0, 'woomens'),
(3, 'Детское', 0, 'childrens'),
(4, 'Рубашки', 1, 'rubashki'),
(5, 'Брюки', 1, 'bruki'),
(6, 'Футболки', 1, 'footbolki'),
(7, 'Топик', 2, 'topik'),
(8, 'Юбка', 2, 'ubka'),
(9, 'Джинсы', 3, 'jeans'),
(10, 'Кепки', 3, 'heats');


Далее нужно получить все записи из этой таблицы и создать массив где ключами массива является ID меню:
protected function getCat(){
       $res = $this->db->all("SELECT * FROM {$this->table}");

       $cat = [];
       foreach ($res as $row){
           $cat[$row['id']] = $row;
       }
       return $cat;
    }


В результате работы getCat получаю вот такой массив:
Array
(
    [1] => Array
        (
            [id] => 1
            [title] => Мужское
            [parent] => 0
            [alias] => mens
        )

    [2] => Array
        (
            [id] => 2
            [title] => Женское
            [parent] => 0
            [alias] => woomens
        )

    [3] => Array
        (
            [id] => 3
            [title] => Детское
            [parent] => 0
            [alias] => childrens
        )

    [4] => Array
        (
            [id] => 4
            [title] => Рубашки
            [parent] => 1
            [alias] => rubashki
        )

    [5] => Array
        (
            [id] => 5
            [title] => Брюки
            [parent] => 1
            [alias] => bruki
        )

    [6] => Array
        (
            [id] => 6
            [title] => Футболки
            [parent] => 1
            [alias] => footbolki
        )

    [7] => Array
        (
            [id] => 7
            [title] => Топик
            [parent] => 2
            [alias] => topik
        )

    [8] => Array
        (
            [id] => 8
            [title] => Юбка
            [parent] => 2
            [alias] => ubka
        )

    [9] => Array
        (
            [id] => 9
            [title] => Джинсы
            [parent] => 3
            [alias] => jeans
        )

    [10] => Array
        (
            [id] => 10
            [title] => Кепки
            [parent] => 3
            [alias] => heats
        )
)


Вот ссылка которая генерируется в меню:
<a href="/catalog/<?=$category['alias'];?>/"><?=$category['title'];?></a>


Кликнув на неё в контроллере alias попадает в этуфункцию
$get_alias = $menu->getAliasId($this->route['alias']);


Которая возвращает id категории из таблицы main_menu
public function getAliasId($cat_alias){

        if(!$cat_alias){
            return false;
        }

        foreach ($this->data as $key => $value){
            if($value['alias'] == $cat_alias){
                return $key;
            }
            return false;
        }
    }


Теперь нужно найти потомков категории(если таковые имеются). Вот скрипт который отвечает за эту работу:
public function getParentId($id){

        if(!$id){
            return false;
        }

        $data = null;
        foreach ($this->data as $cat){
            if ($cat['parent'] == $id){
                $data .= $cat['id'] . ",";
                $data .= $this->getParentId($cat['id']);
            }
        }
        return $data;
    }


А фот теперь сама проблема. Скрипт работает не корректно. Он находит id и потомков только 1-й категории...
int(1) string(6) "4,5,6,". То есть int(1) - это категория МУЖСКОЕ, а 4,5, и 6 это подкатеогрии (4, 'Рубашки', 1, 'rubashki'),
(5, 'Брюки', 1, 'bruki') и (6, 'Футболки', 1, 'footbolki').

Дело в том что скрипт не находит другие категории. Т.е. Женское = false и подкатегории тоже false. Аналогично и с детской категорией false и подкатегории false.

Я не понимаю как это может быть. Значит 1-ю категорию и его подкатегории скрипт видит, все последующие нет. О_о У меня уже нет сил. Оно должно работать, но не работает =) сил у меня уже нет. Перепробовал всё что смог. ПОМОГИТЕ =)

Старался объяснить максимально подробно, но если что-то не ясно пишите.
  • Вопрос задан
  • 287 просмотров
Решения вопроса 3
@Ambrosian
Попутно:

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

Реляционные СУБД плохо работают с иерархическими структурами. Медленно.
Ответ написан
Immortal_pony
@Immortal_pony Куратор тега PHP

Теперь нужно найти потомков категории(если таковые имеются). Вот скрипт который отвечает за эту работу:
getParentId

Для начала я бы рекомендовал называть вещи своими именами. Если выхотите потомков, то и назвайте функцию getDescendants или getDescendantsIds.

Ваш код вполне рабочий. Если не обращать внимания на то, что в конце строки всегда будет запятая.
И для других категорий тоже работает. Проверка

Что же касается выбранной архитектуры БД - она неудачная.
В текущем виде для получения данных о какой-то ветви вам необходимо всегда получать из БД все категории целиком, а потом уже рабираться с ними на стороне PHP. На малых объемах проблем не будет, но если данных будет много, то подобная система будет работать неспешно.
Я рекомендую ознакомиться с постом, который описывает другие архитектурные подходы для хранения иерархических структур данных в БД.
Ответ написан
Комментировать
@3dben Автор вопроса
Immortal_pony,
Если не обращать внимания на то, что в конце строки всегда будет запятая.

Запятая не лишняя =) Туда после найденных дочерних категорий записывается родительская.
Результат работы скрипта: string(6) "4,5,6,1", где 4,5,6 - это дочерние категории, а 1 это родитель. В общем тут детальнее: catalogIds($route).

abbaboka,
Тебя никто не обвиняет. Тебе просто дают обратную связь, оценив твое решение с профессионального взгляда.

ОК

Вопрос решен. нашел лишний false вот тут:
public function getAliasId($cat_alias){

        if(!$cat_alias){
            return false;
        }

        foreach ($this->data as $key => $value){
            if($value['alias'] == $cat_alias){
                return $key;
            }
            return false;
        }
    }


Итог:
protected function getAliasId($cat_alias){

        if(!$cat_alias){
            return false;
        }
        foreach ($this->data as $key => $value){
            if($value['alias'] == $cat_alias){
                return $key;
            }
        }
        return false;
    }

    protected function getDescendants($id) {

        if(!$id){
            return false;
        }
        $descendants = "";
        foreach ($this->data as $element) {
            if ($element['parent'] == $id) {
                $descendants .= $element['id'] . ",";
                $descendants .= $this->getDescendants($element['id']);
            }
        }
        return $descendants;
    }

    public function catalogIds($route){
        $get_alias = $this->getAliasId($route);
        $descendants = $this->getDescendants($get_alias);

        if(!$descendants){
            return $get_alias;
        }
        return $descendants.$get_alias;
    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
1) Получаете все элементы
2) Строите дерево
3) В цикле рендерите его
Ответ написан
talam0nal
@talam0nal
PHP/Laravel разработчик
Для работы с иерархическими структурами рекомендую использовать эту библиотеку https://github.com/BlueM/Tree
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы