Skip to content

bingbin/zeus-php

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zeus-php

图例

alt 架构

写在前面的话

为什么建立zeus-php,因为看到越来越多的php开发人员在构建应用程序时太过注重数据库结构设计,往往一个应用的开始就伴随着数据库结构的开始。

  • 好的架构并非数据库优先,而是业务模型优先;数据库的职责是存储数据,业务不应该过度的依赖数据库。
  • MVC的M不是数据源,而是业务模型。
  • 框架的用意不是功能库,而是约定与约束。
  • 领域驱动是目前较好的抽象业务的方式。
  • 模块化垂直架构 or 功能性水平分层架构的选择,zeus选择前者。
  • 聚合根:业务抽象入口。注意:不使用集合管理聚合下的实体。
  • 实体:实体保留聚合根引用。
  • 值对象:无状态的数据值。
  • 领域服务:业务可确定的聚合间协作。
  • 领域事件:业务完成后广播的事件,通常用于消息通知,日志记录等行为。
  • 事件源:目前框架暂未启用mq队列实现事件源。
  • 命令:事件触发的上下文,事件的开始。
  • 存储库:一个聚合根一个存储库,存储聚合内所有实体数据。
  • 上下文:业务行为的生命周期。
  • 单一职责,依赖倒置,接口隔离。
  • 代码即注解。

文档

zeus以模块化来设计架构,使用领域驱动来组织代码。关注约定与约束,不造功能性轮子,各种功能性轮子可以使用autoload方式,以模块形式加入到“上下文”中。 使用MVC为业务行为驱动的基础模型,并约定了行为的路由规则(详见:zeus\mvc\Router)。

config

提供默认的配置文件“config.php”,应用层可使用APP_ENV_PATH来定义应用自身的配置文件(test\bootstrap.php ), 配置文件的管理方式详见[zeus\sandbox\ConfigManager]。

bootstap

顾名思义框架启动入口,初始化上下文。见[zeus\sandbox\ApplicationContext] (# ApplicationContext)

基本模块

  • base:定义上下文管理方式、组件、事件。
  • domain:聚合、实体、可以发生事件源的聚合
  • http:request、response、cookie、session
  • mvc:mvc 分发上下文、路由等。
  • database:pdo抽象层,定义了xa事务、active record等基础组件,使用规约提供统一的执行入口(zeus\database\specification\AbstractSpecification)。
  • utils:cryto、uploader、download等,可根据模块分类。

Roadmap

  • plugin机制
  • EventSouring事件源
  • Snapshot 事件源归档快照

Usage

加载框架

define("CURRENT_DIR",dirname(__FILE__));//项目根目录,非必选
define("APP_ENV_PATH",CURRENT_DIR.DIRECTORY_SEPARATOR."config.php");//项目配置文件路径

define("ROOT",dirname(CURRENT_DIR));//项目目录与框架目录所在的根目录,非必须
include_once ROOT.DIRECTORY_SEPARATOR."zeus".DIRECTORY_SEPARATOR."bootstrap.php";//加载框架

路由

zeus使用两种路由方式,1、正则表达式;2、模块约定路径。

  • 正则表达式,即传统的URL重写方式,并通过正则分组获取url中的参数。
  • 模块约定路径,预定路由方式为/module/[controller]/[action]/[params options][?query_string]
    • module 必须的,且已注册到路由中的模块。第一项;
    • controller 可选。如果未指定则使用router.default_controller。第二项;
    • actioin 可选。如果未指定则使用router.default_controller_action。第三项目。
    • controller约定的格式为“ucfirst($fragment)Controller"”, 如果约定格式的controller文件不存在,则判定此controller fragment为action, 忽略原定的action fragment(第三项)并当作params。
    • controller的匹配格式为模块定义的命名空间前缀+controller名称。 例如Router::addModule("test","com\oa\test");, 假设router.default_controller为“indexController”、router.default_controller_action为“index” url为“/test/echo”,默认匹配com\oa\test\EchoController并调用index方法,如果com\oa\test\EchoController则匹配 com\oa\test\IndexController并调用echo方法。

url rewrite

<?php
Router::addRouter('/',IndexPlatformController::class); 
Router::addRouter('/welcome',WelcomePlatformController::class);

模块约定

Router::addModule("account","account");
Router::addModule("account_auth","account_auth");
Router::addModule("bus","bus");
Router::addModule("report","report");
Router::addModule("customer","customer");
Router::addModule("test","com\\oa\\test");

controller

class IndexController extends Controller
{
    public function test2($a){
        print_r($this->request->getData());
        echo $a;
    }
}

Command&Event

//test
use test\EchoCommand;

include_once 'bootstrap.php';

$command = new EchoCommand();
$command->execute();//or ApplicationContext::currentContext()->getCommandBus()->execute($command);

//command
use zeus\base\command\AbstractCommand;
use zeus\sandbox\ApplicationContext;

class EchoCommand extends AbstractCommand
{
    public function __construct()
    {
        parent::__construct();

        $this->setData([1,2,3]);
    }

    public function start(){
        echo "{$this->commandType} => starting \r\n";
    }

    public function finished(){
        echo "{$this->commandType} => finished \r\n";
    }

}

ApplicationContext::currentContext()->getCommandBus()->register(EchoCommand::class,EchoCommandHandler::class);

//commandhandler
use zeus\base\AbstractComponent;
use zeus\base\command\AbstractCommand;
use zeus\base\command\CommandHandlerInterface;

class EchoCommandHandler extends AbstractComponent implements CommandHandlerInterface
{
    public function execute(AbstractCommand $command)
    {
        print_r($command->getData());

        $this->raise(new EchoedEvent());
        
        //$event = new new EchoedEvent();
        //$msg   = new EventMessage($this,$event);
        //ApplicationContext::currentContext()->getEventBus()->publish($msg);
    }
}

//event
class EchoedEvent extends AbstractEvent
{
    public function __construct()
    {
        parent::__construct();

        $this->setData(["a","b","c"]);
    }

    public function start(){
        echo "{$this->eventType} => starting \r\n";
    }

    public function finished(){
        echo "{$this->eventType} => finished \r\n";
    }
}

ApplicationContext::currentContext()->getEventBus()->subscribe(EchoedEvent::class,EchoedEventHandler::class);

//listener
use zeus\base\event\EventListenerInterface;
use zeus\base\event\EventMessage;

class EchoedEventHandler implements EventListenerInterface
{
    public function handler(EventMessage $eventMessage)
    {
        $sender = $eventMessage->getSender();
        $event  = $eventMessage->getEvent();

        echo "sender : ".get_class($sender)."=>\r\n";
        print_r($event->getData());
    }
}

License

  • All code in this repository is covered by the terms of the Apache2.0 License.

About

php cqrs framework

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 99.5%
  • Other 0.5%