Codeigniter - получить связанные строки данных как структуры/объекты, а не массив

Я новичок в CodeIgniter.

Я создал модель для стола Pizza и таблицы Ingredients. Столы объединены дополнительной таблицей Pizza_Ingredients (отношение многие ко многим).

Моя модель:

<?php

class Pizza extends DataMapper {

    var $table = 'Pizza';

    var $has_many = 
        array(
        'ingredients' => 
            array(
            'class' => 'ingredients',
            'join_table' => 'pizza_ingredients'
            )
        );
}

class Ingredients extends DataMapper {

    var $table = 'Ingredients';
    var $has_many = 
        array(
            'pizza' => 
                array(
                'class' => 'pizza',
                'join_table' => 'pizza_ingredients'
             )
        );
}

?>

Когда я получаю данные, используя этот код:

$pm = new Pizza();
$pm->include_related('ingredients');
$array = $pm->get();

я получаю массив, который дублирует значения пиццы (это похоже на результат запроса sql).

margherita    | cheese
vegetariana   | vegetable 1
vegetariana   | vegetable 2

Я не могу просто сгенерировать html-таблицу в "foreach" для такого массива.

я хочу получить объект, который имеет такую ​​структуру:

margherita:
 - cheese

vegetariana:
 - vegetable 1
 - vegetable 2

это позволяет мне сделать цикл foreach (с пиццей) с другим циклом foreach (с ингредиентами) внутри «цикла пиццы».

Я должен написать это на PHP, или CodeIgniter/DataMapper может сделать для меня что-то еще?

Любой совет?


person Kamil    schedule 24.10.2012    source источник
comment
Я думаю, что это больше связано с вашим методом get, чем с классом/методами, которые вы показали выше. В вашем методе get просто установите ключи для вашего массива на пиццу, которую вы возвращаете из БД. Затем по мере поступления ингредиентов вы будете добавлять массив пиццы вместо создания нового массива для каждой пиццы для каждого ингредиента.   -  person Cody Covey    schedule 24.10.2012
comment
Итак, мне нужно написать собственный аксессуар для моей пиццы. Но как сделать это эффективно и в стиле CodeIgniter? Может ли кто-нибудь привести небольшой пример?   -  person Kamil    schedule 24.10.2012


Ответы (3)


Я просто застрял в том же ответе...

Итак, просматривая DOC CI Datamapper, я нашел кое-что, что поможет (http://datamapper.wanwizard.eu/pages/getadvanced.html), посмотрите на первый пример!

Перевод на вашу проблему должен быть таким:

    // Create pizza

    $pm = new Pizza();

    // DO NOT USE include_related to Ingredients Here !!!
    //Datamapper will DO THIS for you!
    // Remember to declare your Ingredients class in singular, not plural
    // So your class should be in singular -> Ingredient
    // And your DB Table should be in plural -> Ingredients
    // As CI Datamapper Guide teaches :)

    // Get all pizzas

    $pm->get();

    // Loop through all pizzas

    foreach ($pm as $pizza)
    {

    // Print the actual pizza name

            echo $pizza->name."<br/>";

            // Get the current pizza's Ingredients  <- Here is the magic comes!

            $pizza->ingredient->get();

            // Print all current pizza's Ingredients

            foreach ($pizza->ingredient as $ingredient)
            {
                    echo $ingredient->name."<br/>";
            }
    }

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

Я очень ценю, если какое-то решение, использующее CI Datamapper, требует меньше запросов к БД.

Поделитесь, если найдете!

person JorgeDev    schedule 29.10.2012
comment
Я думаю, что лучшим способом сделать это правильно может быть большой SQL-запрос с соединениями. Единственная проблема - это формат данных, возвращаемых запросом - его набор записей, а не древовидная структура. - person Kamil; 29.10.2012

Почему бы не использовать промежуточную таблицу, чтобы разрушить отношения «многие ко многим». Кажется намного проще в управлении. Нравится:

TABLE pizza_ingredients
   id
   pizza_id
   ingredient_id

Тогда вы можете попробовать что-то вроде этого:

foreach($pizzas as $pizza)
    $pizza->ingredients = $this->get_ingredients($pizza->id);
person Jahmic    schedule 25.10.2012
comment
Если вы имеете в виду цикл для строк pizza_ingredients - кажется, это хорошая идея, но я думаю, что get_igredients должен работать с буферизованными данными из одного запроса, а не выполнять 30 запросов, таких как получение ингредиента, где .... вы понимаете, что я имею в виду? - person Kamil; 26.10.2012
comment
Если у вас есть 30 пицц, да, вы попадете в БД 31 раз. Не идеально. Почему бы просто не игнорировать повторяющиеся названия пиццы? Вы пытаетесь поиграть с вложенным выбором на уровне sql, что-то вроде: выберите x, y (выберите z...)... Этот тип запросов требует проб и ошибок. Но, в конце концов, один запрос возвращает строки, а не вложенные данные. - person Jahmic; 26.10.2012
comment
Я могу получить все данные из этих трех таблиц (пицца, таблица отношений, ингредиенты) и поместить их в массивы. Затем сделайте несколько foreach для массива отношений, и я сделаю только 3 запроса. Но у меня есть время, может быть, кто-то придумает что-нибудь получше... - person Kamil; 26.10.2012

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

foreach ($pizza as $k=>$p) {
    if ($last_pizza === $p->pizza) {
        echo "<tr>
            <td>
            </td>
        </tr>
        <tr>
            <td>
                $p->cheese
            </td>
        </tr>";
        $last_pizza = $p->pizza;
    }else{
        echo "<tr>
            <td>
                $p->pizza
            </td>
        </tr>
        <tr>
            <td>
                $p->cheese
            </td>
        </tr>";
        $last_pizza = $p->pizza;
    }
}
person Cody Covey    schedule 25.10.2012
comment
Это не то, что я ищу, но я, вероятно, использую аналогичный код для создания моего объекта pizza_with_ingredients. Я не могу поверить, что есть лучший способ... - person Kamil; 25.10.2012