2009-06-15 13 views
11

Occasionalmente scriverò una funzione PHP con un singolo input, un array associativo contenente tutti gli input di quella funzione. Ciò ha dei vantaggi, come non dover ricordare l'ordine corretto degli input, ma ho anche notato che rende molto più semplice implementare le modifiche a codebase di grandi dimensioni; quando ho bisogno di aggiungere un'altra variabile, e quella variabile deve passare attraverso 4 o 5 funzioni preesistenti, è molto più semplice quando posso semplicemente inserirla nell'array e trasferirla.Utilizzo di un array associativo come input della funzione php

La mia domanda è, c'è un lato negativo a fare questo?

Raramente vedo le funzioni scritte in questo modo negli esempi o nell'open source che uso, il che mi porta a credere che probabilmente c'è un aspetto negativo. Se il numero non è un motivo per non farlo, perché non scrivere tutte le funzioni in questo modo?

UPDATE

Grazie per tutte le vostre risposte. Sembra che due problemi principali spiccano:

la leggibilità del codice - impossibile dire quali variabili stanno andando in una funzione e quello che stanno per

scorrimento variabile - potrebbe finire con le matrici enormi che rimbalza da una funzione all'altra; non si devono passare parametri a funzioni che non li richiedono

Quali sono entrambi i punti importanti a cui non ho pensato.

Sembra che l'essenza generale sia che il codice in cui questo è un problema, dovrebbe probabilmente essere convertito in una classe. Sfortunatamente in questo specifico progetto un tale refactoring va oltre lo scopo, ma penso anche che la soluzione di Bill Karwin sia buona: passare una serie di variabili opzionali

+0

Fuori di interesse si può inserire una funzione di esempio si può scrivere? :) –

+0

@Shadi - più come "per curiosità morbosa"? :) –

+1

Così, invece di funzione myFunc ($ var1, var2 $, $ var3, $ var4 ...) {} avresti funzione myFunc ($ params) {} e quindi fare riferimento tramite $ params ['var1'], ecc. – thekevinscott

risposta

12

perché non scrivere tutte le funzioni in questo modo?

Per questo motivo, perché non dimenticare completamente i parametri e utilizzare le variabili globali per tutto? (Scherzo)

Passaggio di un array associativo ha un vantaggio utile: è possibile rendere più parametri funzione opzionale, e si può passare un valore per il parametro N th senza dover passare un valore per il * N-1 * th parametro.

Ma non si ha modo di rendere i parametri obbligatori con un errore in fase di compilazione se non li si passa. Né puoi dichiarare il controllo dei caratteri.

Dovrai scrivere il codice all'interno della funzione chiamata per verificare la presenza e il tipo di parametri richiesti.

Un'alternativa che ho usato è quella di dichiarare parametri convenzionali per quelli che sono obbligatori, e quindi come ultimo argomento (facoltativo), dichiarare un array associativo chiamato $options che contiene solo gli elementi opzionali.

function database_connect($dbname, $user, $password, array $options = array()) 
+0

* Né si può dichiarare il controllo dei tipi * - Potrebbe spiegare di più su come farlo? Ad esempio, nella tua funzione di esempio, possiamo digitare-check '$ password' per essere di stringa nella dichiarazione di funzione? Suppongo che tu intendessi controllarlo tipicamente all'interno della funzione stessa, giusto? – moey

+0

Intendevo il type-checking per 'array' o tipi di classi, dichiarate nella lista degli argomenti (quando ho scritto questo nel 2009, PHP non aveva controlli di tipo simili nella lista degli argomenti per i tipi scalari come string, int, float) . Se si utilizza un array di opzioni $, è necessario eseguire manualmente tutti i controlli di tipo nella propria funzione; non puoi farlo in modo dichiarativo. –

+0

Capito, grazie. PHP è ancora un linguaggio di tipo debole fino ad ora, no? Voglio dire che non puoi specificare il tipo di variabile, ad es. int, float, ecc. – moey

9

Lo svantaggio è che chiunque guarda il tuo codice (diverso da te) non avrebbe idea di quali parametri stanno entrando in un metodo, da dove provengono, o a cosa servono. Inoltre non avrebbero idea di come chiamare un metodo poiché non è chiaro senza guardare il codice esattamente ciò che è richiesto all'interno di tale "array di parametri".

+2

Questo è vero, solo se il programmatore non commenta o documenta nulla. – Spot

1

L'elencazione di ciascun parametro può aumentare la leggibilità del codice. Passare un singolo array associativo non necessariamente spiega quale tipo (i) di dati viene passato a una funzione.

1

Se dovessi rilevare la funzione e vedere che inizia semplicemente a fare riferimento ai valori di hash all'interno di un argomento a funzione singola, sarei un po 'confuso. Aiutare in modo esplicito le variabili e dare un po 'di documentazione all'interno di un docblock usando @param aiuta moltissimo. Dover aggiungere un argomento in due punti è un costo minore rispetto ai rendimenti degli argomenti di leggibilità.

2

presumibilmente uno degli svantaggi è che si finirà con troppi parametri. Questo porta al problema che il codice rischia di perdere la sua leggibilità.

In un rigoroso approccio orientato agli oggetti si converte tutti questi parametri che sono "passati attraverso" più chiamate di funzioni in istanze-variabili delle classi che detengono i metodi.

