第236章 Controller工程
236.1 提出背景
在 ICAI 工程体系中,Controller 是 MVC 架构中的请求控制层。
如果将整个 ICAI 请求处理过程表示为:
Request→Controller→Service→Engine→DomainObject→Repository→MySQLRequest \rightarrow Controller \rightarrow Service \rightarrow Engine \rightarrow DomainObject \rightarrow Repository \rightarrow MySQL
那么 Controller 位于系统外部请求与内部业务运行机制之间。
Controller 的主要职责不是执行复杂的认知计算,而是完成:
Controller=RequestReceive+ParameterProcess+ServiceCall+ResultReturn+PageRedirectController= RequestReceive+ ParameterProcess+ ServiceCall+ ResultReturn+ PageRedirect
即:
- 接收请求;
- 处理请求参数;
- 调用 Service;
- 返回结果;
- 执行页面跳转。
因此:
Controller≠ServiceController\neq Service Controller≠EngineController\neq Engine Controller≠RepositoryController\neq Repository
Controller 是请求协调层。
236.2 Controller定义
**Controller(控制器)**是 MVC 架构中负责接收外部请求、组织请求参数、调用对应 Service、处理服务结果并向客户端返回响应或执行页面跳转的程序对象。
形式化表示:
Controller={Request,Parameter,Service,Result,Response,Redirect}Controller= \{ Request, Parameter, Service, Result, Response, Redirect \}
完整请求过程:
Request→Controller→Parameter→Service→Result→ResponseRequest \rightarrow Controller \rightarrow Parameter \rightarrow Service \rightarrow Result \rightarrow Response
如果需要页面跳转:
Result→Redirect→NewRequestResult \rightarrow Redirect \rightarrow NewRequest
因此 Controller 的核心任务是:
把外部请求转换成系统能够处理的 Service 调用,并把 Service 的结果转换成外部能够接收的响应。
236.3 Controller在ICAI工程中的位置
ICAI 工程完整结构:
User→Controller→Service→Engine→DomainObject→Repository→MySQLUser \rightarrow Controller \rightarrow Service \rightarrow Engine \rightarrow DomainObject \rightarrow Repository \rightarrow MySQL
各层职责不同。
Controller
负责:
Request\rightarrowServiceRequest\rightarrowService
Service
负责:
BusinessProcessBusinessProcess
Engine
负责:
Calculation+Logic+ProcessingCalculation+Logic+Processing
Domain Object
负责:
ObjectStructure+ObjectState+ObjectBehaviorObjectStructure+ObjectState+ObjectBehavior
Repository
负责:
PersistencePersistence
MySQL
负责:
DataStorageDataStorage
因此:
Controller≠BusinessLogicController \neq BusinessLogic
Controller 不应该把 Service、Engine 和 Repository 的职责全部集中在一个类中。
236.4 请求接收
Controller 的第一项职责是请求接收(Request Receive)。
外部请求可能来自:
GETGET POSTPOST PUTPUT DELETEDELETE
在传统 PHP MVC 系统中,最常见的是 GET 和 POST 请求。
请求可以表示为:
Request={Method,URI,Parameters,Headers,Session,Files}Request= \{ Method, URI, Parameters, Headers, Session, Files \}
Controller 首先确定:
RequestMethodRequestMethod
以及:
RequestRouteRequestRoute
例如:
GET /admin/individual/list
可以进入:
IndividualController::index()
而:
POST /admin/individual/create
可以进入:
IndividualController::create()
因此:
URI→Route→Controller→MethodURI \rightarrow Route \rightarrow Controller \rightarrow Method
236.5 请求路由与Controller
Controller 通常不会直接决定所有请求路径,而是由 Router 将请求映射到 Controller。
结构:
Request→Router→Controller→ActionRequest \rightarrow Router \rightarrow Controller \rightarrow Action
其中 Action 表示 Controller 中负责处理某一类请求的方法。
例如:
class IndividualController
{
public function index()
{
}
public function create()
{
}
public function store()
{
}
public function edit()
{
}
public function update()
{
}
public function delete()
{
}
}
可以形成:
/individual→index()/individual \rightarrow index() /individual/create→create()/individual/create \rightarrow create() /individual/store→store()/individual/store \rightarrow store() /individual/update→update()/individual/update \rightarrow update()
因此:
Route→ControllerActionRoute \rightarrow ControllerAction
236.6 参数处理
请求进入 Controller 后,第二项职责是处理请求参数。
参数可以来自:
GETGET POSTPOST FILESFILES SESSIONSESSION
或者系统内部产生的参数。
统一表示:
RequestParameter={Name,Value,Type,Source}RequestParameter= \{ Name, Value, Type, Source \}
例如创建机器个体:
id
type
name
status
Controller 可以接收到:
$id = $_POST['id'];
$type = $_POST['type'];
$name = $_POST['name'];
$status = $_POST['status'];
但是不能简单地把原始请求参数直接传入整个系统。
应该经过:
Request→ParameterExtraction→ParameterValidation→ParameterNormalization→ServiceRequest \rightarrow ParameterExtraction \rightarrow ParameterValidation \rightarrow ParameterNormalization \rightarrow Service
236.7 参数提取
参数提取的职责是从 Request 中获取需要的数据。
例如:
$params = array(
'id' => isset($_POST['id']) ? $_POST['id'] : null,
'type' => isset($_POST['type']) ? $_POST['type'] : null,
'name' => isset($_POST['name']) ? $_POST['name'] : null
);
形成:
Request→ParametersRequest \rightarrow Parameters
参数提取本身不应该进行复杂业务判断。
例如 Controller 可以判断:
id≠∅id\neq\varnothing
但是不应该在 Controller 中实现复杂的能力匹配:
Goal→Capability→Method→DecisionGoal \rightarrow Capability \rightarrow Method \rightarrow Decision
这种计算应该交给 Service 和 Engine。
236.8 参数验证
参数提取以后必须进行基本验证。
定义:
ParameterValid=Required∧Type∧Format∧RangeParameterValid= Required \land Type \land Format \land Range
例如:
if (empty($params['type'])) {
return $this->error('个体类型不能为空');
}
数字参数可以检查:
is_numeric(Parameter)is\_numeric(Parameter)
字符串参数可以检查:
strlen(Parameter)>0strlen(Parameter)>0
因此:
Request→Extract→ValidateRequest \rightarrow Extract \rightarrow Validate
如果参数无效:
InvalidParameter→ErrorResponseInvalidParameter \rightarrow ErrorResponse
而不是继续调用 Service。
236.9 参数规范化
不同来源的参数可能存在不同格式,因此 Controller 可以进行必要的参数规范化。
例如:
" robot "
规范化为:
"robot"
或者:
"001"
转换为:
1
形成:
RawParameter→NormalizedParameterRawParameter \rightarrow NormalizedParameter
但是 Controller 不应该承担复杂的数据转换逻辑。
如果转换涉及领域规则:
Parameter→DomainValueParameter \rightarrow DomainValue
则应该交给 Service 或 Domain Object。
因此:
SimpleNormalization→ControllerSimpleNormalization\rightarrow Controller DomainTransformation→Service/DomainObjectDomainTransformation\rightarrow Service/DomainObject
236.10 Service调用
Controller 最重要的职责之一是调用 Service。
核心关系:
Controller→ServiceController \rightarrow Service
例如:
class IndividualController
{
protected $service;
public function __construct($service)
{
$this->service = $service;
}
public function create()
{
$params = array(
'type' => isset($_POST['type']) ? $_POST['type'] : null,
'name' => isset($_POST['name']) ? $_POST['name'] : null
);
return $this->service->create($params);
}
}
Controller 不直接调用 MySQL:
Controller
↓
MySQL
而应该:
Controller
↓
Service
↓
Repository
↓
MySQL
如果需要复杂计算:
Controller
↓
Service
↓
Engine
↓
Domain Object
↓
Repository
↓
MySQL
236.11 Controller与Service职责边界
Controller 与 Service 必须保持清晰边界。
Controller:
Request→Parameter→ServiceRequest \rightarrow Parameter \rightarrow Service
Service:
Parameter→BusinessProcess→ResultParameter \rightarrow BusinessProcess \rightarrow Result
因此:
Controller=RequestCoordinationController= RequestCoordination Service=BusinessCoordinationService= BusinessCoordination
例如用户创建机器个体:
Controller
↓
接收 type、name
↓
验证基础参数
↓
调用 MachineIndividualService
然后:
MachineIndividualService
↓
创建个体
↓
初始化结构
↓
调用 Engine
↓
Repository 保存
↓
返回结果
Controller 不应该自己完成整个创建流程。
236.12 ICAI Controller与Service
ICAI 的 Controller 可以调用不同的 Service。
例如:
IndividualController
├── IndividualService
├── CognitiveService
├── GoalService
├── CapabilityService
├── MethodService
├── DecisionService
├── BehaviorService
├── MemoryService
└── MaintenanceService
请求:
Request→IndividualControllerRequest \rightarrow IndividualController
根据请求类型:
Controller→IndividualServiceController \rightarrow IndividualService
或者:
Controller→CognitiveServiceController \rightarrow CognitiveService
或者:
Controller→BehaviorServiceController \rightarrow BehaviorService
因此 Controller 是不同系统功能之间的请求入口。
236.13 返回结果
Service 执行完成以后,会返回处理结果。
定义:
ServiceResult={Status,Data,Message,Code,Errors}ServiceResult= \{ Status, Data, Message, Code, Errors \}
例如:
$result = array(
'status' => true,
'data' => $individual,
'message' => '创建成功',
'code' => 200
);
Controller 接收到:
ServiceResultServiceResult
以后,根据请求类型决定如何输出。
如果是页面请求:
Result→ViewResult \rightarrow View
如果是 API 请求:
Result→JSONResult \rightarrow JSON
因此:
Controller→ResponseController \rightarrow Response
236.14 HTML页面返回
传统后台管理系统通常需要返回 HTML 页面。
流程:
Request→Controller→Service→Result→ViewData→Smarty→HTMLRequest \rightarrow Controller \rightarrow Service \rightarrow Result \rightarrow ViewData \rightarrow Smarty \rightarrow HTML
例如:
public function index()
{
$result = $this->service->list();
return $this->view->display(
'individual/index.tpl',
array(
'data' => $result
)
);
}
Controller 负责把 Service 结果转换为 View 所需要的数据。
因此:
ServiceResult→ViewData→SmartyServiceResult \rightarrow ViewData \rightarrow Smarty
236.15 JSON结果返回
如果请求来自 API 或 AJAX,则 Controller 可以返回 JSON。
例如:
public function apiCreate()
{
$params = $this->getRequestParams();
$result = $this->service->create($params);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result);
}
形成:
Request→Controller→Service→Result→JSONRequest \rightarrow Controller \rightarrow Service \rightarrow Result \rightarrow JSON
因此 Controller 需要根据请求类型决定结果表达方式,而不是改变 Service 的核心业务结果。
236.16 页面跳转
Controller 的另一项重要职责是页面跳转。
例如:
POST→Create→Success→Redirect→ListPOST \rightarrow Create \rightarrow Success \rightarrow Redirect \rightarrow List
PHP 中可以使用:
header('Location: /admin/individual/index.php');
exit;
形成:
提交表单
↓
Controller
↓
Service
↓
创建成功
↓
页面跳转
↓
列表页面
页面跳转通常用于避免用户刷新页面时重复提交数据。
典型流程:
POST→Process→Redirect→GETPOST \rightarrow Process \rightarrow Redirect \rightarrow GET
这可以形成清晰的请求生命周期。
236.17 成功与失败处理
Controller 必须能够处理 Service 的不同结果。
定义:
ResultStatus∈{Success,Failed,Invalid,Blocked,NotFound,Unauthorized,Error}ResultStatus\in \{ Success, Failed, Invalid, Blocked, NotFound, Unauthorized, Error \}
成功:
Success→View/RedirectSuccess \rightarrow View/Redirect
失败:
Failed→ErrorResponseFailed \rightarrow ErrorResponse
参数错误:
Invalid→ParameterErrorInvalid \rightarrow ParameterError
对象不存在:
NotFound→404NotFound \rightarrow 404
权限不足:
Unauthorized→403Unauthorized \rightarrow 403
因此:
ServiceResult→ControllerResultHandler→ResponseServiceResult \rightarrow ControllerResultHandler \rightarrow Response
236.18 Controller错误处理
Controller 不应该隐藏 Service 或 Engine 的真实错误。
例如:
Service→ErrorService \rightarrow Error
Controller 应该将错误转换成明确的系统响应:
if (!$result['status']) {
return $this->error(
$result['message']
);
}
但不应该:
try {
// ...
} catch (Exception $e) {
return '操作成功';
}
因为:
RealError≠SuccessRealError\neq Success
ICAI 工程要求:
真实结果→真实返回真实结果 \rightarrow 真实返回
不能把失败结果伪装成成功结果。
236.19 Controller不承担核心认知计算
ICAI Controller 必须严格保持职责边界。
例如:
Controller
↓
读取请求
↓
调用 CognitiveService
而不是:
Controller
↓
对象识别
↓
属性计算
↓
状态计算
↓
关系计算
↓
知识计算
↓
需求判断
↓
目标形成
↓
能力匹配
↓
决策
后者会造成 Controller 业务膨胀。
正确结构:
Controller→CognitiveService→CognitiveEngineController \rightarrow CognitiveService \rightarrow CognitiveEngine
例如:
Object→Attribute→State→Relation→Scene→KnowledgeObject \rightarrow Attribute \rightarrow State \rightarrow Relation \rightarrow Scene \rightarrow Knowledge
由 CognitiveEngine 负责。
Controller 只负责把请求送入正确的 Service。
236.20 Controller工程类模型
基础 Controller 可以定义为:
class BaseController
{
protected $request;
protected $response;
protected $view;
public function __construct(
$request,
$response,
$view
) {
$this->request = $request;
$this->response = $response;
$this->view = $view;
}
protected function getParam($name, $default = null)
{
return $default;
}
protected function json($data)
{
return $data;
}
protected function redirect($url)
{
return $url;
}
protected function render($template, $data = array())
{
return $this->view->display(
$template,
$data
);
}
}
具体 Controller:
class IndividualController extends BaseController
{
protected $individualService;
public function __construct(
$request,
$response,
$view,
$individualService
) {
parent::__construct(
$request,
$response,
$view
);
$this->individualService =
$individualService;
}
public function index()
{
$result =
$this->individualService->list();
return $this->render(
'individual/index.tpl',
array(
'result' => $result
)
);
}
public function create()
{
return $this->render(
'individual/create.tpl'
);
}
public function store()
{
$params = array(
'type' => $this->getParam('type'),
'name' => $this->getParam('name')
);
$result =
$this->individualService
->create($params);
if (!$result['status']) {
return $this->json($result);
}
return $this->redirect(
'/admin/individual/index.php'
);
}
}
这里的关键关系是:
IndividualController→IndividualServiceIndividualController \rightarrow IndividualService
而不是:
IndividualController→MySQLIndividualController \rightarrow MySQL
236.21 Controller生命周期
Controller 本身也可以具有简单的运行过程:
Request→Instantiate→Receive→Validate→CallService→ProcessResult→ResponseRequest \rightarrow Instantiate \rightarrow Receive \rightarrow Validate \rightarrow CallService \rightarrow ProcessResult \rightarrow Response
完整过程:
请求
↓
路由
↓
Controller实例化
↓
接收请求
↓
读取参数
↓
参数验证
↓
Service调用
↓
获得结果
↓
结果判断
├── 成功 → 返回/跳转
├── 失败 → 错误返回
└── 异常 → 异常处理
↓
Response
因此:
ControllerRuntime=Receive+Process+Call+Return+RedirectControllerRuntime= Receive+ Process+ Call+ Return+ Redirect
236.22 Controller与页面跳转关系
后台系统通常存在多个页面:
列表页
↓
创建页
↓
提交
↓
详情页
↓
编辑页
↓
更新
↓
列表页
Controller 可以承担页面之间的请求协调。
例如:
GET/Create→CreatePageGET/Create \rightarrow CreatePage POST/Create→CreateServicePOST/Create \rightarrow CreateService Success→Redirect/ListSuccess \rightarrow Redirect/List
编辑:
GET/Edit→EditPageGET/Edit \rightarrow EditPage POST/Update→UpdateServicePOST/Update \rightarrow UpdateService Success→Redirect/ListSuccess \rightarrow Redirect/List
因此页面跳转本质上属于:
Controller→NavigationController \rightarrow Navigation
而不是 Service 的核心职责。
236.23 Controller与Service与Engine三级关系
ICAI 工程可以建立三级职责:
Controller→Service→EngineController \rightarrow Service \rightarrow Engine
Controller:
Request ProcessingRequest\ Processing
Service:
Business ProcessBusiness\ Process
Engine:
Domain CalculationDomain\ Calculation
例如能力请求:
Request→CapabilityControllerRequest \rightarrow CapabilityController
然后:
CapabilityController→CapabilityServiceCapabilityController \rightarrow CapabilityService
再:
CapabilityService→CapabilityEngineCapabilityService \rightarrow CapabilityEngine
Engine 执行:
Goal→CapabilityRequirement→CapabilityMatchingGoal \rightarrow CapabilityRequirement \rightarrow CapabilityMatching
最后:
CapabilityEngine→CapabilityService→CapabilityController→ResponseCapabilityEngine \rightarrow CapabilityService \rightarrow CapabilityController \rightarrow Response
236.24 Controller与Repository的边界
Controller 不应该直接访问 Repository。
错误结构:
Controller→RepositoryController \rightarrow Repository
正确结构:
Controller→Service→RepositoryController \rightarrow Service \rightarrow Repository
如果存在 Engine:
Controller→Service→Engine→RepositoryController \rightarrow Service \rightarrow Engine \rightarrow Repository
这样可以避免 Controller 与数据库结构产生直接耦合。
例如数据库表发生变化:
MySQL→RepositoryMySQL \rightarrow Repository
只需要调整 Repository 和相关 Service,而不应该让所有 Controller 都直接修改数据库操作。
236.25 Controller与Domain Object的边界
Controller 可以接收或输出 Domain Object 的数据,但不应该承担 Domain Object 的核心领域责任。
例如:
Controller
↓
IndividualService
↓
MachineIndividual
而不是:
Controller
↓
直接修改 MachineIndividual 所有内部状态
Domain Object 自身负责:
Identity+State+Relation+ResponsibilityIdentity+ State+ Relation+ Responsibility
Controller 负责:
Request+ResponseRequest+ Response
因此:
ControllerResponsibility∩DomainResponsibilityControllerResponsibility \cap DomainResponsibility
应该尽量减少。
236.26 Controller工程统一模型
将本章五项职责统一起来:
RequestReceive→ParameterProcess→ServiceCall→ResultReturn→PageRedirect\boxed{ RequestReceive \rightarrow ParameterProcess \rightarrow ServiceCall \rightarrow ResultReturn \rightarrow PageRedirect }
其中:
请求接收
Request→ControllerRequest\rightarrow Controller
参数处理
Controller→ParameterController\rightarrow Parameter
Service调用
Parameter→ServiceParameter\rightarrow Service
返回结果
ServiceResult→ResponseServiceResult\rightarrow Response
页面跳转
Success→RedirectSuccess\rightarrow Redirect
最终:
Request→Controller→Parameter→Service→Result→Response\boxed{ Request \rightarrow Controller \rightarrow Parameter \rightarrow Service \rightarrow Result \rightarrow Response }
页面请求增加:
Result→Redirect→NewRequestResult \rightarrow Redirect \rightarrow NewRequest
236.27 ICAI Controller完整工程链
ICAI 的 Controller 最终进入完整工程体系:
HTTPRequest→Router→Controller→Service→Engine→DomainObject→Repository→MySQL\boxed{ HTTPRequest \rightarrow Router \rightarrow Controller \rightarrow Service \rightarrow Engine \rightarrow DomainObject \rightarrow Repository \rightarrow MySQL }
返回:
MySQL→Repository→DomainObject→Engine→Service→Controller→Response\boxed{ MySQL \rightarrow Repository \rightarrow DomainObject \rightarrow Engine \rightarrow Service \rightarrow Controller \rightarrow Response }
页面:
Controller→ViewData→Smarty→HTMLController \rightarrow ViewData \rightarrow Smarty \rightarrow HTML
跳转:
Controller→Redirect→NewRequestController \rightarrow Redirect \rightarrow NewRequest
由此形成完整 MVC 请求闭环。
236.28 本章总结
Controller 是 ICAI MVC 工程体系中的请求控制层,其核心职责可以概括为:
接收请求→处理参数→调用Service→返回结果→页面跳转\boxed{ 接收请求 \rightarrow 处理参数 \rightarrow 调用Service \rightarrow 返回结果 \rightarrow 页面跳转 }
Controller 不负责替代 Service,也不负责替代 Engine,更不负责直接承担数据库操作。
完整职责边界为:
Controller=请求控制\boxed{ Controller=请求控制 } Service=业务流程\boxed{ Service=业务流程 } Engine=领域计算\boxed{ Engine=领域计算 } DomainObject=领域对象\boxed{ DomainObject=领域对象 } Repository=数据持久化\boxed{ Repository=数据持久化 } MySQL=数据存储\boxed{ MySQL=数据存储 }
因此 ICAI 的 MVC 工程最终形成:
Request→Controller→Service→Engine→DomainObject→Repository→MySQL\boxed{ Request \rightarrow Controller \rightarrow Service \rightarrow Engine \rightarrow DomainObject \rightarrow Repository \rightarrow MySQL }
返回方向:
MySQL→Repository→DomainObject→Engine→Service→Controller→Response\boxed{ MySQL \rightarrow Repository \rightarrow DomainObject \rightarrow Engine \rightarrow Service \rightarrow Controller \rightarrow Response }
而页面显示进一步形成:
Controller→ViewData→Smarty→HTMLController \rightarrow ViewData \rightarrow Smarty \rightarrow HTML
至此,Controller 完成了 ICAI 理论模型进入实际 Web/MVC 运行环境的重要入口,使外部请求能够按照明确的工程层次进入 ICAI 的 Service、Engine、Domain Object 和数据持久化体系。