Функция динамических категорий PHP concat не работает

Я работаю над проектом, в котором есть категории, подкатегории, подкатегории и т. д. Пользователь может их создавать. Я хочу отобразить их на столе. Я использую эту функцию, но возврат дает мне только категории родителей (parent_id = 0). В нем отсутствуют подкатегории, а подкатегории... Если я помещаю var_dump, он показывает мне, что конкатенация работает, но когда функция находит другого родителя категории, теряет другие данные. Что я делаю не так, помогите.

Я хочу вернуть переменную, содержащую все категории и подкатегории.

function categoryTree($catsSubcats = "", $parent_id = 0, $sub_mark = ""){ var_dump($catsSubcats);

        $stmt = Conexion::conectar()->prepare("SELECT * FROM categorias_compra WHERE parent_id = $parent_id");
        $stmt -> execute();
        $respuesta = $stmt -> fetchAll(); 

        if ($respuesta){
            foreach($respuesta as $key => $value){
                $catsSubcats = $catsSubcats . $sub_mark.$value['nombre'].'<br>'; 
                categoryTree($catsSubcats, $value['id'], $sub_mark.str_repeat('&nbsp;', 5));
            }
            return $catsSubcats;
        }
    }

Вы ожидаете, что эта функция будет записывать данные в вашу таблицу? Нет запросов INSERT или UPDATE, и неясно, чего вы пытаетесь достичь

tshimkus 18.03.2019 21:27

Вы не используете результат рекурсивного вызова. Вы хотели добавить это к выходной строке?

Don't Panic 18.03.2019 21:29

Нравится $catsSubcats .= categoryTree(...)

Don't Panic 18.03.2019 21:32

Я хочу добавить все категории и подкатегории в одну строку вывода.

alex prezmon 18.03.2019 21:33

Большое спасибо "Don't Panic"... да, это то, что я хотел

alex prezmon 18.03.2019 21:37

Не по теме: ваш код уязвим для SQL-инъекций. Если вы уже пошли и использовали функцию prepare, то вместо того, чтобы помещать $parent_id непосредственно в строку, используйте заполнитель ? и передайте переменную через функцию execute.

solarc 18.03.2019 21:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
6
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы не используете возвращаемое значение в рекурсии. Вероятно, вы хотите что-то вроде этого:

function categoryTree($parent_id = 0, $sub_mark = ""){ 
        $catsSubcats='';
        $stmt = Conexion::conectar()->prepare("SELECT * FROM categorias_compra WHERE parent_id = $parent_id");
        $stmt -> execute();
        $respuesta = $stmt -> fetchAll(); 

        if ($respuesta){
            foreach($respuesta as $key => $value){
                $catsSubcats .= $sub_mark.$value['nombre'].'<br>'; 
                $catsSubcats .= categoryTree($value['id'], $sub_mark.str_repeat('&nbsp;', 5));
            }
        }
        return $catsSubcats;
    }

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

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

Кроме того, если вы рекурсивно передаете подготовленный оператор, вы должны иметь возможность повторно использовать его вместо повторной подготовки одного и того же.

Я не могу проверить это, но я думаю, что это будет работать лучше.

function categoryTree($parent_id = 0, $sub_mark = "", $stmt = null) {
    if (!$stmt) {
        // only prepare the first time, then pass the prepared statement to subsequent calls
        $stmt = Conexion::conectar()->prepare("SELECT * FROM categorias_compra WHERE parent_id = ?");
    }

    // bind $parent_id to the ? placeholder in the prepared statement
    $stmt->execute([$parent_id]);

    $respuesta = $stmt->fetchAll();

    // initialize the result of each call to an empty string
    $catsSubcats = "";

    if ($respuesta) {

        // you can also move this before the loop so it only has to execute once
        $sub_mark .= str_repeat('&nbsp;', 5);

        foreach ($respuesta as $key => $value) {
            $catsSubcats .= $sub_mark.$value['nombre'].'<br>';
            $catsSubcats .= categoryTree($value['id'], $sub_mark, $stmt);
        }
    }

    // always return a string
    return $catsSubcats;
}

Другие вопросы по теме