【问题标题】:PHP Turn recursive array function into a classPHP将递归数组函数变成一个类
【发布时间】:2011-10-26 07:45:34
【问题描述】:

我有一个简单的递归数组函数,如下所示:

function recursive_array($results) {
    global $DBH;
    if (count($results)) {
        echo $res - > Fname;
        foreach($results as $res) {
            $STH = $DBH - > query("SELECT FID,FParentID,Fname FROM list WHERE FParentID  = ".$res - > FID."");
            $fquerycount = $STH - > rowCount();
            $STH - > setFetchMode(PDO::FETCH_OBJ);
            recursive_array($STH);
        }
    }
}


$FID = isset($_GET['FID']) ? $_GET[' FID'] : 0;
$STH = $DBH - > query("SELECT FID,FParentID,Fname FROM list WHERE FParentID ='0' ");
$STH - > setFetchMode(PDO::FETCH_OBJ);
recursive_array($STH);

我还创建了一个简单的查询类,如下所示:

class queryloop {
    function __construct($args) {
        global $DBH;
        $table = $args['tbl'];
        if (array_key_exists('orderby', $args)): $orderby = 'ORDER BY '.$args['orderby'];
        else: $orderby = '';endif;
        if (array_key_exists('groupby', $args)): $groupby = 'GROUP BY '.$args['groupby'];
        else: $groupby = '';endif;
        if (array_key_exists('start', $args)): unset($orderby);$start = $args['start'].' , ';
        else: $start = '';endif;
        if (array_key_exists('limit', $args)): $limit = 'LIMIT '.$start.' '.$args['limit'];
        else: $limit = '';endif;
        // UNSET the previously used array keys so they are not use again to create the query string
        unset($args['tbl']);
        unset($args['orderby']);
        unset($args['groupby']);
        unset($args['start']);
        unset($args['limit']);
        // Checks if args still an array after UNSET above.  If not empty create the query string
        if (!empty($args)): foreach($args as $k = > $v): $querystr. = 'AND '.$k.' = \''.$v.'\'';endforeach;
        // If args array empty return empty query string
        else: $querystr = '';endif;$STH = $DBH - > query("SELECT * FROM ".$table." WHERE key = '".KEY."'  ".$querystr."  ".$groupby." ".$orderby."  ".$limit." ");
        if ($STH): $STH - > setFetchMode(PDO::FETCH_OBJ);
        while ($row = $STH - > fetch()): foreach($row as $key = > $val):
        // check if value is numeric //        
        if (is_numeric($row - > $key)): $data[$row - > ID][$key] = $row - > $key;
        // check if value is array //
        elseif(is_array($row - > $key)): $data[$row - > ID][$key] = $row - > $key;
        // check if value is not numeric or array convert to html entities //
        else: $data[$row - > ID][$key] = htmlentities($row - > $key);endif;endforeach;endwhile;$this - > data = json_encode($data); // return json array if data
        else: $this - > data = ''; // return 'null' if no data
        endif;
    }
}

$args = array('tbl' = > 'atable', 'limit' = > '5', 'start' = > '200', 'orderby' = > 'ID DESC');
$loop = new queryloop($args) // run the loop etc.

我如何将我的递归数组变成类似于类 queryloop 的东西,以便我可以“拉出”json endded 数据我知道这(下面)是完全错误的,但是无论我做什么我都无法得到一个正确形成的 json 数组甚至是从我下面尝试的课程中返回的任何东西。帮助将不胜感激。提前致谢。

class recloop {
    function __construct() {}

    function recursive_array($results) {
        global $DBH;
        if (count($results)) {
            foreach($results as $res) {
                echo $res - > Name;
                $STH = $DBH - > query("SELECT * FROM atable WHERE ParentID  = ".$res - > ID."");
                $fquerycount = $STH - > rowCount();
                $STH - > setFetchMode(PDO::FETCH_OBJ);
                recursive_array($STH);
            }
        }
    }

    function recursive_start() {
        global $DBH;
        $ID = isset($_GET['ID']) ? $_GET['ID'] : 0;
        $STH = $DBH - > query("SELECT * FROM atable WHERE ParentID  = '".$ID."' ");
        $STH - > setFetchMode(PDO::FETCH_OBJ);
        recursive_array($STH);
    }
}

【问题讨论】:

  • 哦,什么...代码。 1) 使用带有自动缩进功能的 IDE(例如 NetBeans)。 2)不要在递归函数中向数据库发送查询,递归很慢。 3)不要使用全局变量(从不)。 4) 在 SQL 查询中使用准备好的语句或转义数据。
  • 表现得像个补间并获得大括号!我知道 :endif 在 PHP 中是合法的,但它们会激怒大多数人。
  • 5) 请阅读一些 PHP。运营商是$object->member没有人$object - > member。 6)不要使用if: else:,使用if { } else { }。习惯 C 语法,你会在编程中遇到它。很多。
  • 您可能还感兴趣:codereview.stackexchange.com
  • Meagar - 好吧,看来我要参加很多活动了,但我没有创建对象 -> 大师!它已被编辑。

标签: php json class recursive-query


【解决方案1】:

