递归但不递归 - 形式选项组/期权人口

时间:2016-03-30 03:20:36

标签: php recursion

我认为自己是PHP新手。我可以让它做我想做的任何事情,但那并没有使它成为'#34;正确"或者最好的方式来做到这一点"。从表现的角度来看,似乎总是有一个更好的"基于代码复杂性和执行时间来实现它的方法。

这可能是其中一个被关闭的问题,因为它是基于意见的"或者其他什么,但我不是在寻找意见。我正在寻找一个更精简,更精简的人。这样做的方式,如果没有别的,我可以学习如何改进。

以下代码有效。它完全符合我的要求。但它似乎非常麻烦。所以问题是:什么是更清洁,更精简和更简洁的方法来实现这一目标?

模型

public function bdgt_cat_select($id = NULL) {
    if ($id == NULL) {
        $query = $this -> db -> query("SELECT * FROM bdgt_cat WHERE parent_id = 0");
        if ($query -> num_rows() > 0) {
            foreach ($query->result() AS $row) {
                $array[] = get_object_vars($row);
            }
            return $array;
        }
    } else {
        $sql = "SELECT * FROM bdgt_cat WHERE parent_id = ?";
        $query = $this -> db -> query($sql, $id);
        if ($query -> num_rows() > 0) {
            foreach ($query->result() AS $row) {
                $array[$row->parent_id] = get_object_vars($row);
            }
            return $array;
        }
    }
}

控制器

public function index() {
    $data['cat_sel'] = $this->read->bdgt_cat_select();
    foreach($data['cat_sel'] AS $subcat) {
        $data['subcat_sel'] = $this->read->bdgt_cat_select($subcat['id']);
    }
    $this->stencil->paint('finance/add_transaction', $data);
}

查看

<select class="form-control" name="id" id="id">
<option value="">-- SELECT --</option>
<?php
    foreach($cat_sel AS $row) {
        (int) $rid = $row['id'];
            if ((int) $row['parent_id'] === 0) {
                echo '<optgroup label="' . $row['cat_label'] . '">';
                    foreach($subcat_sel AS $sub) {
                        if ((int) $sub['parent_id'] == $rid) {
                            echo '<option value="' . $sub['id'] . '">' . $sub['cat_label'] . '</option>';
                        }
                    }
                echo '</optgroup>';
            }
        }
    ?>
</select>

显然,这是我正在开展的大型项目的预算部分。个人的事。不管。

输出

<select class="form-control" name="id" id="id">
    <option value="">-- SELECT --</option>
    <optgroup label="Manual Adjustment"></optgroup>
    <optgroup label="Income">
        <option value="3">Placeholder</option>
    </optgroup>
</select>

最终笔记

这个项目是在CodeIgniter中构建的(这绝不是&#34;我是否需要更改框架&#34;有点问题)。这纯粹是一个个人项目。它可能永远不会出现在互联网上。无论如何,我无法弄清楚Git。我可能会在某些时候将其转换为Phonegap的东西,或者只是在我手机上运行的某种服务器上运行它。这就是为什么我真的质疑性能和可维护性。

1 个答案:

答案 0 :(得分:1)

这个问题涉及太多问题。另一方面,它提供了许多需要逆向工程的代码。反正。

代码可读性:

在我职业生涯的某个时刻,我发现当数据库变成超过20个表时,团队和我都需要记住每个表,每列。为什么这样?因为所有东西都依赖于一些神奇的字符串,即列名和表名。

当你为这些实体赋予意义时,你确实需要你的团队(或者,从现在开始,我会说“你自己”,因为你说这不是一个专业的项目),或者你自己,要记住它们,以便渲染表行,操纵数据等。

首先,您的控制器非常了解模型返回的内容。您确实使用关联数组并将列名称指定为字符串。今天你知道,但一年后?你会怎么做? var_dump($data)看到所有这些神奇的钥匙?

第二位是观点。要呈现任何选项或组,您需要记住列名称。他们都是。哪个是逻辑检查的可控列,这是用于呈现的数据列。

一旦我遇到这个问题,我发现我的大脑充满了桌子和柱子。当项目越来越多且一些表具有相同的名称时,我开始遇到问题,记住哪些列属于项目X,哪些列属于YX中的用户是expires_on列还是Y

我强烈建议你停止依赖魔法弦并在你的大脑爆炸时进行测试。让你的生活轻松。集中数据库操作并对它们进行抽象。 Object Relational Mappings是一个好的开始,但你也可以用木匠的方式做。在模型中提取一次并将它们放入对象中。所有操作或列名称现在都是methodsproperties,IDE将自动为您完成。您不再需要记住域模型的API。 $bdgedCat->并且您收到了可用操作的完整列表: - )

代码重复:

你的模型有一个简单的if / else,它复制了那里的代码。参数为parent_id时,唯一的区别是NULL为0。为什么不在构造中的if / else和另一部分中仅提取它。现在,当两种方案中应用的内容发生变化时,您需要在ifelse

中进行更改
public function bdgt_cat_select($id = NULL) {
     $parent_id = $id === NULL ? 0 : $id;
     $query = $this -> db -> query("SELECT * FROM bdgt_cat WHERE parent_id = ?", $parent_id);
        if ($query -> num_rows() > 0) {
            foreach ($query->result() AS $row) {
                $array[] = get_object_vars($row);
            }
            return $array;
        }     
}

性能:

如果你仔细观察,你会发现潜在的非常大的性能问题。您可以在结果集中迭代以返回模型中的数组。然后,从模型遍历新创建的数组以创建视图数据。然后在视图中,您将遍历视图数据以呈现HTML。您正在对一个结果集进行三次迭代。 PHP版本5.3与许多其他语言一样支持Generators。一种可以在数据上公开迭代器而不是已经在内存中加载的数据本身的方法。可以通过yield关键字来完成。

在许多情况下,您可能需要更改控制器中的数据模型,这就是为什么某些ORM支持功能方法,因此您可以提供函数如何建模数据,但您仍然可以使用生成器,因此仍未评估数据集。为简单起见,我将在下面的示例中跳过此内容。

您的图层可以简化为:

型号:

public function bdgt_cat_select($id = NULL) {
     $parent_id = $id === NULL ? 0 : $id;
     $query = $this -> db -> query("SELECT * FROM bdgt_cat WHERE parent_id = ?", $parent_id);
        if ($query -> num_rows() > 0) {
            foreach ($query->result() AS $row) {
                yield new Category($row['id'], $row['any_other_column']...);
            }
            return $array;
        }     
}

控制器:

public function index() {
    $data = $this->read->bdgt_cat_select();
    // the potential foreach here to model the data is skipped
    // but you can provide a function in your Category model
    // which will be evaluated on using the object
    // via lambda
    $this->stencil->paint('finance/add_transaction', $data);
}

查看:

<?php /** @var Category $data */ ;?>
<select class="form-control" name="id" id="id">
<option value="">-- SELECT --</option>
<?php foreach($data AS $row): ?>
    <?php if ($row->getParentId() === 0): ?>
         <optgroup label="<?= $row->getCatLabel();?>">
               <?php foreach($row->getSubcatSel() AS $sub): ?>
                   <?php if ($sub->getParentId() == $row->getId()): ?>
                        <option value="<?= $sub->getId();?>"> <?= $sub->getCatLabel(); ?></option>
       <?php endif;?>
                <?php endforeach; ?>
                </optgroup>
            <?php endif; ?>
        <?php endforeach; ?>
</select>

但是你真的需要看看某种ORM,你不需要自己开发它。已经有一些更聪明的团队在我们面前抽象了它。也许看看Propel ORM。