Method chaining in PHP
Development PHP

Method chaining in PHP

Wat is method chaining

Method chaining is een syntax om meerdere methodes aan te roepen in object georiënteerde programmeer talen. Elke methode geeft een object terug met als resultaat dat de calls achter elkaar kunnen worden uitgevoerd zonder dat er variabeles zijn die tussendoor de uitkomst hoeven op te slaan. Bekende voorbeelden binnen laravel zijn bijvoorbeeld de QueryBuilder en de Collection. Hier onder een voorbeeld van de QueryBuilder.

SomeModel::where('first_name', $name)
    ->orWhere('last_name', '')
    ->first();

Hoe dan?

Het implementeren van method chaining in PHP is vrij simpel. In het onderstaande voorbeeld hebben we een class die geen method chainging heeft. De class kan op dit moment alleen nummers optellen en aftrekken.

class NoMethodChainingClass {
    protected $number = 0;
    
    public function addNumber($number_to_add) {
        $this->number += $number_to_add;
    }
    
    public function subtractNumber($number_to_subtract) {
        $this->number -= $number_to_subtract;
    }
    
    public function getNumber() {
        return $this->number;
    }
}

Als we met de bovenstaande code dus het nummer willen aanpassen door een van de methodes aan te roepen kan dat op de volgende manier:

$class = new NoMethodChainingClass();
$class->addNumber(5);
$class->subtractNumber(10);
echo $class->getNumber();

Door een aantal kleine aanpassingen te doen in de bestaande class kunnen we er echter voor zorgen dat de methodes achter elkaar ‘gechained’ kunnen worden. De methodes addNumber en subtractNumber moeten de class instance returnen. Hierdoor kunnen we gelijk op het nieuwe terug gegeven object doorgaan. Ook maken we de methodes en de variabele static. Hierdoor hoeven we niet in twee losse statements eerst de class instance aan te maken met $class = new MethodChainingClass() maar kunnen we gelijk op de MethodChainingClass beginnen met het aanroepen van methodes. We zouden de class ook niet static kunnen maken maar dan moet er dus wel altijd eerst een (nieuwe) instance van de class gemaakt worden, wat niet erg is maar soms wel vervelend kan zijn. De aangepaste class ziet er nu zo uit:

class MethodChainingClass {

    protected static $number = 0;
    
    public static function addNumber($number_to_add) {
        self::$number += $number_to_add;
        
        return new self;
    }
    
    public static function subtractNumber($number_to_subtract) {
        self::$number -= $number_to_subtract;
        
        return new self;
    }
    
    public static function getNumber() {
        return self::$number;
    }
}

Door gebruik te maken van deze nieuwe class kunnen we het bovenstaande voorbeeld versimpelen tot het onderstaande stukje code:

echo MethodChainingClass::addNumber(5)
    ->subtractNumber(10)
    ->getNumber();

Voor- en nadelen

Het klinkt allemaal erg leuk dat method chaining maar wat zijn nou de voor en nadelen? Persoonlijk gebruik ik method chaining alleen als ik op hetzelfde object blijf werken. Zodra ik iets anders terug krijg dan het object waarmee ik was begonnen maak ik eigenlijk altijd een nieuwe variabele aan. Dit zodat ik tussendoor kan testen of het nieuwe object wel bestaat of dat het juiste wordt terug gegeven. Als je dit niet doet kan je bijvoorbeeld op null objects proberen methodes uit te voeren waardoor je applicatie chrashed. Het zou dus foutgevoelliger kunnen zijn als je niet goed oplet. Daarnaast is het debuggen van method chaining niet altijd even goed ondersteund waardoor je bijvoorbeeld niet op de juiste plek je debug proces in kan. Daarintegen schrijf je over het algemeen wel een stuk minder code, zoals ook te zien was in het voorbeeld en is de code die je schrijft een stuk leesbaarder en daarmee ook gelijk een stuk beter onderhoudbaar.