Подтвердить что ты не робот

Рамка для государственных машин PHP

Я сомневаюсь, что существует какая-либо государственная машина, например https://github.com/pluginaweek/state_machine для PHP.

Мне пришлось определять многие логические предложения if-else, и мне хотелось бы, чтобы что-то помогло сделать его более увлекательным, просто определяя:

  • Условие, необходимое для перехода
  • Состояние после перехода

Затем это можно использовать повторно, чтобы проверить соответствие условий или нет, например

$customer->transition('platinum');

Я ожидаю, что эта строка кода неявно проверяет, может ли клиент перейти или нет. Или явно проверьте:

$customer->canTransitTo('platinum');

Спасибо заранее, noomz

4b9b3361

Ответ 1

Я не знаю рамки вроде этого (это не значит, что она не существует). Но хотя это не так, как привязанная структура, шаблон

После того, как вы определили состояния, вам просто нужно применить их к вашему основному объекту:

class Car implements EngineState
{
    protected $state;
    public function __construct()
    {
        $this->state = new EngineTurnedOffState;
    }
    public function startEngine()
    {
        $this->state = $this->state->startEngine();
    }
    public function moveForward()
    {
        $this->state = $this->state->moveForward();
    }
}

И тогда вы можете сделать

$car = new Car;
try {
    $car->moveForward(); // throws Exception
} catch(LogicException $e) {
    echo $e->getMessage();
}

$car = new Car;
$car->startEngine();
$car->moveForward();

Для сокращения слишком больших операторов if/else этого должно быть достаточно. Обратите внимание, что возвращение нового экземпляра состояния для каждого перехода несколько неэффективно. Как я уже сказал, это наивная реализация, чтобы проиллюстрировать суть.

Ответ 3

Я работал над простой библиотекой конечных автоматов PHP, подобной рельсам state_machine. Код здесь: https://github.com/chriswoodford/techne/tree/v0.1

Пример автомобиля, подобный выбранному ответу (см. выше), будет выглядеть примерно так:

Инициализация

  $machine = new StateMachine\FiniteStateMachine();
  $machine->addEvent('start', array('parked' => 'idling'));
  $machine->addEvent('drive', array('idling' => 'driving'));
  $machine->addEvent('stop', array('driving' => 'idling'));
  $machine->addEvent('park', array('idling' => 'parked'));
  $machine->setInitialState('parked');

Использование

  $machine->start();
  echo $machine->getCurrentStatus();
  // prints "idling"     

  $machine->drive();
  echo $machine->getCurrentStatus();
  // prints "driving"

  $machine->stop();
  echo $machine->getCurrentStatus();
  // prints "idling"

  $machine->park();
  echo $machine->getCurrentStatus();
  // prints "parked"

У него отсутствует явно определенный интерфейс, так как он использует магический метод __call() для приема сообщений, но это легко можно решить с помощью adapter.

Ответ 4

Я использовал этот https://github.com/yohang/Finite, который довольно мощный, однако документы не так детализированы. Если вы знакомы с государственными машинами, тогда у вас не должно быть никаких проблем.

Ответ 5

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

https://github.com/definitely246/state-machine

Чтобы использовать его, вы определяете обработчики событий перехода как классы. Затем вам нужно определить переходы. Машина конечного состояния может быть настроена на другие вещи, но вот основные сведения.

class Event1ChangedState1ToState2
{
    public function allow($context)
    {
        return true;
    }

    public function handle($context)
    {
        if (!$context->statesChanged) $context->statesChanged = 0;
        print "state1 -> state2\n";
        return $context->statesChanged++;
    }
}

class Event1ChangedState2ToState1
{
    public function allow($context)
    {
        return true;
    }

    public function handle($context)
    {
        print "state2 -> state1\n";
        return $context->statesChanged++;
    }
}

Затем вы можете определить переходы, которые изменяют состояния при срабатывании события.

$transitions = [
   [ 'event' => 'event1', 'from' => 'state1', 'to' => 'state2', 'start' => true],
   [ 'event' => 'event1', 'from' => 'state2', 'to' => 'state1' ],
];

