aegisora/state-transition-rule 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

aegisora/state-transition-rule

Composer 安装命令:

composer require aegisora/state-transition-rule

包简介

Aegisora validation rule for checking allowed state transitions in Aegisora ecosystem

README 文档

README

Code Coverage Badge Software License PHPStan Badge

State Transition Rule provides a simple, rule-based state transition validation implementation for the Aegisora ecosystem.

It is built on top of aegisora/rule-contract and follows its strict validation architecture, ensuring consistent and predictable behavior across applications.

This rule is useful for validating workflows, status changes, lifecycle transitions, and domain state machines.

📑 Table of Contents

✨ Features

  • 🔹 Lightweight and dependency-free except aegisora/rule-contract
  • 🔹 Validates transitions between named states
  • 🔹 Supports explicit allowed transition maps
  • 🔹 Supports array-based transition map creation
  • 🔹 Ignores invalid raw map data safely
  • 🔹 Deduplicates source states and transition states
  • 🔹 Fully compatible with Aegisora validation pipeline
  • 🔹 Strict ContextResult validation flow
  • 🔹 No raw booleans — only structured results
  • 🔹 Safe execution via base Rule abstraction
  • 🔹 Simple factory API (create)
  • 🔹 Ready to use out of the box

📦 Installation

composer require aegisora/state-transition-rule

🚀 Core Concept

This package implements a single validation rule:

  • accepts a StateTransition value via Context
  • checks whether transition from source state to target state is allowed
  • returns a standardized Result

A transition is represented by two states:

from → to

Example:

draft → paid

The rule validates this transition against configured allowed transition maps.

🏗️ Basic Usage

use Aegisora\RuleContract\Models\Context;
use Aegisora\Rules\StateTransition\Models\State;
use Aegisora\Rules\StateTransition\Models\StateTransition;
use Aegisora\Rules\StateTransition\Models\StateTransitionMap;
use Aegisora\Rules\StateTransition\Models\StateTransitionMaps;
use Aegisora\Rules\StateTransition\StateTransitionRule;

$allowedTransitions = StateTransitionMaps::create([
    StateTransitionMap::create(State::create('draft'), [ State::create('paid'), State::create('cancelled'),]),
    StateTransitionMap::create( State::create('paid'), [ State::create('shipped'), State::create('refunded'),]),
]);

$transition = StateTransition::create(State::create('draft'), State::create('paid'));
$result = StateTransitionRule::create($allowedTransitions)->validate(Context::create($transition));

if ($result->isValid()) {
    // transition is allowed
} else {
    // transition is not allowed
}

🧩 Array-Based Configuration

Allowed transitions may be created from raw array data using StateTransitionMaps::createFromArray().

use Aegisora\RuleContract\Models\Context;
use Aegisora\Rules\StateTransition\Models\State;
use Aegisora\Rules\StateTransition\Models\StateTransition;
use Aegisora\Rules\StateTransition\Models\StateTransitionMaps;
use Aegisora\Rules\StateTransition\StateTransitionRule;

$allowedTransitions = StateTransitionMaps::createFromArray([
    [ 'draft' => [ 'paid', 'cancelled', ],],
    [ 'paid' => [ 'shipped', 'refunded', ],],
    [ 'shipped' => [ 'completed',],],
]);

$transition = StateTransition::create(State::create('paid'), State::create('shipped'));
$result = StateTransitionRule::create($allowedTransitions)->validate(Context::create($transition));

if ($result->isValid()) {
    // paid → shipped is allowed
}

🧹 Raw Data Normalization

StateTransitionMaps::createFromArray() safely normalizes raw transition data.

It accepts only:

  • non-empty string source state names
  • array transition state lists
  • non-empty string transition state names

Invalid values are ignored.

Duplicate source states are skipped after the first valid occurrence.

Duplicate transition states are also skipped.

Example:

$allowedTransitions = StateTransitionMaps::createFromArray([
    ['draft' => ['paid', 'paid', '', 123, true, 'cancelled',],],
]);

The normalized map will contain:

  • draft → paid
  • draft → cancelled

🧱 Models

State

Represents a named state.

State::create('draft');

StateTransition

Represents transition from one state to another.

StateTransition::create(State::create('draft'), State::create('paid'));

StateTransitionMap

Represents allowed target states for a single source state.

StateTransitionMap::create(
    State::create('draft'),
    [State::create('paid'), State::create('cancelled'),]
);

StateTransitionMaps

Represents a collection of transition maps.

StateTransitionMaps::create([
    StateTransitionMap::create(State::create('draft'), [State::create('paid'),]),
]);

🧪 Validation Result

If transition is allowed, the rule returns a valid result.

$result->isValid(); // true

If transition is not allowed, the rule returns an invalid result.

$result->isValid(); // false
$result->getFailedRuleCode(); // state_transition_rule

If the context value is not an instance of StateTransition, the rule throws:

Aegisora\RuleContract\Exceptions\InvalidRuleContextException

🔗 Guardian Usage

This rule can be used together with aegisora/guardian to build fluent validation pipelines.

use Aegisora\Guardian\Guardian;
use Aegisora\Rules\StateTransition\Models\State;
use Aegisora\Rules\StateTransition\Models\StateTransition;
use Aegisora\Rules\StateTransition\Models\StateTransitionMaps;
use Aegisora\Rules\StateTransition\StateTransitionRule;
use App\Exceptions\InvalidOrderStatusTransitionException;

$guardian = new Guardian();

$allowedTransitions = StateTransitionMaps::createFromArray([
    ['draft' => ['paid', 'cancelled',],],
    ['paid' => ['shipped', 'refunded',],],
]);

$guardian
    ->that(StateTransition::create(State::create('draft'), State::create('paid')))
    ->must(StateTransitionRule::create($allowedTransitions), new InvalidOrderStatusTransitionException())
    ->validate();

If the transition is invalid, Guardian throws the provided domain exception.

🧭 Real-World Examples

State Transition Rule is useful for validating domain workflows.

Examples

Order:

draft → paid

paid → shipped

shipped → completed
Payment:

pending → approved

pending → declined

approved → refunded
Ticket:

open → in_progress

in_progress → resolved

resolved → closed
Publication:

draft → review

review → published

published → archived

🧩 Factory Methods

State::create($name);

  • $name — state name

StateTransition::create($from, $to);

  • $from — source State
  • $to — target State

StateTransitionMap::create($sourceState, $transitionStates);

  • $sourceState — source State
  • $transitionStates — list of allowed target State objects

StateTransitionMaps::create($maps);

  • $maps — list of StateTransitionMap objects

StateTransitionMaps::createFromArray($rawData);

  • $rawData — raw transition map array

StateTransitionRule::create($allowedTransitions);

  • $allowedTransitionsStateTransitionMaps instance

🏛️ Architecture

This package relies on aegisora/rule-contract.

Flow:

  1. validate() is called
  2. Context is passed in
  3. StateTransition is extracted from context
  4. Source state is searched in allowed transition maps
  5. Target state is checked against allowed transition states
  6. Result is returned

All logic is safely handled by Rule contract.

⚖️ License

This package is open-source and licensed under the MIT License. See the LICENSE for details.

🌱 Contributing

Contributions are welcome and greatly appreciated! See the CONTRIBUTING for details.

🌟 Support

If you find this project useful, please consider giving it a star on GitHub!

It helps the project grow and motivates further development.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-20

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固