Das Problem, das Sie haben, betrifft Rekursion und/oder Baumtraversierung. PHP unterstützt die Baumtraversierung eines Arrays mit dem RecursiveArrayIterator
und RecursiveIteratorIterator
.
Um alle Schlüssel aller Elternarrays zu erhalten, müssen Sie von der ersten Ebene bis zur aktuellen Tiefe gehen und die Schlüssel erhalten. Dies wird auch vom RecursiveIteratorIterator
mit der Methode getSubIterator()
unterstützt. Es ist im Handbuch nicht wirklich gut dokumentiert, daher hier ein Beispiel:
$it = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array)
);
foreach ($it as $value) {
if ($value !== 'x') continue;
$keys = array();
$depth = $it->getDepth();
for ($i = 0; $keys[] = $it->getSubIterator($i)->key(), $depth--; $i++);
echo implode(', ', $keys), ', ', $value, "\n";
}
In diesem Beispiel wird zunächst der RecursiveArrayIterator
mit Ihrem $array
erstellt. Um die Baumtraversierung zu aktivieren, wird er in den RecursiveIteratorIterator
eingewickelt. Dies ist notwendig, um den $it
-Iterator rekursiv mit dem foreach
zu verwenden.
Im foreach
wird dann der Arraywert gegen Ihren Suchwert überprüft. Wenn er nicht übereinstimmt, wird mit dem nächsten Wert fortgefahren.
Wenn er jedoch übereinstimmt, werden die Methoden getDepth()
und getSubIterator()
des rekursiven Iterators verwendet, um das Schlüsselarray zu erstellen.
Das Beispiel gibt folgende Ausgabe aus:
Start, Element 1, Element 2_1, Element 2_1_1, x
Was Ihrer Beschreibung in der Frage entspricht.
Weil es sich um Iteratoren handelt, können Sie das auch in eine eigene Klasse implementieren. Die folgende Iterator
-Klasse ermöglicht nicht nur die Baumtraversierung über das im Konstruktor bereitgestellte Array, sondern hat auch eine Methode namens getKeys()
, die ein Array mit allen Schlüsseln vom niedrigsten Level bis zur aktuellen Tiefe zurückgibt:
/**
* Klasse ArrayRecursiveKeysIterator
*/
class ArrayRecursiveKeysIterator extends RecursiveIteratorIterator
{
/**
* @param array $array
*/
public function __construct(array $array)
{
parent::__construct(new RecursiveArrayIterator($array));
}
/**
* @return array Schlüssel
*/
public function getKeys()
{
for ($k = [], $i = 0, $m = $this->getDepth(); $i <= $m; $i++)
$k[] = $this->getSubIterator($i)->key();
return $k;
}
}
Es ist dann einfacher zu verwenden (und wahrscheinlich auch für andere Szenarien). Ein einfaches Anwendungsbeispiel zuerst. Gehen Sie durch das Array und zeigen Sie alle Schlüssel für jeden Wert an. Instantiieren Sie den Iterator für Ihr Array und geben Sie die Schlüssel für jeden Wert aus:
$it = new ArrayRecursiveKeysIterator($array);
foreach ($it as $value) {
echo implode(', ', $it->getKeys()), ', ', $value, "\n";
}
Dies erzeugt die folgende Ausgabe:
Start, Element 1, 0, Element 1_1
Start, Element 1, Element 2_1, Element 2_1_1, x
Start, Element 1, 1, Element 3_1
Start, 0, Element 2
Start, 1, Element 3
In Ihrem Szenario möchten Sie den Iterator auch basierend auf einem bestimmten Wert filtern (hier der Zeichenkette "x"
), was Sie ganz einfach durch die Verwendung des RegexIterator
, der ein FilterIterator
ist, tun können. Hier ist also Ihr Szenario:
$it = new ArrayRecursiveKeysIterator($array);
$filter = new RegexIterator($it, '~^x$~');
foreach ($filter as $value) {
echo implode(', ', $it->getKeys()), ', ', $value, "\n";
}
Und hier die Ausgabe:
Start, Element 1, Element 2_1, Element 2_1_1, x
Wie Sie sehen können, ist es nach dem Wert gefiltert, an dem Sie interessiert sind.
Weitere zugehörige Fragen, an denen Sie wahrscheinlich interessiert sind, sind: