【问题标题】:Access array using dynamic path使用动态路径访问数组
【发布时间】:2013-10-02 11:08:39
【问题描述】:

我在访问 php.ini 中的数组时遇到问题。

$path  = "['a']['b']['c']";
$value = $array.$path;

在上面的代码中,我有一个名为 $array 的多维数组。

$path 是我从数据库中获取的动态值。

现在我想使用 $path 从 $array 中检索值,但我做不到。

$value = $array.$path

还给我

Array['a']['b']['c']

而不是值。

我希望我已经正确解释了我的问题。

【问题讨论】:

  • 试试 $value = $array[$path];
  • 我试过了,但它会解释类似 $array[['a']['b']['c']] 的东西。所以它对我不起作用
  • $path = ['a']['b']['c'] 不是有效的 PHP 语法。是字符串吗?
  • 这不是一个有效的语法,对不起
  • 是的,那是一个字符串。抱歉语法错误,但它类似于 $path = "['a']['b']['c']";

标签: php arrays dynamic


【解决方案1】:

你有两个选择。首先(邪恶)如果使用eval() 函数 - 即将您的字符串解释为 code

其次是解析你的路径。那将是:

//$path = "['a']['b']['c']";
preg_match_all("/\['(.*?)'\]/", $path, $rgMatches);
$rgResult = $array;
foreach($rgMatches[1] as $sPath)
{
   $rgResult=$rgResult[$sPath];
}

【讨论】:

  • 一个小的改进是使用\[(\"|')(.*?)(\1)\]$rgMathces[2]
  • 您的代码以垂直方式工作,首先是 $rgResult['a'],然后是 $rgResult['b'],然后是 $rgResult['c']。我想要 $rgResult['a']['b']['c']
  • @ExplosionPills 实际上,我的代码只是用于解析想法的示例。实际情况可能更复杂(例如$path = "[$a[$b][$c[$d]]][$e]" e t.c.)
  • 确实如此。非常感谢您的努力,但这并不能解决我的问题。 :(
  • @AbhishekSanghvi 没有。因为每次$rgResult 都会被自己覆盖,它将直接按照您的需要进行操作。如果它不能解决您的问题 - 那么,请澄清问题所在
【解决方案2】:

Kohana framework "Arr" class (API) 有一个方法 (Arr::path) 可以执行与您的请求类似的操作。它只需要一个数组和一个路径(以. 作为分隔符)并在找到时返回值。您可以修改此方法以满足您的需要。

public static function path($array, $path, $default = NULL, $delimiter = NULL)
{
    if ( ! Arr::is_array($array))
    {
        // This is not an array!
        return $default;
    }

    if (is_array($path))
    {
        // The path has already been separated into keys
        $keys = $path;
    }
    else
    {
        if (array_key_exists($path, $array))
        {
            // No need to do extra processing
            return $array[$path];
        }

        if ($delimiter === NULL)
        {
            // Use the default delimiter
            $delimiter = Arr::$delimiter;
        }

        // Remove starting delimiters and spaces
        $path = ltrim($path, "{$delimiter} ");

        // Remove ending delimiters, spaces, and wildcards
        $path = rtrim($path, "{$delimiter} *");

        // Split the keys by delimiter
        $keys = explode($delimiter, $path);
    }

    do
    {
        $key = array_shift($keys);

        if (ctype_digit($key))
        {
            // Make the key an integer
            $key = (int) $key;
        }

        if (isset($array[$key]))
        {
            if ($keys)
            {
                if (Arr::is_array($array[$key]))
                {
                    // Dig down into the next part of the path
                    $array = $array[$key];
                }
                else
                {
                    // Unable to dig deeper
                    break;
                }
            }
            else
            {
                // Found the path requested
                return $array[$key];
            }
        }
        elseif ($key === '*')
        {
            // Handle wildcards

            $values = array();
            foreach ($array as $arr)
            {
                if ($value = Arr::path($arr, implode('.', $keys)))
                {
                    $values[] = $value;
                }
            }

            if ($values)
            {
                // Found the values requested
                return $values;
            }
            else
            {
                // Unable to dig deeper
                break;
            }
        }
        else
        {
            // Unable to dig deeper
            break;
        }
    }
    while ($keys);

    // Unable to find the value requested
    return $default;
}

【讨论】:

    【解决方案3】:

    我希望找到一个优雅的嵌套数组访问解决方案,而不会引发未定义的索引错误,这篇文章在谷歌上很受欢迎。我参加聚会迟到了,但我想为未来的访客权衡一下。

    一个简单的isset($array['a']['b']['c'] 可以安全地检查嵌套值,但您需要提前知道要访问的元素。我喜欢用点表示法来访问多维数组,所以我自己写了一个类。它确实需要 PHP 5.6。

    该类解析以点表示法编写的字符串路径,并安全地访问数组或类数组对象的嵌套值(实现 ArrayAccess)。如果没有设置,它将返回值或NULL。

    use ArrayAccess;
    
    class SafeArrayGetter implements \JsonSerializable {
    
    /**
     * @var array
     */
    private $data;
    
    /**
     * SafeArrayGetter constructor.
     *
     * @param array $data
     */
    public function __construct( array $data )
    {
        $this->data = $data;
    }
    
    /**
     * @param array $target
     * @param array ...$indices
     *
     * @return array|mixed|null
     */
    protected function safeGet( array $target, ...$indices )
    {
        $movingTarget = $target;
    
        foreach ( $indices as $index )
        {
            $isArray = is_array( $movingTarget ) || $movingTarget instanceof ArrayAccess;
            if ( ! $isArray || ! isset( $movingTarget[ $index ] ) ) return NULL;
    
            $movingTarget = $movingTarget[ $index ];
        }
    
        return $movingTarget;
    }
    
    /**
     * @param array ...$keys
     *
     * @return array|mixed|null
     */
    public function getKeys( ...$keys )
    {
        return static::safeGet( $this->data, ...$keys );
    }
    
    /**
     * <p>Access nested array index values by providing a dot notation access string.</p>
     * <p>Example: $safeArrayGetter->get('customer.paymentInfo.ccToken') ==
     * $array['customer']['paymentInfo']['ccToken']</p>
     *
     * @param $accessString
     *
     * @return array|mixed|null
     */
    public function get( $accessString )
    {
        $keys = $this->parseDotNotation( $accessString );
    
        return $this->getKeys( ...$keys );
    }
    
    /**
     * @param $string
     *
     * @return array
     */
    protected function parseDotNotation( $string )
    {
        return explode( '.', strval( $string ) );
    }
    
    /**
     * @return array
     */
    public function toArray()
    {
        return $this->data;
    }
    
    /**
     * @param int $options
     * @param int $depth
     *
     * @return string
     */
    public function toJson( $options = 0, $depth = 512 )
    {
        return json_encode( $this, $options, $depth );
    }
    
    /**
     * @param array $data
     *
     * @return static
     */
    public static function newFromArray( array $data )
    {
        return new static( $data );
    }
    
    /**
     * @param \stdClass $data
     *
     * @return static
     */
    public static function newFromObject( \stdClass $data )
    {
        return new static( json_decode( json_encode( $data ), TRUE ) );
    }
    
    /**
     * Specify data which should be serialized to JSON
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
     * @return array data which can be serialized by <b>json_encode</b>,
     * which is a value of any type other than a resource.
     * @since 5.4.0
     */
    function jsonSerialize()
    {
        return $this->toArray();
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-18
      • 2019-09-13
      • 1970-01-01
      相关资源
      最近更新 更多