1. 程式人生 > >iWebShop 二次開發之商城後臺模板渲染流程

iWebShop 二次開發之商城後臺模板渲染流程


iwebshop檢視分兩塊,一塊是公共模組叫layouts(佈局),一塊叫viewContent(檢視內容)。
layouts是全域性的,即是一個網站的基礎排版,比如一個經典的三欄佈局,上(網站logo、主選單)、左(左邊選單)、右(右邊內容)。

如下圖所示:


在上面佈局的右邊即是viewContent(檢視內容),這部分內容是由使用者定義的,即我們所寫的檢視會自動插入到右邊。
那麼我們看看admin.html佈局檔案結構,開啟檔案:views/sysdefult/layouts/admin.html
如下圖所示:


我們現在看這個檔案lib/core/webapplication_class.php
找到execRequest

方法,程式碼如下:

/**
 * @brief 請求執行方法,是application執行的入口方法
 */
public function execRequest()
{
	IUrl::beginUrl();
	$ctrlId   = IUrl::getInfo("controller");
	$actionId = IUrl::getInfo('action');
	IInterceptor::run("onBeforeCreateController",$ctrlId);
	//重點看這句,這一句主要是建立一個控制器物件,接著我們看下一段建立控制器的程式碼
	$this->controller = $this->createController($ctrlId);
	IInterceptor::run("onCreateController",$this->controller);
	//以及這句程式碼
	$this->controller->run($actionId);
	IInterceptor::run("onFinishController",$this->controller);
}

重點看這句,這一句主要是建立一個控制器物件
$this->controller = $this->createController($ctrlId);
以及這句程式碼
$this->controller->run($actionId);

接著我們看建立控制器(createController)的程式碼實現:

/**
 * @brief 建立當前的Controller物件
 * @param string $ctrlId 控制器ID
 * @return object Controller物件
 */
public function createController($ctrlId)
{
	$ctrlId     = $ctrlId ? $ctrlId : $this->defaultController;
	$ctrlObject = null;
	$ctrlFile   = $this->basePath."controllers/".$ctrlId.".php";

	if(is_file($ctrlFile) && class_exists($ctrlId) && get_parent_class($ctrlId) == "IController")
	{
		$ctrlObject = new $ctrlId($this,$ctrlId);
	}
	//主要看這一句的new IController,這裡通過IController這個類建立一個控制器
	return $ctrlObject ? $ctrlObject : new IController($this,$ctrlId);
}
主要看上面程式碼的這一句:

return $ctrlObject ? $ctrlObject : new IController($this,$ctrlId);

這裡通過IController這個類建立一個控制器。

接著我們看IController這個類的實現,開啟檔案:lib/web/controller/controller_class.php
接著找到IControllerrun方法中的這句程式碼$actionObj = $this->createAction($actionId);
然後我們在IController類中找到上面$this->createAction方法的實現,在createAction方法中找到這句程式碼:
$this->action = new IViewAction($this,$actionId);
現在我們看IViewAction類的實現,開啟檔案:lib/web/action/view_action.php
找到IViewAction類中的run方法中的這句程式碼$controller->render($this->view);
乍一看,我們現在又要回到控制器類了,開啟檔案:lib/web/controller/controller_class.php
找到render方法中的這句程式碼$output = $this->renderView($view,$data,$return);

renderView方法的實現可以在控制器基類中找到,開啟檔案:lib/web/controller/controller_class.php
然後再在renderView方法中找到這句程式碼:
$layoutFile = $this->getLayoutFile().$this->extend;
哈哈...我們終於找到了生成佈局檔案的入口點了。
然後getLayoutFile的實現又在controllerbase的子類中實現
開啟檔案:lib/web/controller/controller_class.php就可找到getLayoutFile的實現,程式碼如下:

/**
 * @brief 獲取layout檔案路徑(無副檔名)
 * @return string layout路徑
 */
public function getLayoutFile()
{
	//$this->layout這句是一定要注意的,佈局的檔名是使用者自己寫控制器的時候繼承IController時賦值的,
	//換而言之就是使用者去定義佈局檔名是什麼。
	if(!$this->layout)
		return false;
			
	return $this->getViewPath().$this->defaultLayoutPath.DIRECTORY_SEPARATOR.$this->layout;
}

下面是renderView的完整實現:
/**
 * @brief 渲染處理 交流QQ:82530662
 * @param string $viewFile 要渲染的頁面
 * @param string or array $rdata 要渲染的資料
 * @param boolean $return 是否返回路徑名稱
 */
public function renderView($viewFile,$rdata=null,$return=false)
{
	//要渲染的檢視
	$renderFile = $viewFile.$this->extend;

	//檢查檢視檔案是否存在
	if(is_file($renderFile))
	{
		//控制器的檢視(需要進行編譯並且生成可以執行的php檔案)
		if(stripos($renderFile,IWEB_PATH.'web/view/')===false)
		{
			//生成檔案路徑
			$runtimeFile = str_replace($this->app->getBasePath(),$this->app->getRuntimePath(),$viewFile.".php");

			//layout檔案
			$layoutFile = $this->getLayoutFile().$this->extend;
			$issetLayout= is_file($layoutFile);
							
			if($this->isRanderCache == false || !is_file($runtimeFile) || (filemtime($renderFile) > filemtime($runtimeFile)) || ($issetLayout && (filemtime($layoutFile) > filemtime($runtimeFile))))
			{
				//獲取view內容
				$viewContent = file_get_contents($renderFile);
									
				//處理layout
				if($issetLayout && stripos($viewContent,"<html") === false)
				{
											
					$viewContent = $this->renderLayout($layoutFile,$viewContent);
				}

				//標籤編譯
				$inputContent = $this->tagResolve($viewContent);

				//建立檔案
				$fileObj  = new IFile($runtimeFile,'w+');
				$fileObj->write($inputContent);
				$fileObj->save();
				unset($fileObj);
			}
		}
		else
		{
			$runtimeFile = $renderFile;
		}
					
		return $return ? $runtimeFile : $this->requireFile($runtimeFile,$rdata);
	}
	else
	{
		return false;
	}
}