PHP: Getter & Setter

Quanti di voi hanno speso tempo e righe di codice per scrivere metodi che impostano e recuperano i valori delle proprietà definite un una classe? E quanti di voi hanno pensato: ma esiste un modo più semplice e veloce per farlo?

Con questo articolo vi mostrerò come utilizzare i “metodi magici” messi a disposizione da PHP5 per creare una semplice classe che implementa “automagicamente” i metodi getter e setter, aiutando lo sviluppatore nel semplificare la scrittura del codice per le proprie applicazioni web.

GetterSetter.php
<?php
 
/**
 * PHP5 Getter/Setter
 * 
 * @author  Giuseppe Di Terlizzi <[email protected]>
 */
class GetterSetter {
 
  public function __call($method, $arguments) {
 
    $property = lcfirst(substr($method, 3));
    $prefix   = strtolower(substr($method, 0,3));
 
    if ($prefix == 'set' && ! isset($arguments[0])) {
      trigger_error(sprintf('Missing argument 1 for %s::%s()', get_class($this), $method));
      return;
    }
 
    if (! property_exists(get_class($this), $property)) {
      trigger_error(sprintf('Undefined method %s::%s()', get_class($this), $method));
      return;
    }
 
    switch ($prefix) {
 
      case 'get':
        return $this->$property;
 
      case 'set':
        return $this->$property = $arguments[0];
 
    }
 
  }
 
  public function __get($property) {
    return call_user_func_array(array($this, 'get'.ucfirst($property)), array());
  }
 
  public function __set($property, $value) {
    return call_user_func_array(array($this, 'set'.ucfirst($property)), array($value));
  }
 
}

La classe GetterSetter è composta da solo 3 metodi ed adesso vi spiegherò brevemente che cosa fa:

  • Il metodo “magico” "__call", viene invocato per restiuire o impostare un valore della prorietà desiderata.
    • Una substring recupera il nome della proprietà togliendo i primi 3 caratteri.
    • La funzione “property_exists” verifica se la proprietà è definita nella classe. Nel caso non esiste, restiuisce un eccezione indicando che il metodo è inesistente.
    • Se stiamo settando una proprietà viene verificato se viene passato un valore come argomento. Nel caso non passiamo niente restiuisce un messaggio d'errore.
    • Un'altra substring recupera i primi 3 caratteri del metodo per capire se stiamo “recuperando” (get) o “impostando” (set) la proprietà.
  • I metodi "__get" e "__set" permettono di richiamare e settare le proprietà direttamente senza chiamare il relativo metodo get/set.

Adesso creiamo una classe che estende la classe GetterSetter e definiamo delle proprietà a piacere:

<?php
 
include 'GetterSetter.php';
 
class MyObject extends GetterSetter {
 
  public $foo = 'bar';
  public $bar = 'baz';
 
}

Adesso basta istanziare la classe e testarla:

<?php
 
$MyObject = new MyObject;
 
var_dump($MyObject->getFoo()); //string(3) "bar"
 
$MyObject->setFoo('foo');
 
var_dump($MyObject->getFoo()); //string(3) "foo"
 
var_dump($MyObject->bar); //string(3) "baz"
 
$MyObject->bar = 'bar';
 
var_dump($MyObject->bar); //string(3) "bar"

Come potete vedere dall'esempio possiamo accedere alla proprietà MyObject::$foo sia utilizzando il metodo “virtuale” ($MyObject→getFoo()) che direttamente ($MyObject→foo).

Cosa succede se tentiamo di recuperare o impostare una proprietà inesistente?

Nel caso in cui tentiamo di accedere ad una proprietà non definita verrà restituita un'eccezione.

$MyObject->getBaz();
 
//Notice: Undefined method MyObject::getBaz() in /home/lotar/www/GetterSetter.php on line 10

Se non passiamo nessun valore al metodo setXYZ, cosa succede?

Anche in questo caso viene restituito un messaggio d'errore indicando che il metodo richiamato non ha un argomento.

$MyObject->setBaz();
 
//Notice: Notice: Missing argument 1 for MyObject::setBaz() in /home/lotar/www/GetterSetter.php on line 10

Buona programmazione!

Enter your comment: