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

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

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

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

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

$customer->transition('platinum'); 

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

 $customer->canTransitTo('platinum'); 

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

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

 interface EngineState { public function startEngine(); public function moveForward(); } class EngineTurnedOffState implements EngineState { public function startEngine() { echo "Started Engine\n"; return new EngineTurnedOnState; } public function moveForward() { throw new LogicException('Have to start engine first'); } } class EngineTurnedOnState implements EngineState { public function startEngine() { throw new LogicException('Engine already started'); } public function moveForward() { echo "Moved Car forward"; return $this; } } 

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

 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 этого должно быть достаточно. Обратите внимание, что возвращение нового экземпляра состояния для каждого перехода несколько неэффективно. Как я уже сказал, это наивная реализация, чтобы проиллюстрировать это.

FSM Package и FSM Parser .

Я работал над простой библиотекой конечных состояний, которая похожа на рельсы 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 () для приема сообщений, но это легко может быть разрешено с помощью адаптера .

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

Я написал автомат для 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 

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

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

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