Non si devono mai passare parametri a funzioni che in realtà non sono necessarie.

+0

+1 - picchialo su di esso –

+0

Anche se avevi 'function foo ($ a, $ b) {...}' e solo '$ b' importava dal punto di vista del chiamante, potresti potenzialmente finire per passare un valore non necessario come primo parametro per conformarsi ai requisiti della funzione. – moey

0

Il più grande odore di codice qui è che l'aggiunta di un'altra variabile sarebbe cascata attraverso 4-5 diverse funzioni. Non riesco davvero a pensare a una ragione per cui questo dovrebbe accadere.

Sembra che sia necessario refactoring questo codice in una classe in modo che quindi è possibile passare i valori in un costruttore una volta e salvarli come variabili membro.

0

È molto più semplice generare documentazione se si hanno i parametri denominati e passati separatamente. Si potrebbe pensare che l'uso di un array faciliti l'aggiunta di un nuovo codice, ma il vantaggio non migliora la leggibilità. Inoltre, vai via dal tuo codice per 2 mesi e torna indietro ... capendo in quale ordine aggiungere parametri al tuo array in cui le situazioni diventeranno un enorme mal di testa.

2

Questa idea non è necessariamente così male, dato che in PHP manca la funzione "argomenti chiave" trovata in molti altri linguaggi di programmazione moderni (Python, Ruby, ecc.). Tuttavia, ci sono sicuramente alcuni problemi con esso:

  1. Se si modificano i parametri che una funzione accetta, allora è probabile che dovrete modificare un codice in cui si chiama in ogni caso, per abbinare i nuovi parametri.

  2. Se si utilizzano questi array in modo esteso e in molte chiamate di funzione si utilizza un array e semplicemente "si passa", potrebbe essere un segno che si dovrebbe pensare di trasformare alcuni di questi parametri in una classe strutturata.

  3. Se si utilizzano questi array come una struttura di dati mutabile, non si deve necessariamente sapere che l'array che si ha dopo aver chiamato la funzione è lo stesso di quello in cui si è passati. Questo probabilmente tornerà per ottenere a un certo punto.

0

In alcuni casi questo non ha senso mi sento, ma spesso è possibile semplificare le cose con la creazione di più metodi con leggermente diversi comportamenti. Il nome del metodo renderà quindi chiaro a cosa serve.

In generale, se le tue funzioni hanno> 3 argomenti diventerà comunque illeggibile.

In alternativa, uno schema utilizzato spesso sta trasformando il singolo argomento della funzione in oggetto (classificato). La 'classe parametro' definirà esattamente ciò che è supportato.

0

se il quetion è che il modo di dare un array come inputof la funzione, questa è la tua risposta:

<?php 
function city($input){ 
    $i=count($input['iran']); 
    $result=""; 
    for($b=1;$b<=$i;$b++){ 
     $result.='<div style="background:gold">'.$input['iran'][$b].'</div>'; 
     } 
     return $result; 
    } 
$cityName['iran'][1]="Tehran"; 
$cityName['iran'][2]="Qom"; 
$cityName['iran'][3]="MashHad"; 
$cityName['iran'][4]="Isfahan"; 
$cityName['iran'][5]="Shiraz"; 
$cityName['iran'][6]="Yazd"; 

echo city($cityName); 
?> 
1

io personalmente uso il seguente metodo:

  1. dichiarare il parametro come matrice nella definizione della funzione;

  2. stabilire un "valore predefinito" assoc. matrice;

  3. corrispondenza parametri passati con il valore predefinito in un parametro defin.array associare che utilizzo all'interno della funzione. A tale scopo, utilizzo la funzione param_default().

Seguendo questo metodo evito problemi di param obbligatorio e gestisco i valori di default; anche la possibilità di passare le chiavi in ​​qualsiasi ordine è molto comoda.

// default values fx. 
function param_default($def = array(), $parameters= array()){ 
    $parm_diff = array(); 
    $ak=array(); 
    $va=array(); 
    $parm = array(); 
    foreach($def as $key=>$values) if(!in_array($key, array_keys($parameters))){ 
     $ak[]=$key; 
     $va[]=$values; 
    } 
    $parm_diff = array_combine($ak,$va); 
    $parm = array_merge($parm_diff,$parameters); 
    unset($parm_diff, $ak,$va); 

    return $parm; 
} 

Quindi questo è un semplice esempio di utilizzo:

<?php 
// sample use 
function my_func($parameters = array()){ 
    $def = array(
     'first' => 1, 
     'second' => 'foo', 
     'third' => -1 
    ); 
    $parm = param_default($def, $parameters); 
    //hereon I can use my array 

    var_dump($param); 

    if ($param['second'] !=='foo'){ 
     echo 'Not foo!!'; 
     // whatever... 
    } 

    return true; 
} 
?> 

Esempio di emissione:

// calling my_fun() 

$example = my_func(array('second'=>'bar')); 

// results in 
$param array: 
'first' => 1, 
'second' => 'bar', 
'third' => -1 
0

creare la funzione:

function testing($argumentos) { 
    $var_1 = $argumentos['var_01']; 
    $var_2 = $argumentos['var_02']; 

    echo $var_1 . " " . $var_2; 
} 

Chiamare la funzione:

testing(array('var_01' => "mierda", 'var_02' => "conio!")); 

uscita:

mierda conio! 
Problemi correlati