Хобрук: Ваш путь к мастерству в программировании

Как проверить закрытие в php?

У меня есть функция, которая передается Closure. Я хочу узнать название метода, из которого происходит закрытие. Когда я вызываю print_r, он выводит это:

Closure Object
(
  [static] => Array
    (
      [listener] => Event_Subscriber_Calq@vendor_product_created
      [container] => Illuminate\Foundation\Application Object
...

Как мне получить это значение слушателя? Я пробовал ->static, ::$static, getStatic(), я не могу придумать, как получить значение.

В настоящее время я планирую использовать буферизацию вывода для захвата вывода из var_dump. Я не могу использовать print_r для этого, потому что замыкание содержит ссылку и объект, который ссылается на себя, а print_r требует много времени для обработки рекурсии. Я также не могу использовать var_export, потому что он не включает в вывод значение, которое я хочу. Итак, это мое решение:

ob_start();
var_dump($closure);
$data = ob_get_clean();
$data = preg_replace('#^([^\n]*\n){4}#', '', $data);
$data = preg_replace('#\n.*#', '', $data);
$data = preg_replace('#.*string.[0-9]+. "(.*)".*#', '\1', $data);
list($class, $method) = explode('@', $data);

Что ужасно. Есть ли другой способ сделать это? Может быть, с помощью отражения?


  • каково происхождение данных? где ты это вообще взял? возможно, у вашего объекта есть метод получения 06.05.2015
  • На самом деле это исходит от laravel, который расширяет основной класс закрытия php, но не добавляет никаких новых методов. 06.05.2015
  • ...имя метода, из которого получено закрытие... - вы имеете в виду имя метода, передавшего замыкание? Или имя метода, который выполнил/вызвал замыкание? 06.05.2015
  • Вы пытались преобразовать этот массив из ассоциативного в числовой? php.net/manual/en/function.array-values.php 06.05.2015
  • @Quasdunk замыкание обычно является ссылкой на анонимную функцию, однако оно также может быть ссылкой на именованную функцию, что, как я полагаю, у меня здесь ... хотя, присмотревшись, я думаю, что более вероятно, что я пытаюсь извлекать данные из локальной области закрытия... не уверен, что это даже имеет смысл. Что бы это ни было, я пытаюсь получить значение $obj-›static-›listener 06.05.2015
  • @GabrielMoretti Да, он отклоняет это, потому что замыкание - это объект, а не массив. 06.05.2015
  • и что вы получаете от get_object_vars()? @Бенуберд 06.05.2015
  • @GabrielMoretti get_object_vars возвращает пустой массив 06.05.2015
  • @Benubird, почему бы тебе не вернуться на шаг или два и не сказать, чего ты пытаешься достичь. Я вижу, вы работаете с Laravel. Что ты пытаешься сделать? Весьма вероятно, что существует канонический способ приблизиться к вашей более крупной цели. 24.06.2015
  • @Rob_vH Я думаю, что пытался заставить один контроллер вызывать другой маршрут, не используя перенаправление и не зная имени другого контроллера, только имя маршрута, а также не зная, был ли маршрут на самом деле контроллером или замыканием . Я думаю, были еще какие-то сложности, которых я сейчас не вспомню, потому что то, что я только что написал, не совсем соответствует этому вопросу - это было два месяца назад, я не помню подробностей. 24.06.2015

Ответы:


1

Я знаю, что этот пост устарел, но если кто-то ищет информацию, вам нужно использовать ReflectionFunction:

$r = new ReflectionFunction($closure);
var_dump($r, $r->getStaticVariables(), $r->getParameters());

С уважением, Алекс

08.12.2017
  • Спасибо! Это было именно то, что я искал — мне нужно было получить имена классов слушателей для данного события. 28.09.2020

  • 2

    В недавнем проекте я выбрал декларативный подход с использованием класса-оболочки. Класс позволяет задать строку произвольной формы, описывающую источник обратного вызова, и может использоваться как прямая замена закрытия, поскольку он реализует метод __invoke().

    Пример:

    use ClosureTools;
    
    $closure = new NamedClosure(
        function() {
            // do something
        }, 
        'Descriptive text of the closure'
    );
    
    // Call the closure
    $closure();
    

    Для доступа к информации о закрытии:

    if($closure instanceof NamedClosure) {
        $origin = $closure->getOrigin();
    }
    

    Поскольку источник представляет собой строку произвольной формы, для него можно установить любое значение, которое может быть полезно для идентификации замыкания в зависимости от варианта использования.

    Вот скелет класса:

    <?php
    
    declare(strict_types=1);
    
    namespace ClosureTools;
    
    use Closure;
    
    class NamedClosure
    {
        /**
         * @var Closure
         */
        private $closure;
    
        /**
         * @var string
         */
        private $origin;
    
        /**
         * @param Closure $closure
         * @param string $origin
         */
        public function __construct(Closure $closure, string $origin)
        {
            $this->closure = $closure;
            $this->origin = $origin;
        }
    
        /**
         * @return string
         */
        public function getOrigin() : string
        {
            return $this->origin;
        }
    
        public function __invoke()
        {
            return call_user_func($this->closure, func_get_args());
        }
    }
    
    29.04.2021
    Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..