写一个MVC的模板解析方法_PHP教程
MVC是模型(Model)、视图(View)和控制(Controller)的缩写,PHP中采用MVC模式的目的是实现Web系统的职能分工,通俗的说就是把业务逻辑处理从用户界面视图中分离出来。使Web系统的开发与维护更加方便,从而有效的节省人力物力,受到了越来越多企业的青睐。
模板引擎是MVC模式建立过程的重要方法,开发者可以设计一套赋予含义的标签,通过技术解析处理有效的把数据逻辑处理从界面模板中提取出来,通过解读标签的含义把控制权提交给相应业务逻辑处理程序,从而获取到需要的数据,以模板设计的形式展现出来,使设计人员能把精力更多放在表现形式上。下面是我对模板引擎的认识与设计方法:
说的好听些叫模板引擎,实际就是解读模板数据的过程(个人观点^^)。通过我对建站方面的思考认识,网站在展现形式上无非归纳为单条和多条两种形式,那么我们可以设定两种对应标签(如data、list)来处理这两种情况,关键点在于解决两种标签的多层相互嵌套问题,基本适合实现80%界面形式。
解读模板的方法有多种,常用的包括字符串处理(解决嵌套稍麻烦)、正则表达式。在这里我选用的正则表达式,下面是我的处理方法(本文仅提供思路和参考代码,可能不能直接使用)。
模板文件解析类:
<?php class Template { public $html, $vars, $bTag, $eTag; public $bFlag='{', $eFlag='}', $pfix='zmm:'; private $folder, $file; function __construct($vars=array()) { !empty($vars) && $this->vars = $vars; !empty($GLOBALS['cfg_tag_prefix']) && $this->pfix = $GLOBALS['cfg_tag_prefix'].':'; $this->bTag = $this->bFlag.$this->pfix; $this->eTag = $this->bFlag.'\/'.$this->pfix; empty(Tags::$vars) && Tags::$vars = &$this->vars; } public function LoadTpl($tpl) { $this->file = $this->GetTplPath($tpl); Tags::$file = &$this->file; if (is_file($this->file)) { if ($this->GetTplHtml()) { $this->SetTplTags(); } else { exit('模板文件加载失败!'); } } else { exit('模板文件['.$this->file.']不存在!'); } } private function GetTplPath($tpl) { $this->folder = WEBSITE_DIRROOT. $GLOBALS['cfg_tpl_root']; return $this->folder.'/'.$tpl; } private function GetTplHtml() { $html = self::FmtTplHtml(file_get_contents($this->file)); if (!empty($html)) { $callFunc = Tags::$prefix.'Syntax'; $this->html = Tags::$callFunc($html, new Template()); } else { exit('模板文件内容为空!'); } return true; } static public function FmtTplHtml($html) { return preg_replace('/(\r)|(\n)|(\t)|(\s{2,})/is', '', $html); } public function Register($vars=array()) { if (is_array($vars)) { $this->vars = $vars; Tags::$vars = &$this->vars; } } public function Display($bool=false, $name="", $time=0) { if (!empty($this->html)) { if ($bool && !empty($name)) { if (!is_int($time)) $time = 600; $cache = new Cache($time); $cache->Set($name, $this->html); } echo $this->html; flush(); } else { exit('模板文件内容为空!'); } } public function SetAssign($souc, $info) { if (!empty($this->html)) { $this->html = str_ireplace($souc, self::FmtTplHtml($info), $this->html); } else { exit('模板文件内容为空!'); } } private function SetTplTags() { $this->SetPanelTags(); $this->SetTrunkTags(); $this->RegHatchVars(); } private function SetPanelTags() { $rule = $this->bTag.'([^'.$this->eFlag.']+)\/'.$this->eFlag; preg_match_all('/'.$rule.'/ism', $this->html, $out_matches); $this->TransTag($out_matches, 'panel'); unset($out_matches); } private function SetTrunkTags() { $rule = $this->bTag.'(\w+)\s*([^'.$this->eFlag.']*?)'.$this->eFlag. '((?:(?!'.$this->bTag.')[\S\s]*?|(?R))*)'.$this->eTag.'\\1\s*'.$this->eFlag; preg_match_all('/'.$rule.'/ism', $this->html, $out_matches); $this->TransTag($out_matches, 'trunk'); unset($out_matches); } private function TransTag($result, $type) { if (!empty($result[0])) { switch ($type) { case 'panel' : { for ($i = 0; $i < count($result[0]); $i ++) { $strTag = explode(' ', $result[1][$i], 2); if (strpos($strTag[0], '.')) { $itemArg = explode('.', $result[1][$i], 2); $callFunc = Tags::$prefix.ucfirst($itemArg[0]); if (method_exists('Tags', $callFunc)) { $html = Tags::$callFunc(chop($itemArg[1])); if ($html !== false) { $this->html = str_ireplace($result[0][$i], $html, $this->html); } } } else { $rule = '^([^\s]+)\s*([\S\s]+)$'; preg_match_all('/'.$rule.'/is', trim($result[1][$i]), $tmp_matches); $callFunc = Tags::$prefix.ucfirst($tmp_matches[1][0]); if (method_exists('Tags', $callFunc)) { $html = Tags::$callFunc($tmp_matches[2][0]); if ($html !== false) { $this->html = str_ireplace($result[0][$i], $html, $this->html); } } unset($tmp_matches); } } break; } case 'trunk' : { for ($i = 0; $i < count($result[0]); $i ++) { $callFunc = Tags::$prefix.ucfirst($result[1][$i]); if (method_exists('Tags', $callFunc)) { $html = Tags::$callFunc($result[2][$i], $result[3][$i]); $this->html = str_ireplace($result[0][$i], $html, $this->html); } } break; } default: break; } } else { return false; } } private function RegHatchVars() { $this->SetPanelTags(); } function __destruct() {} } ?>
标签解析类:(目前暂时提供data、list两种标签的解析,说明思路)
<?php class Tags { static private $attrs=null; static public $file, $vars, $rule, $prefix='TAG_'; static public function TAG_Syntax($html, $that) { $rule = $that->bTag.'if\s+([^'.$that->eFlag.']+)\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php if (\\1) { ?>', $html); $rule = $that->bTag.'elseif\s+([^'.$that->eFlag.']+)\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php } elseif (\\1) { ?>', $html); $rule = $that->bTag.'else\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php } else { ?>', $html); $rule = $that->bTag.'loop\s+(\S+)\s+(\S+)\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2) { ?>', $html); $rule = $that->bTag.'loop\s+(\S+)\s+(\S+)\s+(\S+)\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2 => \\3) { ?>', $html); $rule = $that->eTag.'(if|loop)\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php } ?>', $html); $rule = $that->bTag.'php\s*'.$that->eFlag.'((?:(?!'. $that->bTag.')[\S\s]*?|(?R))*)'.$that->eTag.'php\s*'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism', '<?php \\1 ?>', $html); return self::TAG_Execute($html); } static public function TAG_List($attr, $html) { if (!empty($html)) { if (self::TAG_HaveTag($html)) { return self::TAG_DealTag($attr, $html, true); } else { return self::TAG_GetData($attr, $html, true); } } else { exit('标签{list}的内容为空!'); } } static public function TAG_Data($attr, $html) { if (!empty($html)) { if (self::TAG_HaveTag($html)) { return self::TAG_DealTag($attr, $html, false); } else { return self::TAG_GetData($attr, $html, false); } } else { exit('标签{data}的内容为空!'); } } static public function TAG_Execute($html) { ob_clean(); ob_start(); if (!empty(self::$vars)) { is_array(self::$vars) && extract(self::$vars, EXTR_OVERWRITE); } $file_inc = WEBSITE_DIRINC.'/buffer/'. md5(uniqid(rand(), true)).'.php'; if ($fp = fopen($file_inc, 'xb')) { fwrite($fp, $html); if (fclose($fp)) { include($file_inc); $html = ob_get_contents(); } unset($fp); } else { exit('模板解析文件生成失败!'); } ob_end_clean(); @unlink($file_inc); return $html; } static private function TAG_HaveTag($html) { $bool_has = false; $tpl_ins = new Template(); self::$rule = $tpl_ins->bTag.'([^'.$tpl_ins->eFlag.']+)\/'.$tpl_ins->eFlag; $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html); self::$rule = $tpl_ins->bTag.'(\w+)\s*([^'.$tpl_ins->eFlag.']*?)'.$tpl_ins->eFlag. '((?:(?!'.$tpl_ins->bTag.')[\S\s]*?|(?R))*)'.$tpl_ins->eTag.'\\1\s*'.$tpl_ins->eFlag; $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html); unset($tpl_ins); return $bool_has; } static private function TAG_DealTag($attr, $html, $list) { preg_match_all('/'.self::$rule.'/ism', $html, $out_matches); if (!empty($out_matches[0])) { $child_node = array(); for ($i = 0; $i < count($out_matches[0]); $i ++) { $child_node[] = $out_matches[3][$i]; $html = str_ireplace($out_matches[3][$i], '{-->>child_node_'.$i.'<<--}', $html); } $html = self::TAG_GetData($attr, $html, $list); for ($i = 0; $i < count($out_matches[0]); $i ++) { $html = str_ireplace('{-->>child_node_'.$i.'<<--}', $child_node[$i], $html); } preg_match_all('/'.self::$rule.'/ism', $html, $tmp_matches); if (!empty($tmp_matches[0])) { for ($i = 0; $i < count($tmp_matches[0]); $i ++) { $callFunc = self::$prefix.ucfirst($tmp_matches[1][$i]); if (method_exists('Tags', $callFunc)) { $temp = self::$callFunc($tmp_matches[2][$i], $tmp_matches[3][$i]); $html = str_ireplace($tmp_matches[0][$i], $temp, $html); } } } unset($tmp_matches); } unset($out_matches); return $html; } static private function TAG_GetData($attr, $html, $list=false) { if (!empty($attr)) { $attr_ins = new Attbt($attr); $attr_arr = $attr_ins->attrs; if (is_array($attr_arr)) { extract($attr_arr, EXTR_OVERWRITE); $source = table_name($source, $column); $rule = '\[field:\s*(\w+)\s*([^\]]*?)\s*\/?]'; preg_match_all('/'.$rule.'/is', $html, $out_matches); $data_str = ''; $data_ins = new DataSql(); $attr_where = $attr_order = ''; if (!empty($where)) { $where = str_replace(',', ' and ', $where); $attr_where = ' where '. $where; } if (!empty($order)) { $attr_order = ' order by '.$order; } else { $fed_name = ''; $fed_ins = $data_ins->GetFedNeedle($source); $fed_cnt = $data_ins->GetFedCount($fed_ins); for ($i = 0; $i < $fed_cnt; $i ++) { $fed_flag = $data_ins->GetFedFlag($fed_ins, $i); if (preg_match('/auto_increment/ism', $fed_flag)) { $fed_name = $data_ins->GetFedName($fed_ins, $i); break; } } if (!empty($fed_name)) $attr_order = ' order by '.$fed_name.' desc'; } if ($list == true) { if (empty($source) && empty($sql)) { exit('标签{list}必须指定source属性!'); } $attr_rows = $attr_page = ''; if ($rows > 0) { $attr_rows = ' limit 0,'.$rows; } if (!empty($sql)) { $data_sql = $sql; } else { $data_sql = 'select * from `'.$source.'`'. $attr_where.$attr_order.$attr_rows; } if ($pages=='true' && !empty($size)) { $data_num = $data_ins->GetRecNum($data_sql); $page_cnt = ceil($data_num / $size); global $page; if (!isset($page) || $page < 1) $page = 1; if ($page > $page_cnt) $page = $page_cnt; $data_sql = 'select * from `'.$source.'`'.$attr_where. $attr_order.' limit '.($page-1) * $size.','.$size; $GLOBALS['cfg_page_curr'] = $page; $GLOBALS['cfg_page_prev'] = $page - 1; $GLOBALS['cfg_page_next'] = $page + 1; $GLOBALS['cfg_page_nums'] = $page_cnt; if (function_exists('list_pagelink')) { $GLOBALS['cfg_page_list'] = list_pagelink($page, $page_cnt, 2); } } $data_idx = 0; $data_ret = $data_ins->SqlCmdExec($data_sql); while ($row = $data_ins->GetRecArr($data_ret)) { if ($skip > 0 && !empty($flag)) { $data_idx != 0 && $data_idx % $skip == 0 && $data_str .= $flag; } $data_tmp = $html; $data_tmp = str_ireplace('@idx', $data_idx, $data_tmp); for ($i = 0; $i < count($out_matches[0]); $i ++) { $data_tmp = str_ireplace($out_matches[0][$i], $row[$out_matches[1][$i]], $data_tmp); } $data_str .= $data_tmp; $data_idx ++; } } else { if (empty($source)) { exit('标签{data}必须指定source属性!'); } $data_sql = 'select * from `'.$source. '`'.$attr_where.$attr_order; $row = $data_ins->GetOneRec($data_sql); if (is_array($row)) { $data_tmp = $html; for ($i = 0; $i < count($out_matches[0]); $i ++) { $data_val = $row[$out_matches[1][$i]]; if (empty($out_matches[2][$i])) { $data_tmp = str_ireplace($out_matches[0][$i], $data_val, $data_tmp); } else { $attr_str = $out_matches[2][$i]; $attr_ins = new Attbt($attr_str); $func_txt = $attr_ins->attrs['function']; if (!empty($func_txt)) { $func_tmp = explode('(', $func_txt); if (function_exists($func_tmp[0])) { eval('$func_ret ='.str_ireplace('@me', '\''.$data_val.'\'', $func_txt)); $data_tmp = str_ireplace($out_matches[0][$i], $func_ret, $data_tmp); } else { exit('调用了不存在的函数!'); } } else { exit('标签设置属性无效!'); } } } $data_str .= $data_tmp; } } unset($data_ins); return $data_str; } else { exit('标签设置属性无效!'); } } else { exit('没有设置标签属性!'); } } static public function __callStatic($name, $args) { exit('标签{'.$name.'}不存在!'); } } ?>

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









