Posts Tagged - hack

  • php

Instancier une classe qui n'existe pas en PHP

Vous voulez instancier une classe qui n’existe pas en PHP ? Hold my beer 🍺.

Un autoloader permet de dicter à PHP comment il doit s’y prendre afin d’instancier une nouvelle classe, en d’autres termes : vous avez le contrôle sur le comportement d’un “new”.

Une fois qu’on s’est dit ca, on peut s’imaginer faire quelques bêtises, par exemple, instancier une classe qui n’existe “pas” réellement.

Imaginez que votre projet possède une unique classe App\Foo et que vous souhaitez l’instancier à partir d’un FQCN quelconque … du genre Domain\Foo ?

Actuellement, cette instanciation lève une erreur, c’est normal, la classe Domain\Foo n’existe pas.

1
2
new Domain\Foo();
# Fatal error: Uncaught Error: Class "Foo" not found

À l’aide d’un autoloader, nous pouvons “attraper” cette instanciation en vol afin de la rediriger ailleurs :

1
2
3
4
5
6
7
8
9
10
spl_autoload_register(function ($class) {

    if (str_starts_with($class, 'Domain')) {

        $alias = str_replace('Domain', 'App', $class);

        return class_alias($alias, $class);
    }

}, true, true);

Ce code sera Ă  placer au plus haut de votre application, dans le cadre de Laravel, dans son fichier bootstrap/app.php.

Grace à cet autoloader, nous instancions désormais la classe Foo présente dans le namespace App/, il n’y a plus d’erreur, le code fonctionne … bien évidemment, évitez d’être contraint d’effectuer ce genre de trick périlleux, mais cela pourrait peut-être vous aider dans des situations très exotiques.

1
2
3
$foo = new Domain\Foo();
var_dump($foo);
# object(Foo)#1 (0) {}

PS : Créer un alias d’une classe inexistante lève un warning en PHP 8, mais entre nous, à ce niveau de magie noire, on s’en moque un petit peu.

Read More

  • php

Acceder aux éléments protégés d'une class

Nous sommes parfois amenés à vouloir manipuler une propriété ou une méthode protected de nos class.

L’utilisation de la reflection est envisageable pour modifier la visibilité mais une autre solution élégante à base de closure est également possible.

Considérons la class suivante :

1
2
3
4
class Foo {
    protected $bar;
    protected function bar() {}
}

L’idée est d’utiliser le Closure::call introduit en php7 pour injecter une closure dans le scope d’une instance de la class Foo.

1
2
3
4
5
6
7
8
$foo = new Foo();

$closure = function () {
    $this->bar = false;
    $this->bar();
};

$closure->call($foo);

Une fois notre closure injecté, il lui est désormais possible d’acceder à toutes les proprietés et méthodes protected de notre class.

Certes, c’est pas usuel, mais vous êtes majeur et vacciné.

Read More