$fsm = new StateMachine\FSM($transitions);

print $fsm->state() . PHP_EOL; // 'state1'

$fsm->event1(); // returns 1, prints 'state1 -> state2'

print $fsm->state() . PHP_EOL; // 'state2'

$fsm->event1(); // returns 2, prints 'state2 -> state1'

print $fsm->state() . PHP_EOL; // 'state1'

Вы можете установить с помощью композитора

composer require definitely246/state-machine

Ответ 6

Для записи пишу (еще один) конечный автомат

https://github.com/EFTEC/StateMachineOne

Тем не менее, он основан на автоматизации, а не на событии (однако можно использовать поле в качестве события). Переход состояния инициируется значениями, вручную или кодом.

Например, пример парковки:

где педаль, ключ, газ, скорость и тормоз - это поля, определяемые и контролируемые кодом.

$smachine->addTransition(PARKED,IDLING
    ,'when pedal = 1 and turnkey = 1 and gas > 0');
$smachine->addTransition(IDLING,DRIVING
    ,'when gas > 0 and speed > 0');
$smachine->addTransition(DRIVING,IDLING
    ,'when brake = 1 and speed = 0');
$smachine->addTransition(IDLING,PARKED
    ,'when turnkey = 0 and speed = 0');

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

Особенности:

  • Хранит информацию в базе данных (необязательно).
  • Он имеет пользовательский интерфейс (для тестирования) см. Изображение

state machine

Я также опубликовал статью об этом

https://medium.com/cook-php/creating-a-state-machine-using-php-ddef9395430e

Ответ 7

Я создал Smalldb framework для реализации уровня модели веб-приложения с использованием государственных машин. Он предназначен для работы непосредственно с базой данных SQL, где каждая строка таблицы SQL представляет экземпляр конечного автомата (поэтому государственные машины являются постоянными).

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

Чтобы ускорить разработку, Smalldb может загружать диаграммы состояний в GraphML, созданные с помощью редактора yEd, поэтому вы можете нарисовать диаграмму состояний, а затем напрямую использовать ее в своем приложении, а также в своей документации. Также в разработке находится встроенный редактор (jQuery widget + desktop wrapper). Для целей отладки и онлайн-документации в приложении Smalldb может генерировать диаграммы состояний с использованием Graphviz.

Ответ 8

Symfony имеет компонент рабочего процесса с 2016 года, который включает в себя все функции конечного автомата, которые вы можете себе представить, и к настоящему моменту он кажется гибким и зрелым. Он привязан к Symfony, поэтому, если вы используете Symfony и Doctrine, его очень легко интегрировать (но вы также можете использовать его отдельно). Мне также нравится, как вы можете создавать дампы визуальных представлений о ваших рабочих процессах, чтобы показывать их людям или обсуждать их с командой, и есть много отличных учебных пособий, доступных в Интернете или на реальных семинарах.

На Youtube есть несколько хороших видео об обоих конечных автоматах и о том, как вы используете их с компонентом рабочего процесса, например это Мишель Санвер или это Тобиас Найхольм.

При этом компонент рабочего процесса предполагает многое из вашего конечного автомата и работает лучше всего, если вы следуете этим принципам и комбинируете его с другими смежными компонентами (Symfony Event Dispatcher и Doctrine). Если вы используете Domain Driven Design или CQRS или хранилище событий или что-то подобное, возможно, имеет смысл просто обрабатывать ваши собственные состояния. Сначала нарисуйте свой конечный автомат (чтобы вы знали состояния и переходы), а затем реализуйте классы для обработки изменений или доступа к текущему состоянию - сложная вещь в конечных автоматах - это логика (о которой вам все равно следует подумать заранее), а не обязательно представление в коде. Получите хорошее представление о том, как работают конечные автоматы, вдохновляйтесь библиотеками, такими как компонент рабочего процесса Symfony (вы даже можете создавать прототипы на них или сначала попробовать их с ними), а затем попытайтесь адаптировать его к вашей ситуации и посмотреть, где ваше наиболее важное состояние машинная логика и как вы можете ее применять.