Többdimenziós tömbök értékeinek szelektív lekérdezése php-ban

Az ötletet a különböző keretrendszerekben megtalálható hasonló metódusok adták, amik adatbázisból lekérdezett eredményhalmaz átrendezésére használhatók. A különböző rekordokat egy kétdimenziós tömbben is visszakaphatjuk, ami vagy numerikusan indexelt, vagy valamelyik adott oszlop értéke szerint. Például felhasználó azonosítója. Az összetett kulcsok által indexelésre viszont ezek sem adnak megoldást. Továbbá vannak olyan helyzetek, amikor egy tömbből konkrét indexekhez ( oszlopokhoz ) tartozó értékekre van szükség és csak azokra. Erre talán azt tudnám példaként említeni, amikor egy nem általunk írt függvény az átadott összes tömbelemet feldolgozza. Ezeken túl a következő függvény a nem létező indexekhez tartozó értékeket figyelmen kívül hagyja.

Példa tömb:

$array = array(
        4 => array('id' => 1, 'name' => 'Takács Ákos','age' => 25),
        8 => array('id' => 345, 'name' => 'Kovács Géza', 'age' => 31),
        1 => array('id' => 13, 'name' => 'Tóth Töhötöm', 'age' => 12),
        56 => array('id' => 98, 'name' => 'Teszt Eszter', 'age' => 43)
);

Példa select lista készítéséhez

<?php
$persons = fetch($array, 'name', 'id');
?>
<select name="persons">
<?php foreach ($persons as $id => $name) : ?>
        <option value="<?php echo (int)$id; ?>"><?php echo htmlspecialchars($name); ?></option>
<?php endforeach; ?>
</select>

Eredmény:

<select name="persons">
        <option value="1">Takács Ákos</option>
        <option value="345">Kovács Géza</option>
        <option value="13">Tóth Töhötöm</option>
        <option value="98">Teszt Eszter</option>
</select>

További példák a használatára:

Csak ID-k lekérdezése: var_dump(fetch($array,'id'));
Eredmény:

array
  0 => int 1
  1 => int 345
  2 => int 13
  3 => int 98

Csak ID lekérdezése indexelt tömbként: var_dump(fetch($array, array('id')));
Eredmény:

array
  0 =>
    array
      'id' => int 1
  1 =>
    array
      'id' => int 345
  2 =>
    array
      'id' => int 13
  3 =>
    array
      'id' => int 98

ID-k és nevek lekérdezése: var_dump(fetch($array, array('id','name')));
Eredmény:

array
  0 =>
    array
      'id' => int 1
      'name' => string 'Takács Ákos' (length=13)
  1 =>
    array
      'id' => int 345
      'name' => string 'Kovács Géza' (length=13)
  2 =>
    array
      'id' => int 13
      'name' => string 'Tóth Töhötöm' (length=16)
  3 =>
    array
      'id' => int 98
      'name' => string 'Teszt Eszter' (length=12)

Összetett indexek ( id és kor ): var_dump(fetch($array, null, array('id','age')));
Eredmény:

array
  '1-25' =>
    array
      'id' => int 1
      'name' => string 'Takács Ákos' (length=13)
      'age' => int 25
  '345-31' =>
    array
      'id' => int 345
      'name' => string 'Kovács Géza' (length=13)
      'age' => int 31
  '13-12' =>
    array
      'id' => int 13
      'name' => string 'Tóth Töhötöm' (length=16)
      'age' => int 12
  '98-43' =>
    array
      'id' => int 98
      'name' => string 'Teszt Eszter' (length=12)
      'age' => int 43

Persze hozzá kell tennem, ez nem működne olyan indexekkel, amik eleve tartalmazhatnak a $separator karakterrel megegyező karaktert. Olyankor vagy másik elválasztót kell megadni, vagy a függvény hibás eredményt adhat. Például "X-Y" és "Z" összefűzése ugyanaz, mint "X" és "Y-Z" összefűzése.

A függvény:

/**
 * Többdimenziós tömbök értékeinek szelektív lekérdezése
 *
 * @param array $array
 *              A tömb, amiből az adatokat ki kell nyerni
 * @param mixed $valueIndexes
 *              A lekérendő értékek indexeinek tömbje, ha tömbként várjuk vissza az eredményt is
 *              Vagy csak egy érték indexe stringként. Akkor az eredményt sem tömbként kapjuk.
 *              Elhagyása esetén az összes érték le lesz kérdezve.               
 * @param mixed $keyValues
 *              Az eredményhalmaz indexelésére szolgáló "oszlopnevév". Vagy tömbként
 *              megadva több "oszlopnevet" azok együttesen azonosítják az eredményhalmaz
 *              elemeit a $separator paramétert használva elválasztóként
 * @param string $separator
 *              Tömbként megadott $keyValues paraméter esetén az egyes indexeket ez
 *              választja el.
 * @return array
 *              A kinyert eredményhalmaz tömbje
 */
           
function fetch(array $array, $valueIndexes = null, $keyIndexes = null, $separator = '-')
{
        $results = array();
       
        $asArray = true;
       
        if (is_null($keyIndexes)) {
                $keyIndexes = array();
        }
        if (!is_array($keyIndexes)) {
                $keyIndexes = array($keyIndexes);
        }
        if (is_null($valueIndexes)) {
                $valueIndexes = array();
        }
        if (!is_array($valueIndexes)) {
                $valueIndexes = array($valueIndexes);
                $asArray = false;
        }
       
        if (!$keyIndexes and !$valueIndexes) { //egyik sincs megadva
                $results = array_values($array);
        } else         
        if (!$valueIndexes) { //Értékek indexe meghatározatlan. Összes kell
                foreach ($array as &$item) {
                        $indexes = array();
                        foreach ($keyIndexes as &$index) {
                                if (!isset($item[$index])) continue;
                                $indexes[] = $item[$index];
                        }
                        $results[implode($separator, $indexes)] = $item;
                }
        } else
        if (!$keyIndexes) { //kulcsok indexe meghatározatlan. De az értékeké nem.
                foreach ($array as &$item) {
                        $values = array();
                        foreach ($valueIndexes as &$index) {
                                if (!isset($item[$index])) continue;
                                $values[$index] = $item[$index];
                        }
                        if (!$asArray) {
                                $values = isset($values[$index]) ? $values[$index] : array();
                        }
                        $results[] = $values;
                }      
        } else { //mindkettő meg lett adva.
                foreach ($array as &$item) {
                        $indexes = array();
                        foreach ($keyIndexes as &$index) {
                                if (!isset($item[$index])) continue;
                                $indexes[] = $item[$index];
                        }
                        $values = array();
                        foreach ($valueIndexes as &$index) {
                                if (!isset($item[$index])) continue;
                                $values[$index] = $item[$index];
                        }
                        if (!$asArray) {
                                $values = isset($values[$index]) ? $values[$index] : array();
                        }
                        $results[implode($separator, $indexes)] = $values;
                }      
        }
       
        return $results;
}
Kategóriák: 
Megosztás/Mentés

Hozzászólások

Gaál Tamás képe

Remek, pont erre van szükségem :)

Rimelek képe

Örülök, hogy 10 év után is segít valakinek egy cikkem :)