OpenCart中的调度工作原理

作为一名程序员,了解您正在使用的系统的流程很重要,这不仅是为了能够在需要时进行更改,而且因为这样做可以使您信心倍增。

今天,我们将选择OpenCart并对其进行剖析,以了解调度过程的基础。 我们将从调度过程的全部内容开始,并且随着我们的前进,我们将从框架的不同部分探索代码片段。

我将为本文选择OpenCart的最新版本,但其流程在早期版本中或多或少都相似。

简而言之调度

在任何基于Web的应用程序中,调度过程都用于查找传入请求URL与框架中相应模块之间的映射。 当然,实现因框架而异,但基本概念保持不变。 因此,这是调度程序的一些职责:

  • 从请求对象中获取适当的参数。
  • 查找相应的模块和要调用的动作。
  • 如果找到了相应的模块和动作,则分配过程结束。
  • 如果找不到给定请求的模块,则将设置默认操作,并且分发过程结束。

让我们尝试使用OpenCart中的一个简单示例来理解这一点。 要从前端创建新用户,需要使用http://www.youropencartstore.com/index.php?route=account/register在网站上进行注册。 让我们总结一下OpenCart为呈现请求的页面而采取的步骤。

  • 首先,它检查“ route”查询字符串变量的存在,否则它将“ common / home”设置为页面的默认“ route”。
  • 在我们的例子中,它存在,因此它将设置必需的变量并触发调度过程。
  • 在调度过程的开始,它将运行一些用于执行常见任务的“ preAction”操作。 我们将在本文的后面部分讨论“ preAction”内容。
  • 最后,它将检查当前“ route”变量是否有可用的控制器文件,如果有,则将调用该文件来获取响应。
  • 如果没有控制器文件可用于请求的“ route”变量,它将执行“ error / not_found”操作,该操作向用户显示“找不到页面”消息。

因此,这是OpenCart如何遍历请求的URL并返回响应的顶层视图。 在下一节中,我们将更深入地了解它是如何做到的。

顺其自然

继续并在OpenCart的文档根目录中打开index.php文件。 该文件中发生了很多事情,但不要被淹没,因为大多数只是整个框架中使用的对象的设置。

让我们直接从该文件中提取我们感兴趣的片段。

// Front Controller
$controller = new Front($registry);

// Maintenance Mode
$controller->addPreAction(new Action('common/maintenance'));

// SEO URL's
$controller->addPreAction(new Action('common/seo_url'));

与大多数其他框架一样,OpenCart也依赖于前控制器模式,因此应用程序中的所有请求都有一个公共入口点。

首先,我们创建前端控制器的实例,并将其分配给$controller变量。 紧接着,我们正在调用addPreAction方法来添加几个动作。

现在,这带来了另一个话题:什么是“ preAction”? 简单来说,preAction是一个动作,它将在任何页面上的请求动作之前执行。 例如,当用户单击任何页面时,您要在返回实际响应之前检查站点是否处于维护模式。 在这种情况下,您可以使用preAction,以便将用户重定向到维护页面(如果处于打开状态)。

另外,我们还添加了common/seo_url作为preAction,因为在启用SEO的网站上,我们希望在实际分派开始之前获取相应的路由变量。

让我们继续下一个重要的代码片段。

// Router
if (isset($request->get['route'])) {
    $action = new Action($request->get['route']);
} else {
    $action = new Action('common/home');
}

