【问题标题】:Trying to understand recursion in objects and arrays in php试图理解 php 中对象和数组的递归
【发布时间】:2011-10-20 02:48:15
【问题描述】:

我正在尝试构建一个将项目添加到数据库的 mysql 查询。这些项目保存在一个对象中,其格式如下:

object(PhealResult)#7 (5) {
  ["request_time"]=>
  string(19) "2011-08-04 14:14:37"
  ["request_time_unixtime"]=>
  int(1312467277)
  ["cached_until"]=>
  string(19) "2011-08-04 20:14:37"
  ["cached_until_unixtime"]=>
  int(1312488877)
  ["_element:private"]=>
  object(PhealElement)#12 (3) {
    ["_name"]=>
    string(6) "result"
    ["_value"]=>
    object(PhealContainer)#11 (1) {
      ["_container:private"]=>
      array(1) {
        ["assets"]=>
        object(PhealRowSet)#14 (3) {
          [0]=>
          object(PhealRowSetRow)#19 (6) {
            ["itemID"]=>
            string(13) "1003152969505"
            ["locationID"]=>
            string(8) "30000157"
            ["typeID"]=>
            string(5) "11489"
            ["quantity"]=>
            string(1) "1"
            ["flag"]=>
            string(1) "0"
            ["singleton"]=>
            string(1) "1"
          }
          [1]=>
          object(PhealRowSetRow)#18 (7) {
            ["itemID"]=>
            string(9) "290900396"
            ["locationID"]=>
            string(8) "66002198"
            ["typeID"]=>
            string(2) "27"
            ["quantity"]=>
            string(1) "1"
            ["flag"]=>
            string(2) "71"
            ["singleton"]=>
            string(1) "1"
            ["contents"]=>
            object(PhealRowSet)#24 (15) {
              [0]=>
              object(PhealRowSetRow)#29 (5) {
                ["itemID"]=>
                string(13) "1003305129036"
                ["typeID"]=>
                string(4) "2183"
                ["quantity"]=>
                string(1) "4"
                ["flag"]=>
                string(3) "117"
                ["singleton"]=>
                string(1) "0"
              }
              **cropped**
            }
          }
          **cropped**
         }
        }
       }
      }

特别注意嵌套的工作方式。顶级行集被命名为“资产”,但其中的每个项目都可以有“内容”。其中的每个项目也可以有一个“内容”列表。就 EVE 而言,它可以走多远是有限制的,但这个限制是未知的,代码应该假设没有真正的限制。

我对位于http://php.net/manual/en/language.types.array.php 上的代码 sn-ps 进行了一些尝试,目前该代码似乎已关闭。

    function array_value_recursive($key, array $arr){
        $val = null;
        array_walk_recursive($arr, function($v, $k) use($key, &$val){
            $val = $k == $key ? $v : (!is_null($val) ? $val : false);
        });
        return $val;
    }

鉴于我不知道它有多深,我似乎无法理解如何使用对象/数组。我如何知道我在对象/数组中的深度以及如何访问包含的数据。预先感谢您的时间和帮助。

下面的代码是我在知道可能存在无穷无尽的嵌套“内容”之前使用的代码。我已包含此代码,因此您可以看到我要完成的工作。

