一个最符合中国国情的工作流设计参考(包括PHP实现)

本文介绍了一款基于PHP自定义开发的工作流引擎设计方案。该方案遵循80/20原则,仅实现WFMC模型中核心功能,并针对国内JBPM使用经验进行优化。设计包括数据表结构、常见流程及PHP实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源 :  
       开源的工作流很少有让人满意的,即便是国内用的比较多的jbpm,用起来也会觉得很便扭。再加上PHP中没有什么好用的工作流,于是干脆自己设计一个,设计的原则如下:
1 根据80/20原则,只使用wfmc模型中最符合自身应用的20%功能
2 充分吸收国内使用jbpm开发BOSS中遇到的问题,工作流引擎只负责参数的收集和流程的流转,具体和业务的控制,交给每个流程定制的控制类去实现。
3 表单采用简单的html+控制标签的方法实现
4 权限和模板引擎,以及其它辅助函数直接使用办公系统自带的框架
5 充分利用PHP语言的特点,流程设计是基于数据库的,程序上使用OO设计,但采用重对象的方法
6 不把可视化设计流程的工作交给最终客户,而且由设计时完成,因此不考虑流程版本更新的问题
一、工作流数据表设计
 
tbl_workflow_defination:工作流定义表
defination_id
流程id
 
defination_name
流程名称
 
defination_handler
流程处理辅助文件,每个工作流一个文件
自定义处理文件,及其对象。例如workflow-proporsal-handler.php,其中定义对象proposal
 
tbl_workflow_node:流程结点步骤表
node_id
结点id
 
defination_id
流程id
 
node_index
结点序号
结点的step
node_name
结点名称
 
node_type
结点类型
1人为决策,2自动处理(直接执行execute_function),3等待外部响应(例如外部WS触发),4分支,5汇总 6结束结点(此结点执行时候自动终止进程)
init_function
流程初始函数
 
run_function
流程运行函数
 
save_function
流程保存函数
 
transit_function
流程流转函数
 
prev_node_index
前结点序号
例如1。开始结点没有
执行前,通过此来校验一下流程
next_node_index
后结点序号
例如[同意]3,[不同意]4。尾结点或要结束的结点没有,若没有,直接调用end
executor
执行角色,组,人
role[1,2] group[1,2] user[1,2],为空由运行时决定
execute_type
执行类型
0需所有人执行 1只需一人执行
remind
提醒
0不提醒 1邮件 2短信 3邮件和短信
field
可编辑的字段
name,content
max_day
最长时间(天)
 
 
tbl_workflow_process :流程执行进程表
process_id
进程id
 
defination_id
流程id
 
process_desc
进程描述
显示在我的工作台中
context
上下文
存放上下文变量,例如业务表的id
current_node_index
当前结点序号
 
start_time
流程启动时间
如遇分支、汇合显示为:
1=》3,4=》3,5=》6
finish_time
流程完成时间
 
state
状态
1运行 2结束
start_user
发起人
发起人,用于显示自己的流程
 
tbl_workflow_thread :流程执行线程表
thread_id
线程id
 
process_id
进程id
 
process_desc
进程描述
 
node_id
结点id
 
node_name
结点名称
 
executor
执行人
 
start_time
线程生成时间
 
receive_time
线程接收时间
 
finish_time
线程完成时间
 
max_time
结点规定的最长时间
 
state
状态
0未接收 1已接收 2已处理
 
二、常见流程
人工决策

领导传阅
部门领导审批
填写表单
结束
放弃
提交
同意
重填(退回)
不同意
完成

外部响应

发送支付信息
接收支付成功响应(外部WS触发该流程)

三、PHP设计
运行的函数由结点在设计时候决定,如果没有设定,就使用默认的函数。利用了PHP语言的以下特性
<?php
class Foo
{
    function Variable()
    {
        $name 'Bar';
        $this->$name(); // This calls the Bar() method
    }
    
    function Bar()
    {
        echo "This is Bar";
    }
}

$foo = new Foo();
$funcname "Variable";
$foo->$funcname();  // This calls $foo->Variable()

?>
使用前可以用method_exists来检查。
 
WorkflowService.php
 WorkflowService
    $defination
$process
$node
$thread
$input 用户输入的和流程有关的变量
list_defination()
{
}
init_process(defination_id)
{ global user;
取得$defination,得到业务的handler,例如WorkflowProposalHandler
   建立$process行记录
}
start_process()
{ 调用WorkflowProposalHandler->start($process)//新建业务对象,并把业务类的参数例如proposal_id放到$process[‘context’]里面
   init_thread(1);  //默认调用第一个结点
}
 
list_ my_thread ()
{ global user;
}
 
