2016-02-22 13 views
6

Ho alcune configurazioni predefinite e alcune configurazioni specifiche che potrebbero essere configurate. Ho bisogno di unire le configurazioni specifiche nelle configurazioni predefinite.PHP array_replace_recursive se scalare, array_merge_recursive se array

  • Nel caso in cui l'opzione di configurazione specifica non esiste, verrà utilizzata l'opzione predefinita .
  • Nel caso in cui il value è uno scalare, la configurazione specifica deve essere applicato
  • Nel caso in cui il value è una matrice scalari, gli array dovrebbero essere unificati e array_unique applicati.
  • Nel caso in cui lo value sia un array associativo, è necessario applicare le precedenti regole scalar e scalar_array.

Esempio:

$defaultConfigs = [ 
    'scalar1' => 1, 
    'scalar2' => "Apple", 
    'array_scalar' => [3,4,5], 
    'array_associative' => [ 
     'scalar' => 1, 
     'array_scalar' => [1,2,3], 
     'array_associative' => [ 
      ... 
     ] 
    ], 
]; 

$specificConfigs = [ 
    'scalar1' => "A",       
    'array_scalar' => [3,4,5], 
    'array_associative' => [ 
     'scalar' => 1, 
     'array_scalar' => [1,2,3], 
     'array_associative' => [ 
      ... 
     ] 
    ], 
]; 

Output previsto:

$expectedConfigs = [ 
    'scalar1' => "A",     // Overridden 
    'scalar2' => "Apple",    // Default used 
    'array_scalar' => [1,2,3,4,5],  // Scalar merged and array_unique 
    'array_associative' => [ 
     'scalar' => "B",    // Overridden 
     'array_scalar' => [1,2,3,4,5], // Scalar merged and array_unique 
     'array_associative' => [ 
      ... 
     ] 
    ], 
]; 

C'è un bel modo pulito per ottenere questo risultato?

+0

Questo è interessante, se ho capito, stai provando qualcosa come i file di configurazione di SublimeText (solo per renderlo chiaro)? – Asur

+0

Penso che tu l'abbia capito esattamente – Gravy

+0

Vorrei andare con una funzione ricorsiva personalizzata, perché potresti avere bisogno di più funzioni di quante possano avere le funzioni ricorsive di PHP. Ma comunque personalmente lo trovo completamente ok. – Asur

risposta

1

Il mio caso era leggermente diverso ma potrebbe essere di aiuto. Avevo bisogno di sostituire gli scalari e array_merge_recursive sugli array.

class ArrayUtil { 

    public static function mergeRecursive(array $array1, $array2) { 
     if($array2 && is_array($array2)) { 
      foreach($array2 as $key => $val2) { 
       if (is_array($val2) && (null!==($val1 = isset($array1[$key]) ? $array1[$key] : null)) && is_array($val1)) { 
        $array1[$key] = self::mergeRecursive($val1,$val2); 
       } else { 
        $array1[$key] = $val2; 
       } 
      } 
     } 
     return $array1; 
    } 
} 
1

Questa funzione consente di ottenere il risultato desiderato. Assumono che tipi specifici siano coerenti con i tipi predefiniti, quindi non viene eseguito alcun controllo di coerenza. La funzione itera l'array di configurazione specifico e controlla il valore di default corrispondente : se è scalare, sostituire il valore predefinito; se si tratta di un array enumerato , unisce i valori univoci; altrimenti la funzione chiama se stessa con valori correnti come argomenti.

function fillConfig($default, $specific) 
{ 
    foreach($specific as $key=> $val) 
    { 
     if(isset($default[$key])) 
     { 
      if(! is_array($default[$key])) 
      { 
       $default[$key] = $val; 
      } 
      elseif(array_keys($default[$key]) === range(0, count($default[$key]) - 1)) 
      { 
       $default[$key] = array_unique(array_merge($default[$key], $val)); 
      } 
      else 
      { 
       $default[$key] = fillConfig($default[$key], $val); 
      } 
     } 
     else 
     { 
      // This happens when a specific key doesn't exists in default configuration. 
      // I think that in this case the value must be omitted, 
      // otherwise you can un-comment following line: 
      // $default[$key] = $val; 
     } 
    } 
    return $default; 
} 

Chiamando la funzione in questo modo:

$result = fillConfig($defaultConfigs, $specificConfigs); 

$result, applicato al vostro campione array, è questa:

Array 
(
    [scalar1] => A 
    [scalar2] => Apple 
    [array_scalar] => Array 
     (
      [0] => 3 
      [1] => 4 
      [2] => 5 
     ) 
    [array_associative] => Array 
     (
      [scalar] => 1 
      [array_scalar] => Array 
       (
        [0] => 1 
        [1] => 2 
        [2] => 3 
       ) 
      [array_associative] => Array 
       (
       ) 
     ) 
) 

Con questa coppia matrice:

$defaultConfigs = [ 
    'scalar1' => 1, 
    'scalar2' => "Apple", 
    'array_scalar' => [3,4,5], 
    'array_associative' => [ 
     'scalar' => 1, 
     'array_scalar' => [1,2,3], 
     'array_associative' => [ 

     ] 
    ], 
]; 

$specificConfigs = [ 
    'scalar1' => "A",       
    'array_scalar' => [3,4,5], 
    'array_associative' => [ 
     'scalar' => B, 
     'array_scalar' => [3,4,5], 
     'array_associative' => [ 

     ] 
    ], 
]; 

$result è:

Array 
(
    [scalar1] => A 
    [scalar2] => Apple 
    [array_scalar] => Array 
     (
      [0] => 3 
      [1] => 4 
      [2] => 5 
     ) 

    [array_associative] => Array 
     (
      [scalar] => B 
      [array_scalar] => Array 
       (
        [0] => 1 
        [1] => 2 
        [2] => 3 
        [4] => 4 
        [5] => 5 
       ) 

      [array_associative] => Array 
       (
       ) 

     ) 

) 

Note:

Sì, questo è un po 'incoerente: ho sentito è stato meglio Scorrere matrice specifica (non oggetti esistenti rimangono intatte), ma l'esecuzione di controllo del valore sulla matrice predefinita, questo è il punto di riferimento.

Il controllo di matrice enumerato/associativo è basato su this answer.