1. 通常,很多人都是在控制器里直接调用view()方法渲染视图文件,因为很多框架都是这么干的,于是大家都这么干了,但这种方式并不好,使得view与controller极度耦合。
2. webman中的controller没有传递request对象,使得代码写起来有些繁琐,基本每个action要传递request,但如果在construct中传递request,就可以这么写:
```php
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
```
3. 可以利用中间件解决很多问题,但中间件无法处理控制器内部的业务逻辑,假设在调用action之前,我们希望业务逻辑通过是否有中断标识,决定是否真正调用action,用中间件搞感觉很麻烦,如果硬编码在每个action里,又觉得很繁琐,再有,我们想通过在调用action后统一处理action的返回结果,决定是否调用view渲染视图还是返回json等等。
修改后的代码:
```php
protected static function getCallback(string $plugin, string $app, $call, array $args = null, bool $withGlobalMiddleware = true, RouteObject $route = null)
{
$args = $args === null ? null : array_values($args);
$middlewares = [];
if ($route) {
$routeMiddlewares = array_reverse($route->getMiddleware());
foreach ($routeMiddlewares as $className) {
$middlewares[] = [$className, 'process'];
}
}
$middlewares = array_merge($middlewares, Middleware::getMiddleware($plugin, $app, $withGlobalMiddleware));
foreach ($middlewares as $key => $item) {
$middleware = $item[0];
if (is_string($middleware)) {
$middleware = static::container($plugin)->get($middleware);
} elseif ($middleware instanceof Closure) {
$middleware = call_user_func($middleware, static::container($plugin));
}
if (!$middleware instanceof MiddlewareInterface) {
throw new InvalidArgumentException('Not support middleware type');
}
$middlewares[$key][0] = $middleware;
}
$needInject = static::isNeedInject($call, $args);
if (is_array($call) && is_string($call[0])) {
$controllerReuse = static::config($plugin, 'app.controller_reuse', true);
if (!$controllerReuse) {
if ($needInject) {
$call = function ($request, ...$args) use ($call, $plugin) {
$call[0] = static::container($plugin)->make($call[0], [$request]);
if (true !== ($result = static::beforeCall($call[0], $call[1], $request))) {
return $result;
}
$reflector = static::getReflector($call);
$args = static::resolveMethodDependencies($plugin, $request, $args, $reflector);
// return $call(...$args);
return static::afterCall($call[0], $call[1], $call(...$args), $request);
};
$needInject = false;
} else {
$call = function ($request, ...$args) use ($call, $plugin) {
$call[0] = static::container($plugin)->make($call[0], [$request]);
if (true !== ($result = static::beforeCall($call[0], $call[1], $request))) {
return $result;
}
// return $call($request, ...$args);
return static::afterCall($call[0], $call[1], $call($request, ...$args), $request);
};
}
} else {
$call[0] = static::container($plugin)->get($call[0]);
}
}
if ($needInject) {
$call = static::resolveInject($plugin, $call);
}
if ($middlewares) {
$callback = array_reduce($middlewares, function ($carry, $pipe) {
return function ($request) use ($carry, $pipe) {
try {
return $pipe($request, $carry);
} catch (Throwable $e) {
return static::exceptionResponse($e, $request);
}
};
}, function ($request) use ($call, $args) {
try {
if ($args === null) {
$response = $call($request);
} else {
$response = $call($request, ...$args);
}
} catch (Throwable $e) {
return static::exceptionResponse($e, $request);
}
if (!$response instanceof Response) {
if (!is_string($response)) {
$response = static::stringify($response);
}
$response = new Response(200, [], $response);
}
return $response;
});
} else {
if ($args === null) {
$callback = $call;
} else {
$callback = function ($request) use ($call, $args) {
return $call($request, ...$args);
};
}
}
return $callback;
}
```
```php
protected static function beforeCall($controller, $action, $request)
{
if (false !== ($result = static::detectHalted($controller))) {
return $result;
}
static::doBeforeAction($controller, $action, $request);
if (false !== ($result = static::detectHalted($controller))) {
return $result;
}
return true;
}
protected static function afterCall($controller, $action, $response, $request)
{
$method = 'after' . ucfirst($action) . 'Action';
if (method_exists($controller, $method)) {
$response = $controller->{$method}($response, $request);
}
if (method_exists($controller, 'afterAction')) {
$response = $controller->afterAction($response, $request);
}
return $response;
}
protected static function detectHalted($controller)
{
if (method_exists($controller, 'halted') && $controller->halted()) {
return $controller->getHaltedResult();
}
return false;
}
protected static function doBeforeAction($controller, $action, $request)
{
if (method_exists($controller, 'beforeAction')) {
$controller->beforeAction($request);
}
$method = 'before' . ucfirst($action) . 'Action';
if (method_exists($controller, $method)) {
$controller->{$method}($request);
}
}
```
食用示例:
```php
namespace app\controller;
use Webman\App;
use support\Model;
use support\Request;
use support\Response;
/**
* 基础控制器
*/
class Base
{
protected $halted = false; //标识是否中断
protected $haltedResult = null; //接收中断返回的内容
protected $request = null;
public function __construct(Request $request)
{
$this->request = $request;
}
public function halted($flag = null)
{
if (is_bool($flag)) {
$this->halted = $flag;
return;
}
return $this->halted;
}
public function getHaltedResult()
{
return $this->haltedResult;
}
// 统一处理action返回的结果
public function afterAction($data)
{
$script = $this->request->script;
if (!$data) {
return view($script, $data);
}
return $data;
}
}
```