Laravel WorkflowSubscriber класс, который условно вызывает методы защиты на основе текущего перехода, вызывающего неправильные методы

У меня здесь излишне запутанная ситуация. Я просто пытаюсь создать внутри этого WorkflowSubscriber метод, который проверяет переход события, создает переменную $guardMethod, которая будет выглядеть примерно как guardToSomePlace, а затем, если этот метод существует, вызовите ее. Вот код этой концепции:

<?php

namespace App\Listeners;

use App\Models\BugTypes\Bug;
use Symfony\Component\Workflow\Event\GuardEvent;

class BugWorkflowSubscriber
{
    /**
     * Handle workflow guard events.
     *
     * @param \Symfony\Component\Workflow\Event\GuardEvent $event
     */
    public function onGuard(GuardEvent $event)
    {
        $transition = $event->getTransition();

        $guardMethod = 'guard' . studly_case($transition->getName());
        // this can be something like guardToAccepted and it 
        // calls guardToOnHold below

        if (method_exists($this, $guardMethod)) { // should fail
            $this->$guardMethod($event);
        }
    }

    /**
     * Guards the to_on_hold transition
     *
     * @param \Symfony\Workflow\Event\GuardEvent $event
     *
     * @return void
     */
    private function guardToOnHold(GuardEvent $event)
    {
        dd('why is it getting here for other transitions?');
    }

    /**
     * Register the listeners for the subscriber.
     *
     * @param  \Illuminate\Events\Dispatcher  $events
     */
    public function subscribe($events)
    {
        $events->listen(
            'workflow.bug.guard',
            'App\Listeners\BugWorkflowSubscriber@onGuard'
        );

        $events->listen(
            'workflow.bug.entered.*',
            'App\Listeners\Workflow\Bug\OnEntered'
        );
    }
}

Он вызывает метод guardToOnHold для нескольких переходов, несмотря на то, что я могу dd $event->getTransition(), и это именно тот переход, который я ожидаю, и если я dd method_exists($this, $guardMethod), он будет ложным для любых / всех методов, кроме guardToOnHold, поскольку это единственный, который будет существовать после Создаю переменную $guardMethod. Если я поставлю method_exists($this, $guardMethod) перед оператором if, он будет ложным, но если я вставлю его внутри оператора if с тем же событием / переходом, он попадет в оператор if и true dd. Это Laravel 5.7 с использованием пакета Brexis / Laravel Symfony Workflow. Переход к событию всегда такой, каким я его ожидал. $event->getTransition() всегда возвращает один объект перехода с правильным именем, от и до.

Вы уверены, что он не выпускает одно событие за другим? Что произойдет, если вы позвоните в $this->$guardMethod($event) без проверки if?

newUserName02 30.10.2018 23:14

Я пробовал это. Он генерирует исключение для вызова неопределенного метода, как и следовало ожидать для любых переходов, у которых нет защиты.

Matt Larson 30.10.2018 23:19

Возможно несколько событий. Если я передаю строку, идентичную результату $transition->getName(), она ведет себя правильно.

Matt Larson 30.10.2018 23:21

Если я поставил само событие, оно выглядит точным (с правильным местом и переходом). Это не учитывает возможность выпуска большего количества событий ...

Matt Larson 30.10.2018 23:25

Но вы dd, а как насчет только dump?

newUserName02 30.10.2018 23:27

Я попробовал dump и print_r, чтобы он продолжал двигаться. Он просто выгружает / печатает одно событие.

Matt Larson 30.10.2018 23:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
6
370
1

Ответы 1

На самом деле это связано с тем, что я исследую последние 3 дня. Что происходит в рабочем процессе symfony, когда вы применяете переход, он вызывает функцию getEnabledTransitions, которая, в свою очередь, вызывает метод doCan и вызывает guardTransition, теперь guardTransition отправляет событие workflow.guard, и поскольку у вас есть слушатель (onGuard), ваша функция получает называется.

Это то, что, я думаю, происходит. Я все еще не уверен на 100%, прав ли я и что нужно делать в таких случаях, возможно, мне нужно дополнительное расследование.

Соответствующий код:

// all taken from Symfony/Component/Workflow/Workflow.php
public function apply($subject, $transitionName)
    {
        $transitions = $this->getEnabledTransitions($subject);

public function getEnabledTransitions($subject)
    {
        $enabled = array();
        $marking = $this->getMarking($subject);
        foreach ($this->definition->getTransitions() as $transition) {
            if ($this->doCan($subject, $marking, $transition)) {
                $enabled[] = $transition;
            }
        }
        return $enabled;
    }

private function doCan($subject, Marking $marking, Transition $transition)
    {
        foreach ($transition->getFroms() as $place) {
            if (!$marking->has($place)) {
                return false;
            }
        }
        if (true === $this->guardTransition($subject, $marking, $transition)) {
            return false;
        }

private function guardTransition($subject, Marking $marking, Transition $transition)
    {
        if (null === $this->dispatcher) {
            return;
        }
        $event = new GuardEvent($subject, $marking, $transition, $this->name);
        $this->dispatcher->dispatch('workflow.guard', $event);

Добавьте это здесь, чтобы это могло помочь кому-то в будущем.

Другие вопросы по теме