工作流设计参考包括php实现.doc
工作流设计参考(包括PHP实现)本文关键词:php工作流,workflow工作流设计的工作流很少有让人满意的,即便是国内用的比较多的jbpm,用起来也会觉得很便扭。再加上PHP中没有什么好用的工作流,于是干脆自己设计一个,设计的原则如下:1根据80/20原则,只使用wfmc模型中最符合自身应用的20%功能2充分吸收国内使用jbpm开发BOSS中遇到的问题,工作流引擎只负责参数的收集和流程的流转,具体和业务的控制,交给每个流程定制的控制类去实现。3表单采用简单的html+控制标签的方法实现4权限和模板引擎,以及其它辅助函数直接使用办公系统自带的框架5充分利用PHP语言的特点,流程设计是基于数据库的,程序上使用OO设计,但采用重对象的方法6不把可视化设计流程的工作交给最终客户,而且由设计时完成,因此不考虑流程版本更新的问题一、工作流数据表设计tbl_workflow_defination:工作流定义表defination_id流程iddefination_name流程名称defination_handler流程处理辅助文件,每个工作流一个文件自定义处理文件,及其对象。例如workflow-proporsal-handler.php,其中定义对象proposaltbl_workflow_node:流程结点步骤表node_id结点iddefination_id流程idnode_index结点序号结点的stepnode_name结点名称node_type结点类型1人为决策,2自动处理(直接执行cute_function),3等待外部响应(例如外部WS触发),4分支,5汇总6结束结点(此结点执行时候自动终止进程)init_function流程初始函数run_function流程运行函数save_function流程保存函数transit_function流程流转函数prev_node_index前结点序号例如1。开始结点没有执行前,通过此来校验一下流程next_node_index后结点序号例如[同意]3,[不同意]4。尾结点或要结束的结点没有,若没有,直接调用endcutor执行角色,组,人role[1,2]group[1,2]user[1,2],为空由运行时决定cute_type执行类型0需所有人执行1只需一人执行remind提醒0不提醒1邮件2短信3邮件和短信field可编辑的字段name,contentmax_day最长时间(天)tbl_workflow_process:流程执行进程表process_id进程iddefination_id流程idprocess_desc进程描述显示在我的工作台中context上下文存放上下文变量,例如业务表的idcurrent_node_index当前结点序号start_time流程启动时间如遇分支、汇合显示为:1=》3,4=》3,5=》6finish_time流程完成时间state状态1运行2结束start_user发起人发起人,用于显示自己的流程tbl_workflow_thread:流程执行线程表thread_id线程idprocess_id进程idprocess_desc进程描述node_id结点idnode_name结点名称cutor执行人start_time线程生成时间receive_time线程接收时间finish_time线程完成时间max_time结点规定的最长时间state状态0未接收1已接收2已处理二、常见流程人工决策领导传阅部门领导审批填写表单结束放弃提交同意重填(退回)不同意完成外部响应发送支付信息接收支付成功响应(外部WS触发该流程)三、PHP设计运行的函数由结点在设计时候决定,如果没有设定,就使用默认的函数。利用了PHP语言的以下特性$name();//ThiscallstheBar()}functionBar(){echo“ThisisBar“;}}$foo=newFoo();$funcname=“Variable“;$foo->$funcname();//Thiscalls$foo->Variable()?>使用前可以用_exists来检查。WorkflowService.phpWorkflowService$defination$process$node$thread$用户输入的和流程有关的变量list_defination(){}init_process(defination_id){globaluser;取得$defination,得到业务的handler,例如WorkflowProposalHandler建立$process行记录}start_process(){调用WorkflowProposalHandler->start($process)//新建业务对象,并把业务类的参数例如proposal_id放到$process[‘context’]里面init_thread(1);//默认调用第一个结点}list_my_thread(){globaluser;}init_thread(node_index){取得$node取得$process修改$process为运行到当前结点Switch($node[‘node_type’])Case1:人工决策建立$threadWorkflowProposalHandler->init_function($process,$node,$thread)发送提醒Case2:自动处理建立$threadWorkflowProposalHandler->init_function($process,$node,$thread)调用run_thread(thread_id)Case3:等待外部响应建立$threadWorkflowProposalHandler->init_function($process,$node,$thread)Case4:分支取得所有分支的子结点init_thread(子结点)Case5:汇总:取得所有前结点,如果所有前结点的Thread都结束了,调出下一结点调用init_thread(子结点)Case6:结束:直接结束进程processend_process()}run_thread(thread_id){取得$node取得$process取得$threadSwitch($node[‘node_type’])Case1:人工决策修改$thread为已接收WorkflowProposalHandler->run_function($process,$node,$thread)显示表单Case2:自动处理修改$thread为已接收$next_node_id=WorkflowProposalHandler->run_function($process,$node,$thread)调用transit_thread(thread_id,$next_node_id)Case3:等待外部响应修改$thread为已接收$next_node_id=WorkflowProposalHand