2013-09-26 6 views
5

Ich habe ein Problem beim Zugriff auf das Array in PHP.Zugriff auf Array mit dynamischem Pfad

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

In dem obigen Stück Code habe ich eine mehrdimensionale Array namens $ Array.

$path ist ein dynamischer Wert, den ich von der Datenbank erhalten würde.

Jetzt möchte ich den Wert aus $ Array mit $ Pfad abrufen, aber ich bin nicht in der Lage.

$value = $array.$path 

gibt mir

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

eher als der Wert.

Ich hoffe, ich habe meine Frage richtig erklärt.

+0

versuchen $ value = $ array [$ pfad]; – Pupil

+0

Ich habe versucht, aber es interpretiert etwas wie $ array [['a'] ['b'] ['c']]. So funktioniert es nicht für mich –

+0

'$ path = ['a'] ['b'] ['c']' ist nicht gültig PHP-Syntax. Ist es eine Schnur? –

Antwort

11

Sie haben zwei Möglichkeiten. Erstens (böse), wenn eval() Funktion zu verwenden - d. H. Interpretieren Sie Ihre Zeichenfolge als Code.

Zweitens ist Ihren Weg zu analysieren. Das wird:

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

Eine kleine Verbesserung wäre die Verwendung von '\ [(\" | ') (. *?) (\ 1) \] 'und' $ rgMathces [2] ' –

+0

Ihr Code funktioniert in einer vertikalen Weise, die zuerst geht für $ rgResult ['a'] dann $ rgResult ['b'] und dann $ rgResult ['c']. Ich will $ rgResult ['a'] ['b'] ['c'] –

+0

@ExplosionPills Mein Code ist nur ein Beispiel für die Analyse der Idee.Die reale Situation könnte komplizierter sein (wie etwa $ path = "[$ a [$ b] [$ c [$ d]]] [$ e]" 'e t.c.) –

2

Die Kohana framework "Arr" class (API) hat eine Methode (Arr::path), der etwas tut, ähnlich dem, was Sie fordern. Es nimmt einfach ein Array und einen Pfad (mit einem . als Trennzeichen) und gibt den Wert zurück, falls gefunden. Sie können diese Methode Ihren Anforderungen anpassen.

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; 
} 
0

Ich hatte gehofft, eine elegante Lösung für den geschachtelten Array-Zugriff zu finden, ohne undefinierte Indexfehler zu werfen, und dieser Beitrag trifft hoch auf Google. Ich bin zu spät zur Party, aber ich wollte mich für zukünftige Besucher einbringen.

Eine einfache isset($array['a']['b']['c'] kann geschachtelte Werte sicher überprüfen, aber Sie müssen die Elemente kennen, auf die Sie im Voraus zugreifen können. Ich mag die Punktnotation für den Zugriff auf mehrdimensionale Arrays, also schrieb ich eine eigene Klasse. Es erfordert PHP 5.6.

Diese Klasse analysiert einen in Punktnotation geschriebenen Zeichenfolgenpfad und greift sicher auf die verschachtelten Werte des Arrays oder arrayähnlichen Objekts zu (implementiert ArrayAccess). Es wird den Wert oder NULL zurückgeben, wenn nicht festgelegt.

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(); 
} 
}