Фреймворк машины состояния PHP

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

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

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

затем это можно повторно использовать для проверки соответствия условий или нет, для пример

$customer->transition('platinum');

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

$customer->canTransitTo('platinum');

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

6 ответов


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

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



Я работал над простой библиотекой конечных автоматов PHP, похожей на rails 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 что довольно мощно, однако документы не так подробны. Если вы familliar с государственными машинами, то у вас не должно быть никаких проблем.


Я написал государственную машину для 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

composer require definitely246/state-machine

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

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

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