我如何将我的递归数组变成类似于类 queryloop 的东西,以便我可以“拉出”json endded 数据我知道这(下面)是完全错误的,但是无论我做什么我都无法得到一个正确形成的 json 数组甚至是从我下面尝试的课程中返回的任何东西。帮助将不胜感激。提前致谢。

要回答您的问题,我想说的是,您是否将例程封装到对象中并不具体,但您要注意每个对象都存在唯一目的。例如:

  • 一个对象正在从数据库中获取数据。
  • 一个对象/复合/数组是数据结构,代表数据。
  • 一个对象或函数正在接管将数据转换/编码为 json 的工作。

在您的代码中,我看到您现在只运行 SQL 查询。从数据库服务器获取的数据根本不会存储到返回变量中,而是在递归处理时直接使用。我假设你这样做是出于调试原因。

所以实际的问题是,你想做什么?你写你想将一个对象编码成 json 输出,这完全可以使用json_encodeDocs,但是我认为你指的是一些特定的数据,比如最 parentId 的实体(数据)或其他东西。

以下是一些基于您的代码的模型代码,用于阅读目的(未经测试,不得满足您的需求),可以使用递归提供由 ID 指定的所有父对象。递归受到批评,因为这可能导致运行大量查询 - 此外还有创建无限循环的风险,这将导致递归堆栈溢出 - 然后您的程序崩溃。

为了解决这个问题,这与数据库设计绑定(这应该在设计代码之前完成,我不知道你的数据库设计,也不知道你真正想要做什么,所以我无法添加的假设)。因此,以下代码仅处理已查询的对象,同时仍使用递归作为查询数据库的策略。

对于实际的数据结构,我选择了一组普通的旧 PHP 对象,以数据库中的 ID 字段为键(我假设它存在于每条记录中):

/**
 * HTTP Get Parameter (Input)
 */
class HTTPGetParameter {
    private $name;
    private $default;
    public function __construct($name, $default = '') {
        $this->name = (string) $name;
        $this->default = (string) $default;   
    }
    /**
     * @return string
     */
    public function getValue()
    {
        return isset($_GET[$name]) ? $_GET[$name] : $this->default;
    }
    /**
     * @return int
     */
    public function getValueInt()
    {
        return (int) $this->getValue();
    }
    /**
     * @link http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
     */
    public function __toString()
    {
        return $this->getValue();
    }
}

/**
 * Data Provider
 */
class PDODataProvider
{
    private $pdo;
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
    /**
     * @return array
     */
    public function findAllATableParents($id)
    {
        return $this->findAllOn('atable', 'ParentID', $id);
    }
    public function findAllBTableParents($id)
    {
        return $this->findAllOn('btable', 'ParentID', $id);
    }
    private function findAllOn($table, $field, $id)
    {
        $id = (int) $id;

        $objects = array();

        $sql = sprintf("SELECT * FROM %s WHERE %s  = '%d'", $table, $field, $id);
        $pdoStatement = $this->pdo->query($sql);
        $pdoStatement->setFetchMode(PDO::FETCH_OBJ);

        foreach($pdoStatement as $parent)
        {
             $parentId = $parent->ID;

             # parents that had been queried are skipped
             if (isset($objects[$parentId]))
                 continue;

             $objects[$parentId] = $parent;

             # add parent objects by recursion
             $objects += $this->findAllParents($parentId);
        }
        return $objects;
    }
}


/**
 * main
 */
$data = new PDODataProvider($DBH);

$id = new HTTPGetParameter('ID', 0);

$objects = $data->findAllParents($id->getValueInt());

echo json_encode($objects);

我希望这个例子对你回答你的问题有所帮助。

【讨论】:

  • 阅读这个 - 非常缓慢 - :) 认为我可以解决 - 因此阅读速度很慢!不太习惯创建类,因为在我的一般工作类型中不需要太多(加上不太了解它们;)所以我倾向于在大多数时间创建“硬”查询。我想我可以从你的例子中学习。非常感谢您的回答。
  • Ummmmm 认为我现在拥有它,因为我说这比我高一点 :) 好的,所以课程有效 - 谢谢 - 但是我如何/在哪里可以为实际表添加 $args 来查询“类似于”我的第一堂课,即一组像表名一样的想法,好像可以完成我可以看到这取代了我在页面顶部的“基本”类 - 具有更多功能。即我们在查询中做这样的事情: $sql = sprintf("SELECT * FROM ".$args['table']." WHERE ParentID = '%d'", $id);
  • 创建一个私有帮助函数,它获取表名作为第二个参数,但作用相同。然后将代码从实际函数移动到辅助函数并参数化表名。然后添加另一个公共函数来查找您需要的第二个表对象。我会更新代码。
  • 对不起,Hakre,现在不丢了getValueInt());"。我看到了“ATable”和“BTable”的辅助函数,但没有看到你实际调用表格的地方(如果那是短语)——应该是这样的吗? $objects = $data->findAllParents($id->getValueInt(),'SOMETHING HERE TO CALL THE TABLE');?
  • 不,我将表名隐藏在类中。普通脚本不应该知道表名,而只知道它请求的数据。然后表名隐藏在 DataProvider 中。而是致电findAllATableParentsfindAllBTableParents
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多