소개 오늘날 빠르게 발전하는 디지털 세계에서는 강력하고 유연하며 유지 관리가 가능한 웹 애플리케이션을 구축하는 것이 중요합니다. PHPmvc 아키텍처는 이러한 목표를 달성하기 위한 이상적인 솔루션을 제공합니다. MVC(Model-View-Controller)는 애플리케이션의 다양한 측면을 독립적인 구성 요소로 분리하는 널리 사용되는 디자인 패턴입니다. MVC 아키텍처의 기초 MVC 아키텍처의 핵심 원칙은 관심사 분리입니다. 모델: 애플리케이션의 데이터와 비즈니스 로직을 캡슐화합니다. 보기: 데이터 표시 및 사용자 상호 작용 처리를 담당합니다. 컨트롤러: 모델과 뷰 간의 상호 작용을 조정하고 사용자 요청과 비즈니스 로직을 관리합니다. PHPMVC 아키텍처 phpMVC 아키텍처는 전통적인 MVC 패턴을 따르지만 언어별 기능도 도입합니다. 다음은 PHPMVC입니다.

MVC 아키텍처(Model-View-Controller)는 코드를 구성하고 WEB 애플리케이션 개발을 단순화하기 위한 명확한 구조를 제공하기 때문에 PHP 개발에서 가장 널리 사용되는 패턴 중 하나입니다. 기본 MVC 원칙은 대부분의 웹 애플리케이션에 충분하지만 복잡한 데이터를 처리하거나 고급 기능을 구현해야 하는 애플리케이션에는 몇 가지 제한 사항이 있습니다. 모델 계층 분리 모델 계층을 분리하는 것은 고급 MVC 아키텍처에서 일반적인 기술입니다. 여기에는 모델 클래스를 더 작은 하위 클래스로 나누는 작업이 포함되며, 각 하위 클래스는 특정 기능에 중점을 둡니다. 예를 들어 전자 상거래 애플리케이션의 경우 기본 모델 클래스를 주문 모델, 제품 모델 및 고객 모델로 나눌 수 있습니다. 이러한 분리는 코드 유지 관리성과 재사용성을 향상시키는 데 도움이 됩니다. 의존성 주입 사용