init_thread(node_index)
{
  取得$node
  取得$process
  修改$process为运行到当前结点
 Switch($node[‘node_type’])
   Case 1: 人工决策
       建立$thread
       WorkflowProposalHandler-> init_function ($process,$node,$thread)
       发送提醒
Case 2: 自动处理
    建立$thread
    WorkflowProposalHandler-> init_function ($process,$node,$thread)
       调用run_thread(thread_id)
Case 3: 等待外部响应
    建立$thread
    WorkflowProposalHandler-> init_function ($process,$node,$thread)
Case 4: 分支
    取得所有分支的子结点
    init_thread(子结点)
Case 5: 汇总:
    取得所有前结点,如果所有前结点的Thread都结束了,调出下一结点
       调用init_thread(子结点)
Case 6: 结束:直接结束进程process
    end_process()
}
run_thread(thread_id)
{   
取得$node
取得$process
取得$thread
 Switch($node[‘node_type’])
   Case 1: 人工决策
       修改$thread为已接收
          WorkflowProposalHandler-> run_function ($process,$node,$thread) 显示表单
Case 2: 自动处理
    修改$thread为已接收
    $next_node_id=WorkflowProposalHandler-> run_function ($process,$node,$thread)
       调用transit_thread(thread_id, $next_node_id)
Case 3: 等待外部响应
    修改$thread为已接收
    $next_node_id=WorkflowProposalHandler-> run_function ($process,$node,$thread)
    transit_thread(thread_id, $next_node_id)
Case 4: 分支
Case 5: 汇总:
Case 6: 结束:
}
save_thread(thread_id)
{ //保存结点数据
取得$node
取得$process
取得$thread
 Switch($node[‘node_type’])
   Case 1: 人工决策
          WorkflowProposalHandler-> save_function ($process,$node,$thread) 保存表单
WorkflowProposalHandler-> run_function ($process,$node,$thread) 显示表单
Case 2: 自动处理
Case 3: 等待外部响应
Case 4: 分支
Case 5: 汇总:
Case 6: 结束:
}
transit_thread(thread_id, $next_node_id)
{ 取得$node
  取得$process
取得$thread
 Switch($node[‘node_type’])
   Case 1: 人工决策
      WorkflowProposalHandler->transit_function($process,$node,$thread,$next_node_id)  
          修改$thread为已完成
          If($next_node_id < $ cur_node_id) { //回退
删除所有大于$next_node_id的Thread
}
init_thread($next_node_id)
Case 2: 自动处理
修改$thread为已完成
           If($next_node_id < $ cur_node_id) { //回退
删除所有大于$next_node_id的Thread
}
       init _thread($next_node_id)
Case 3: 等待外部响应
    修改$thread为已完成
           If($next_node_id < $ cur_node_id) { //回退
删除所有大于$next_node_id的Thread
}
    init _thread($next_node_id)
Case 4: 分支
Case 5: 汇总:
Case 6: 结束:
 
}
 
end_process()
 
list_my_process
view_process
 
workflow_proposal_handler.php
WorkflowProposalHandler
 start()
 prepare_input() 准备用户输入变量,从$_POST收集
 init_function () 线程建立后调用的默认函数,当流程的执行者由程序生成时,在此函数内更改$thread的executor,例如直接赋值user[2]
run_function () 线程运行化时候调用的默认函数
save_function () 保存运行信息
 transit_function () 执行流转
 sendmail 其它结点调用函数
 
workflow.php
 switch(op)
   case list_defination
        参数:无
WorkflowService->list_defination()
case start_process : 启动
       参数:defination_id
       WorkflowService->init_process(defination_id)
WorkflowService->start_process()
   case list_ my_thread : 待处理的列表
       WorkflowService->list_ my_thread()
   case run_thread :
       参数:thread_id
       WorkflowService->run_thread(thread_id)
case save_thread :
    参数:thread_id
    把input收集起来(所有的变量以 f_ 开头),赋给WorkflowService的Input,另外还要获得thread_id
    WorkflowService->save_thread(thread_id)
   case transit_thread :
   参数:thread_id
把input收集起来,赋给WorkflowService的Input,另外还要获得thread_id
$next_node_id = 得到用户选择的下一结点id
WorkflowService-> transit _thread(thread_id,$next_node_id)
 
   case list_my_process: 所有我发起的流程
case list_all_process: 所有我发起的流程
case view_process :
 
在其它程序中初始化流程
    1先自行建立好业务表单
2WorkflowService->init_process(defination_id)
3把建好的业务表单的ID放在process的context里面
4WorkflowService->init_thread(1)
WorkflowService->transit_thread(1,2) 通过手动调用把前面的流程过掉
外部服务继续流转流程(只用于自动流程)
1 把input收集起来,赋给WorkflowService的Input,另外还要获得thread_id
2 WorkflowService->run_thread(thread_id)
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值