best practice per inizializzare i membri della classe in php


10

Ho un sacco di codice come questo nei miei costruttori: -

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

È meglio farlo piuttosto che specificare il valore predefinito nella definizione della proprietà? cioè public $property = default_val? A volte c'è una logica per il valore predefinito e alcuni valori predefiniti sono presi da altre proprietà, motivo per cui lo stavo facendo nel costruttore.

Dovrei usare setter in modo che tutta la logica per i valori predefiniti sia separata?

Risposte:


8

Ho avuto questo tipo di dibattito filosofico con me stesso prima. Ecco dove mi trovo la maggior parte del tempo anche se mi rendo conto che questa è una risposta basata sull'opinione:

Una cosa che vedo che potrebbe aiutare a rispondere alla domanda è il passaggio di $ params che possono o meno avere attributi / membri dell'array impostati.

Nel corso degli anni sono giunto a questa conclusione:

Evitare il passaggio di array.

Perché? Bene, non c'è modo di impostare o di definire valori sentinella per argomenti passati opzionali.

In altre parole, con il codice che hai specificato, non puoi fare qualcosa del genere:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 e $ arg2 sono argomenti opzionali - se non passati hanno rispettivamente NULL e DEFAULT_VAL - non è necessario controllare esplicitamente.

Forse questo sembra un po 'arbitrario.

Penso di ottenere ciò che stai cercando di realizzare: il passaggio di un singolo riferimento invece di tonnellate di argomenti. Questo mi porta alla mia prossima inclusione:

Se non passa variabili "atomiche" (stringhe, numeri interi, valori letterali), passa oggetti.

Qui ci sono vantaggi in termini di prestazioni poiché il passaggio di oggetti viene fatto per riferimento (anche se le matrici credo siano più o meno le stesse all'interno di PHP).

Quindi potresti fare qualcosa del tipo:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

L'argomento oggetto passato verrebbe quindi garantito per avere "proprietà1", "proprietà2" sebbene possibilmente con valori predefiniti stessi.

Inoltre, qui puoi digitare un suggerimento e un buon IDE eseguirà correttamente anche il completamento automatico del codice.

Ma ci rendiamo presto conto che abbiamo un pollo e un uovo in corso: stai costruendo un oggetto con argomenti oggetto passati che a loro volta hanno bisogno di essere costruiti.

Quindi dove ci lascia questo? Bene, sono giunto alla conclusione che alla fine tutte le classi si distillano, per mancanza di un termine migliore, variabili "atomiche" (stringhe, float, doppie, ints, risorse che ottieni il mio punto) e che tendo a provare per costruire tutte le classi con quei tipi di variabili o oggetti, ma non array.

Quindi ho risposto alla tua domanda? probabilmente non esattamente. Ma spero di aver illustrato qualcosa di utile seppur in qualche modo stilistico. Penso che il codice sia un po 'più pulito, più leggibile e meno costoso.

Ora, questo non vuol dire che non dovresti disinfettare i tuoi input. Questa è un'altra discussione del tutto.

Spero che sia di aiuto.


1
È un buon punto e molto utile per i prompt IDE ma ci sono troppe proprietà dell'oggetto per passarle tutte come parametri. Se hai 7 argomenti, diciamo 5 dei quali sono opzionali, new object($param1,-some default value so I can specify the next parameter-, $param3);
finisci

3

Anche se tendo ad evitare il passaggio di matrici a un costruttore, a volte trovo necessario elaborare un valore di matrice in entrata (ad esempio per una classe che legge valori da un file di configurazione).

In un caso come questo, approfitterò delle funzioni dell'array di PHP per assicurarmi di lavorare esattamente con ciò che penso di lavorare:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

L'ultima riga utilizza array_merge()per sovrascrivere tutti i valori $defaultscon i loro valori corrispondenti da $incoming. Uso anche array_intersect_key()per garantire che l'array risultante non contenga chiavi extra che la classe / metodo non saprebbero come elaborare.


Ciao, qual è il comportamento se $ defaults contiene un array invece di semplici variabili?
Pol Dellaiera,

@PolDellaiera Guarda array_merge_recursive.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.