Comment appliquer ce design pattern en PHP ? Comment appeler une méthode à la fois statiquement et non?
Tout d'abord, qu'est-ce qu'une API fluide ?
Comme le dit wikipédia :
L'interface Fluent est une API orientée objet dont la conception repose largement sur le chaînage de méthodes. Son objectif est d'augmenter la lisibilité du code.
Par exemple, dans Laravel, vous pouvez créer une requête SQL à l'aide de la classe Eloquent DB (qui implémente l'API fluide) :
DB::table('users')->where('age', '>', 18)->limit(100)->orderBy('name')->get();
User::where('age', '>', 18)->limit(100)->orderBy('name')->get();
Avec l'API fluide, il est pratique d' appeler une méthode à la fois statiquement et non . Comme ça:
FluentMath::add(10)->subtract(3)->result();
FluentMath::subtract(3)->add(10)->result();
Dans l'exemple ci-dessus, vous pouvez voir que les méthodes add
et substract
ont été appelées à la fois statiquement et non.
Comment appeler une méthode non statique avec deux-points (::) Vous pouvez y parvenir en utilisant les méthodes magiques __call et __callStatic.
Comment les méthodes magiques __call
et __callStatic
fonctionnent?
Lorsque vous appelez une méthode statique qui n'existe pas, l'appel revient à la méthode __callStatic
.
class MagicStaticTest
{
public static function __callStatic($method, $args)
{
echo ' la méthode statistique a été retournée!<br>';
}
public static function definedMethod()
{
echo 'la méthode statistique a été retournée!</br>';
}
}
// Ça nous donne la méthode statistique a été retournée!
MagicStaticTest::definedMethod();
// Ça nous donne la méthode statistique a été retournée!
MagicStaticTest::notExistingMethod();
Il en va de même avec les appels non statiques : si vous invoquez une méthode non statique qui n'existe pas, l'appel revient à la fonction magique __call
.
class MagicTest
{
public function __call($method, $args)
{
echo 'l\' appelle revient à la méthode __call<br>';
}
public static function definedMethod()
{
echo 'la méthode definedMethod a été retournée!<br>';
}
}
$instance = new MagicTest;
$instance->definedMethod();
$instance->aMethodThatDoesNotExists();
Pour appeler une méthode à la fois statiquement et non statiquement, vous pouvez utiliser une astuce simple : vous pouvez utiliser les méthodes magiques __call
et __callstatic
router l'appel vers la méthode de votre choix.
Expliquons-le avec un exemple.
Supposons que nous voulions créer une API fluide pour ajouter ou soustraire une quantité à un nombre. Par exemple ce que nous voulons réaliser est ceci :
$res = FluentMath::add(5)
->subtract(2)
->add(8)
->result();
// $res is 5 - 2 + 8 = 11
Nous pouvons construire la FluentMathclasse comme ci-dessous :
class FluentMath
{
private $result = 0;
public function __call($method, $args)
{
return $this->call($method, $args);
}
public static function __callStatic($method, $args)
{
return (new static())->call($method, $args);
}
private function call($method, $args)
{
if (! method_exists($this , '_' . $method)) {
throw new Exception('Call undefined method ' . $method);
}
return $this->{'_' . $method}(...$args);
}
private function _add($num)
{
$this->result += $num;
return $this;
}
private function _subtract($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
Lorsque vous appelez statiquement,
FluentMath::add(10)
l'appel revient à la méthode __callStatic car la méthode add
n'existe pas. La méthode __callStatic vérifie si la méthode _add existe (avec un trait _de soulignement au début), puis elle appelle la méthode _add et enfin elle renvoie une nouvelle instance de classe.
Au lieu de cela, lorsque vous appelez une méthode non statique, par exemple
$instance->add(10)
, l'appel revient à la méthode magique __call* car la méthode add n'existe pas. Ensuite, la méthode __call vérifie si la méthode _add existe, puis elle appelle la méthode _add et enfin elle renvoie l'instance de classe.
Dans la FluentMathclasse, toutes les méthodes qui commencent par un trait de soulignement _ peuvent être appelées à la fois statiquement et non. De plus, ces fonctions peuvent également être enchaînées.
Vous pouvez utiliser la classe ci-dessous pour étendre d'autres classes afin de créer votre classe API fluide.
class FluentApi
{
public function __call($method, $args)
{
return $this->call($method, $args);
}
public static function __callStatic($method, $args)
{
return (new static())->call($method, $args);
}
private function call($method, $args)
{
if (! method_exists($this , '_' . $method)) {
throw new Exception('Call undefined method ' . $method);
}
return $this->{'_' . $method}(...$args);
}
}
Vous trouverez ci-dessous un exemple d'utilisation de la FluentApiclasse :
class FluentMath extends FluentApi
{
private $result = 0;
protected function _add($num)
{
$this->result += $num;
return $this;
}
protected function _subtract($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
Lorsque vous utilisez la FluentApiclasse, rappelez-vous que toutes les méthodes qui commencent par un trait de soulignement _ (comme _add
ou _subtract
dans l'exemple ci-dessus) peuvent être enchaînées et peuvent être appelées à la fois statiquement et non. _
code source
Nous voilà à la fin de l'article, ça été un gros challenge, ce pendant nous avons appris du moins comment créer et utiliser l'API fluide. N'oubliez pas de vous abonner et liker l'article les amis. 🙏 A la prochaine 👋👋!