MVC(Model-View-Controller) 패턴은 개발자가 코드를 더 잘 구성하고 관리하는 데 도움이 될 수 있는 일반적으로 사용되는 소프트웨어 디자인 패턴입니다. MVC 패턴은 애플리케이션을 모델, 뷰, 컨트롤러의 세 부분으로 나누고 각 부분에는 고유한 역할과 책임이 있습니다. 이번 글에서는 PHP를 사용하여 MVC 패턴을 구현하는 방법에 대해 설명합니다. 모델 모델은 애플리케이션의 데이터 및 데이터 처리를 나타냅니다. 대개,

SpringMVC 프레임워크 복호화: 왜 그렇게 인기가 있으며 특정 코드 예제가 필요합니까? 소개: 오늘날의 소프트웨어 개발 분야에서 SpringMVC 프레임워크는 개발자들 사이에서 매우 인기 있는 선택이 되었습니다. MVC 아키텍처 패턴을 기반으로 하는 웹 프레임워크로 유연하고 가볍고 효율적인 개발 방법을 제공합니다. 이 기사에서는 SpringMVC 프레임워크의 매력을 자세히 살펴보고 특정 코드 예제를 통해 그 강력함을 보여줍니다. 1. SpringMVC 프레임워크의 장점 유연한 구성 방식 Spr

