Массив доступа с использованием динамического пути

У меня проблема с доступом к массиву в php.

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

В вышеприведенном фрагменте кода у меня есть многомерный массив с именем $ array.

$path – это динамическое значение, которое я получаю из базы данных.

Теперь я хочу получить значение из $ array, используя $ path, но я не могу.

 $value = $array.$path 

возвращает меня

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

а не значение.

Надеюсь, я правильно объяснил свой вопрос.

У вас есть два варианта. Первое (зло), если использовать функцию eval() т.е. интерпретировать вашу строку как код .

Во-вторых, нужно проанализировать ваш путь. Это будет:

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

Класс «Arr» класса Kohana (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; } 

Я надеялся найти изящное решение для вложенного доступа к массиву, не бросая неопределенные ошибки индекса, и этот пост попадает высоко в google. Я опаздываю на вечеринку, но я хотел взвесить для будущих посетителей.

Простой 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(); } }