try { 
            $corpPheal = new Pheal($fullUserID, $fullAPIKey, "corp");

                $corpAssetList = $corpPheal->AssetList(array('characterID'=>$fullCharID));

                echo "<pre>";
                var_dump($corpAssetList);
                echo "</pre>";


        }
        catch (PhealException $e) {
            echo 'error: ' . $e->code . ' meesage: ' . $e->getMessage();
        }

        $numOfAssetList = count($corpAssetList->assets);


        for ($i =0; $i <= ($numOfAssetList -1); $i++){

            $numOfAssetContents = count($corpAssetList->assets[$i]->contents);
            echo $numOfAssetContents . "<br>\n";

            if ($numOfAssetContents > 0){
                $count = 0;
                for ($j=0; $j <= ($numOfAssetContents - 1); $j++){
                    echo "i = $i, j = $j <br>\n";
                    $count++;
                    foreach ($corpAssetList->assets[$i]->contents[$j] as $key => $value){

                        switch ($key) {
                            case "itemID":
                                $qry = "INSERT INTO eve_asset_list(`itemID`, `typeID`, `quantity`, `flag`, `singleton`) VALUES('$value','";
                                break;

                            case "typeID":
                                $qry = $qry . $value . "','";
                                break;
                            case "quantity":
                                $quantity = $value;
                                $qry = $qry . $value . "','";
                                break;
                            case "flag":
                                $qry = $qry . $value . "','";
                                break;
                            case "singleton":
                                $qry = $qry . $value . "') ON DUPLICATE KEY UPDATE quantity = $quantity";
                                break;
                        }
                    }

                    $result = mysql_query($qry);
                    include "./includes/mysqlError.inc.php";
                }
            }else {

                foreach ($corpAssetList->assets[$i] as $key => $value){

                        switch ($key) {
                            case "itemID":
                                $qry = "INSERT INTO eve_asset_list(`itemID`, `typeID`, `quantity`, `flag`, `singleton`) VALUES('$value','";
                                break;

                            case "typeID":
                                $qry = $qry . $value . "','";
                                break;
                            case "quantity":
                                $quantity = $value;
                                $qry = $qry . $value . "','";
                                break;
                            case "flag":
                                $qry = $qry . $value . "','";
                                break;
                            case "singleton":
                                $qry = $qry . $value . "') ON DUPLICATE KEY UPDATE quantity = $quantity";
                                break;
                        }
                    }

            }
        }

【问题讨论】:

  • 是递归的概念困扰着你还是如何用 php 做到这一点?
  • 我不明白如何使递归发生,因此当我编写 mysql 语句时,我将使用数组/对象中 x 位置的数据。最初我不知道对象/数组可以继续深入增长并使用多个嵌套的 for 语句,但这种方法会非常臃肿。我知道答案是使用递归来获得我正在寻找的结果,但我不太明白我如何知道我在哪里以及如何获取我所在位置的数据。我确实将递归的概念理解为调用自身的函数。

标签: php arrays object recursion nested


【解决方案1】:

您的代码 sn-p 现在所做的是将函数应用于每个元素 array_walk_recursive。这是 PHP 中的预定义函数。

现在应用的函数检查当前键是否等于作为参数给出的键。如果它们相等,则存储该值,否则不存储。

最终返回第一个找到的值。这个返回值可以是一个数组本身,你可以用它来访问内部数据。

目前它对数据的深度没有任何作用。这是你想要改变的吗?如果是,您希望该功能做什么?

编辑:

你可能需要类似的东西

function insert_all($pheal_row_set)
{
    foreach($pheal_row_set as $pheal_row_set_row)
    {
        foreach($pheal_row_set_row as $key => $value)
        {
            //switch statment
        }
        //insert
        if(!is_null($pheal_row_set_row['contents']) &&
            is_array($pheal_row_set_row['contents']))
        {
            insert_all($pheal_row_set_row['contents']);
        }
    }
}

【讨论】:

  • 我已经编辑了我的 OP,以便我可以向您展示我正在努力完成的工作。现在鉴于我不太了解这种级别的编码,所以我的下一个陈述可能是不正确的。我认为我不需要关心我有多深,只要我能得到位于那个深度的数据。
  • 我进行了编辑。如果您需要更多解释,请询问。我保留了您提供的对象的名称,因此请注意 $pheal_row_set$pheal_row_set_row 之间的区别
  • 我不确定这个函数是否考虑到“内容”可能包含项目和“内容”。必须添加所有项目。如果遇到“内容”,则必须添加其项目,如果具有“内容”,则必须以相同的方式评估它们。您的解决方案非常接近,我正在尝试完全理解它并对其进行修改以产生正确的结果。我正在加分您的回答,因为您从技术上回答了标题问题。
  • 如果你能输入类似if (is_array($pheal_row_set_row) || is_object($pheal_row_set_row)){ //Switch }else{ foreach($pheal_row_set_row as $key =&gt; $value) { //switch statment }}的代码,我会标记为正确的。我希望这个编辑有意义。如果它没有让我知道,我将编辑您的帖子以反映必要的更改
  • 我将is_array 放在递归调用的保护中。我认为结构不需要更多。 PhealRowSetPhealRowSetRows 的数组。所以这些都被遍历了。使用这样的行构建插入查询,如果该行在其内容中包含PhealRowSet,则对其执行相同的操作。也许在这种情况下使用instance of 会更整洁。
猜你喜欢
  • 2015-03-23
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2014-12-23
相关资源
最近更新 更多