웹 개발에서 MVC(Model-View-Controller)는 애플리케이션의 데이터, 사용자 인터페이스 및 제어 논리를 처리하고 관리하기 위해 일반적으로 사용되는 아키텍처 패턴입니다. 널리 사용되는 웹 개발 언어인 PHP는 MVC 아키텍처를 사용하여 웹 애플리케이션을 설계하고 구축할 수도 있습니다. 이 기사에서는 MVC 아키텍처를 사용하여 PHP에서 프로젝트를 설계하는 방법을 소개하고 그 장점과 주의 사항에 대해 설명합니다. MVCMVC란 웹 애플리케이션에서 일반적으로 사용되는 소프트웨어 아키텍처 패턴입니다. MV

PHP8 프레임워크를 사용하여 MVC 개발: 단계별 가이드 소개: MVC(Model-View-Controller)는 애플리케이션의 논리, 데이터 및 사용자 인터페이스를 분리하는 데 사용되는 일반적으로 사용되는 소프트웨어 아키텍처 패턴입니다. 코드를 더 잘 관리하고 유지 관리하기 위해 애플리케이션을 세 가지 개별 구성 요소로 분리하는 구조를 제공합니다. 이 기사에서는 PHP8 프레임워크를 사용하여 MVC 패턴을 준수하는 애플리케이션을 개발하는 방법을 살펴보겠습니다. 1단계: MVC 패턴 이해 MVC 애플리케이션 개발을 시작하기 전에 나는

