PHP reflection on closures

Hi Habr! Today I want to talk about my crutch, which helped me not to plunge into the jungle of PHP Reflection . After all, everyone writes crutches, just someone writes large, and someone smaller.


image


I actively use Laravel in my projects. For those who are not familiar with this framework, do not despair, because I will explain obscure points.


This time I wrote some extension of validation rules:


Validator::extend('someRule', function ($attribute, $value, $parameters, $validator) {
        // some code...
        return $result; // boolean
}, ':attribute is invalid');

And I needed to get a list of all the rules passed to the validator. As it turned out, this seemingly simple task took me a little longer than I planned. The property was private. And there were no getters for it in the class implementation. Of course, I didn’t change the class, because after composer update this edit will fly off right away.


It should be said that I had never used Reflection before, but I heard what it is used for. So, I started reading the documentation. Naturally, the code from the example did not start the first time and it was necessary to look for more. And then I thought that the solution should be simpler.


And I did find a simple and elegant crutch. Still, it’s better not to do that. Private properties are private, so they do not climb there. But circumstances require, so ...


Validator::extend('someRule', function ($attribute, $value, $parameters, $validator) {
        // Это функция-ниндзя. Она врывается в валидатор и крадет приватное свойство.
        // Это очень коварно и подло, но у меня нет другого выбора (есть, но там писать больше)
        $ninja = function() { 
                // именно в этом свойстве хранится массив с нужными мне данными
                return $this->initialRules;
        };
        $initialRules = $ninja->call($validator); // параметр $newThis
        // some code
        return $result;
}, ':attribute is invalid');

If someone else does not understand, I will explain: I created an anonymous function that returns some property. And then just replaced the context with the validator context (laravel passes an instance of this class). That is, the closure now has access to this object from the inside and can access any private property and method.


All this beauty works, starting with PHP 5.4


That is actually all that I wanted to tell. It may have been invented before me, but it came to my mind myself, so I decided to share it. Suddenly, this decision will simplify someone's life.


Thanks for attention.


Also popular now: