首页 > 解决方案 > PHP循环遍历数组,查找匹配并附加属性

问题描述

如果找到匹配项,我需要检测当前 URL 并为其设置一个附加属性,所以目前我正在循环遍历该对象,如果未找到匹配项并且当前属性是一个数组,则将该数组传递给它自己。

所以我无法知道我在对象中的哪个位置来设置属性,我需要以某种方式保留键的引用吗?所以我可以设置 objects 属性。

示例对象:

$example = [
    'home' => [
        'link' => 'index.php',
        'code' => 'home',
        'label' => 'Home'
    ],
    'cars' => [
        'link' => 'javascript:void(0)',
        'code' => 'used-cars',
        'label' => 'Used Cars',
        'void' => true,
        'subpages' => [
            [
                'link' => 'used-cars',
                'code' => 'used-cars',
                'label' => 'View all cars'
            ]
        ],
        'brands' => [
            'used' => [
                [
                    'link' => "/used/cars/audi",
                    'code' => "used-audi",
                    'label' => "Audi"
                ],
                [
                    'link' => "/used/cars/bmw",
                    'code' => "used-bmw",
                    'label' => "BMW"
                ],
                [
                    'link' => "/used/cars/chevrolet",
                    'code' => "used-chevrolet",
                    'label' => "Chevrolet"
                ]
            ]
        ]
    ]
];

因此,例如,假设我目前正在使用“二手车/汽车/奥迪”。上面包含它的数组link应该如下所示:

[
    'link' => "/used/cars/audi",
    'code' => "used-audi",
    'label' => "Audi"
    'current' = true
]

这是我目前拥有的代码,如何在循环期间将属性添加到对象内的正确位置?

private function findCurrent($links) {

    $request_uri = explode("?", $_SERVER['REQUEST_URI'])[0];
    if ($request_uri === '') {
        $request_uri = '/index.php';
    }

    foreach ($links as $key => $value) {

        if (isset($value) && $value == $request_uri) {

            // Set as current

            break;
        }

        // No match, but does it have children!?
        if (is_array($value)) {
            $this->findCurrent($value);
        }
    }
}

标签: php

解决方案


一个问题是该行:$value == $request_uri-> 因为'void' => true将完成该惰性比较。将其更改为

$value == $request_uri

第二:如果要从函数内部和 foreach 循环内部更改数组,则需要通过引用传递它

这是您的功能的一个版本,它可以按照我的预期工作:

                // this '&' is important to pass the array as reference
function findCurrent(&$links) {
                               // dummy-data here for testing
    $request_uri = explode("?", "/used/cars/audi?test")[0];
    // original: $request_uri = explode("?", $_SERVER['REQUEST_URI'])[0];
    if ($request_uri === '') {
        $request_uri = '/index.php';
    }
                        // again, use $value as reference
    foreach ($links as $key => &$value) {
        #echo "now in $key<br>";

        if (isset($value) && $value === $request_uri) {
            // we found the correct entry, so return true
            return true;
        }

        // No match, but does it have children!?
        if (is_array($value)) {
            // if we found the link in this array,...
            if(findCurrent($value)) {
                // add the flag 'current'
                $value['current'] = true;   
                // and get out of the function
                return true;
            }
        }
    }
}

$success = findCurrent($links);

// testing if that array has changed as intended:
var_dump($links['cars']['brands']['used'][0]);

//  array(4) { 
//      ["link"]=> string(15) "/used/cars/audi" 
//      ["code"]=> string(9) "used-audi" 
//      ["label"]=> string(4) "Audi" 
//      ["current"]=> bool(true) 
//  }

推荐阅读