它检查“ route”查询字符串变量的存在,如果存在,我们将通过传递当前的“ route”值作为构造函数参数来创建Action类的实例。 如果不存在,我们将对主页路由URI( common/home执行相同的操作。

$action变量设置为适当的值后,我们继续下一个代码段。

// Dispatch
$controller->dispatch($action, new Action('error/not_found'));

最后,我们调用前端控制器类的dispatch方法。 继续打开system/engine/front.php并找到以下片段。

public function dispatch($action, $error) {
    $this->error = $error;

    foreach ($this->pre_action as $pre_action) {
        $result = $this->execute($pre_action);

        if ($result) {
            $action = $result;

            break;
        }
    }

    while ($action) {
        $action = $this->execute($action);
    }
}

这是所有魔术发生的方法! 首先,它执行前面讨论的所有“ preAction”。 此外,在while循环中,它将尝试执行我们当前的$action ,将其作为execute方法的参数传递。

让我们遵循同一文件中execute方法的定义。

private function execute($action) {
	$result = $action->execute($this->registry);

	if (is_object($result)) {
		$action = $result;
	} elseif ($result === false) {
		$action = $this->error;

    	$this->error = '';
	} else {
		$action = false;
	}

	return $action;
}

在第一行,将execute Action类的execute方法。 不要将其与Front控制器类的execute方法混淆。 打开文件system/engine/action.php ,就在这里。

public function execute($registry) {
	// Stop any magical methods being called
	if (substr($this->method, 0, 2) == '__') {
		return false;
	}

	if (is_file($this->file)) {
		include_once($this->file);

		$class = $this->class;

		$controller = new $class($registry);

		if (is_callable(array($controller, $this->method))) {
			return call_user_func(array($controller, $this->method), $this->args);
		} else {
			return false;
		}
	} else {
		return false;
	}
}

这里要注意的重要一点是,当在index.php实例化操作对象时, Action类已经在构造函数中设置了必需的变量。 它设置了fileclassmethod属性,这些属性将在execute方法中使用。 为了使事情不那么复杂,我们将只讨论execute方法,尽管我建议您遍历Action类的构造函数。

回到Action类的execute方法,它检查与当前路由关联的文件( $this->file )是否存在。 如果一切正常,它将包含该文件,并使用call_user_func函数调用该控制器类的相应方法( $this->method ),并返回响应。

如果关联的文件不可用,它将返回false 。 现在,让我们回到Front控制器类的execute方法中的代码段。 耐心点,我们快到了!

...
$result = $action->execute($this->registry);

if (is_object($result)) {
	$action = $result;
} elseif ($result === false) {
	$action = $this->error;

	$this->error = '';
} else {
	$action = false;
}

return $action;
...

一旦Action类的execute方法完成了该过程,它将返回结果并将其分配给$result变量。 现在,存在三种不同的可能性,其值存储在$result 。 让我们检查每个。

如果一切顺利,我们将在$result变量中提供HTML输出,因此$action变量将设置为false并结束过程。 这是最后一种情况。

回想一下,如果在Action类的execute方法中找不到相应的控制器文件,则返回false 。 在这种情况下, $action变量将设置为$this->error (error / not_found Action ),并向用户显示“找不到页面”。

最后,如果我们发现$result是对象本身,则将其设置为$action变量。 是的,这很奇怪:为什么在应该为请求的页面返回HTML输出的情况下,控制器方法究竟会返回另一个Action对象? 但这只是控制器将用户重定向到其他URL的方式之一。

让我们快速打开catalog/controller/common/maintenance.php文件并查看其运行情况。 在index方法中,如果满足某些条件,它将返回Action对象。

…
if (($route != 'payment' && $route != 'api') && !$this->user->isLogged()) {
    return new Action('common/maintenance/info');
}
…

因此,如您所见,它返回Action对象以将用户重定向到common/maintenance/info URL。 当然,前端控制器类的dispatch方法中有一个代码可以处理此行为。 回忆一下该方法中的代码片段-我保证这是本教程的最后一个代码片段。

...
while ($action) {
	$action = $this->execute($action);
}
...

因此,这是一个while循环,它将一直运行到找到$action变量设置为false为止! 更具体地说,当我们为用户提供有用的输出时,它将结束循环。

这就是旅程的终点​​。 我希望它不会像乍看起来那样复杂。

结论

今天,我们经历了OpenCart框架的重要方面-调度过程。 我们了解了调度的基础知识,并通过完整的流程来了解调度的工作原理。

如果您正在寻找其他OpenCart工具,实用程序,扩展等,以便可以在自己的项目中使用或用于自己的教育,请不要忘记查看我们在市场上提供的产品

如有任何疑问,请随时留下您的评论。 另外, Twitter是与我联系的另一种选择,我很快做出了回应。

翻译自: https://code.tutsplus.com/articles/how-dispatching-works-in-opencart--cms-21787

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值