Beego는 Go 언어 기반의 웹 애플리케이션 프레임워크로 고성능, 단순성, 사용 편의성, 높은 확장성의 장점을 가지고 있습니다. 그중 MVC 아키텍처는 개발자가 코드를 더 잘 관리 및 구성하고 개발 효율성과 코드 품질을 향상시키는 데 도움이 되는 Beego 프레임워크의 핵심 설계 개념 중 하나입니다. 이 기사에서는 개발자가 Beego 프레임워크를 더 잘 이해하고 사용할 수 있도록 Beego의 MVC 아키텍처를 자세히 살펴보겠습니다. 1. MVC 아키텍처 소개 MVC(Model-View-Controller)는 일반적인 아키텍처입니다.

PHP8 프레임워크를 사용하여 MVC 개발: 초보자가 알아야 할 중요한 개념 및 기술 소개: 인터넷의 급속한 발전으로 인해 웹 개발은 오늘날 소프트웨어 개발 산업에서 중요한 역할을 하고 있습니다. PHP는 웹 개발에 널리 사용되며 개발자가 애플리케이션을 보다 효율적으로 구축하는 데 도움이 되는 성숙한 프레임워크가 많이 있습니다. 그 중 MVC(Model-View-Controller) 아키텍처는 가장 일반적이고 널리 사용되는 패턴 중 하나입니다. 이 기사에서는 초보자가 PHP8 프레임워크를 사용하여 MVC 애플리케이션을 개발하는 방법을 소개합니다.
