【问题标题】:Codeigniter - get related data rows as structures/objects, not arrayCodeigniter - 将相关数据行作为结构/对象获取,而不是数组
【发布时间】:2012-10-14 19:17:05
【问题描述】:

我是 CodeIgniter 的新手。

我为比萨表和配料表创建了模型。表由附加的 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();

我正在获取包含重复 Pizza 值的数组(看起来只是 sql 查询结果)。

margherita    | cheese
vegetariana   | vegetable 1
vegetariana   | vegetable 2

我不能像这样在数组的“foreach”中简单地生成 html 表。

我想获取具有如下结构的对象:

margherita:
 - cheese

vegetariana:
 - vegetable 1
 - vegetable 2

这让我可以在“披萨循环”中与其他 foreach 循环(带有配料)一起制作 foreach 循环(带有披萨)。

我必须用 PHP 写这个,或者 CodeIgniter/DataMapper 可以为我做更多的事情?

有什么建议吗?

【问题讨论】:

  • 我认为这与您的 get 方法有关,而不是您在上面显示的类/方法。在您的 get 方法中,只需将数组的键设置为您从数据库返回的比萨饼。当配料进来时,您将附加比萨数组,而不是为每种配料的每个比萨创建一个新数组。
  • 好的,所以我必须为我的披萨编写自定义访问器。但是如何以 CodeIgniter 风格高效地做到这一点?有人可以举个小例子吗?

标签: php codeigniter codeigniter-datamapper


【解决方案1】:

我只是停留在同一个答案中......

所以,搜索 CI Datamapper DOC,我发现了一些有用的东西(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 的某些解决方案减少对 DB 的请求,我将不胜感激。

如果找到请分享!

【讨论】:

  • 我认为最好的方法可能是使用连接的大 SQL 查询。唯一的问题是查询返回的数据格式——它的记录集,而不是“树结构”。
【解决方案2】:

为什么不使用中间表来分解多对多关系。似乎更容易管理。喜欢:

TABLE pizza_ingredients
   id
   pizza_id
   ingredient_id

然后你可以试试这样的:

foreach($pizzas as $pizza)
    $pizza->ingredients = $this->get_ingredients($pizza->id);

【讨论】:

  • 如果您的意思是在 Pizza_ingredients 行上循环 - 似乎是个好主意,但我认为 get_igredients 应该处理来自一个查询的缓冲数据,而不是运行 30 个查询,例如“get ingredients where ...”。你知道我的意思吗?
  • 如果你有 30 个比萨饼,是的,你会打 db 31 次。不理想。为什么不忽略重复的披萨名称?您尝试在 sql 级别使用嵌套选择,例如: select x, y (select z ...) ... 这些类型的查询需要一些试验和错误。但最终,单个查询返回行,而不是嵌套数据。
  • 我可以从这 3 个表(披萨、关系表、配料)中获取所有数据并将它们放入数组中。然后在关系数组上做一些 foreach ,我只会做 3 个查询。但是我有时间,也许有人会想出更好的主意...
【解决方案3】:

您可以设置一个变量,即您当前正在吃的披萨,并在下一次迭代中检查它。您的格式和其他内容会有所不同,但这会给您一个想法。

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;
    }
}

【讨论】:

  • 这不是我想要的,但我可能使用类似的代码来构建我的“pizza_with_ingredients”对象。我不敢相信有更好的方法......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
相关资源
最近更新 更多