0

在 PHP 中使用 codeigniter 活动记录实现这样的结果集的最有效方法是什么?

[2] => stdClass Object
    (
        [id] => 12
        [title] => 2 sections
        [layout_id] => 1
        [layout] => stdClass Object
            (
                [id] => 1
                [file] => 3_column.php
                [title] => 3 Column
            )

        [sections] => Array
            (
                [0] => stdClass Object
                    (
                        [module_id] => 12
                        [section_id] => 1
                    )

                [1] => stdClass Object
                    (
                        [module_id] => 12
                        [section_id] => 2
                    )

            )

    )   

这里有一些东西可以给我想要的嵌套结果,但我发现这种方法效率很低(忽略select *每个查询的)

public function all()
{
  $rows = $this->db->get('modules')->result();

  foreach($rows as &$row)
  {
    $row->layout = $this->db->get_where('layouts', array('id' => $row->layout_id), 1)->first_row();
    $row->sections = $this->db->get_where('modules_sections', array('module_id' => $row->id))->result();
  }

  return $rows;
}
4

2 回答 2

1

您可以使用一些连接和 GROUP_BY 子句轻松地将这几个查询转换为一个查询。这种方法最大的缺点是它需要对数据进行一点分组和定界,但 PHP 擅长“爆炸”定界数据。试试这个:

function all()
{

    $this->db->select("`modules`.*, CONCAT(`layouts`.`id`,'".DATA_SUBDELIMITER."',`layouts`.`title`,'".DATA_SUBDELIMITER."',`layouts`.`file`) AS layout, CAST(GROUP_CONCAT(`sections`.`id`,'".DATA_SUBDELIMITER."',`sections`.`title` SEPARATOR '".DATA_DELIMITER."') AS CHAR) AS sections", false);
    $this->db->from('modules');
    $this->db->join('layouts', 'layouts.id = modules.layout_id');
    $this->db->join('modules_sections', 'modules_sections.module_id = modules.id');
    $this->db->join('sections', 'sections.id = modules_sections.section_id');
    $this->db->group_by('modules.id');

    $rows = $this->db->get()->result_array();
    foreach($rows as &$row)
    {
        foreach($row as $k=>&$r)
        {
            if($k=='layout' || $k=='sections')
            {
                $new_r = explode(DATA_DELIMITER, $r);
                foreach($new_r as &$c)
                {
                    $e = explode(DATA_SUBDELIMITER,$c);
                    $c = array();
                    list($c['id'],$c['title']) = $e;
                    if(!empty($e[2])) $c['file'] = $e[2];
                }
                if($k=='layout') $new_r = $new_r[0];
                $r = $new_r;
            }
        }
    }

    return $rows;
}

此示例使用 DATA_DELIMITER 和 DATA_SUBDELIMITER 作为分隔数据的字符。如果您使用这些常量,那么您可能应该在您的 application/config/constants.php 文件中定义它们。或许是这样的:

define('DATA_DELIMITER','||');
define('DATA_SUBDELIMITER','##');

测试此代码以产生如下结果:

Array
(
    [0] => Array
        (
            [id] => 1
            [title] => Module 1
            [layout_id] => 1
            [layout] => Array
                (
                    [title] => 3 Column
                    [id] => 1
                    [file] => 3_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 2
                            [id] => 2
                        )

                )

        )

    [1] => Array
        (
            [id] => 2
            [title] => Module 2
            [layout_id] => 2
            [layout] => Array
                (
                    [title] => 2 Column
                    [id] => 2
                    [file] => 2_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                )

        )

    [2] => Array
        (
            [id] => 3
            [title] => Module 3
            [layout_id] => 1
            [layout] => Array
                (
                    [title] => 3 Column
                    [id] => 1
                    [file] => 3_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                )

        )

    [3] => Array
        (
            [id] => 4
            [title] => Module 4
            [layout_id] => 2
            [layout] => Array
                (
                    [title] => 2 Column
                    [id] => 2
                    [file] => 2_column.php
                )

            [sections] => Array
                (
                    [0] => Array
                        (
                            [title] => Section 1
                            [id] => 1
                        )

                    [1] => Array
                        (
                            [title] => Section 2
                            [id] => 2
                        )

                    [2] => Array
                        (
                            [title] => Section 3
                            [id] => 3
                        )

                    [3] => Array
                        (
                            [title] => Section 4
                            [id] => 4
                        )

                )

        )

)
于 2012-08-02T21:55:23.037 回答
0

高效在这里是一个相对的术语。

如果您正在考虑最小化 sql server 上的查询,您总是可以序列化您的对象并将它们存储在缓存表中,那么您只有一个查找,但您必须在任何类型的写入操作中维护这些对象。除此之外,您可能只需要加载测试并查看瓶颈在哪里。有时,多个查询可能比一个巨大的多表连接更快。

于 2012-08-02T21:26:56.593 回答