찾다
php教程php手册一步步编写PHP的Framework(十一)

 

之前讲了怎么让实现跳转和请求的转发,当然,也只是很简单的说了一下,更深的内容需要你自己去读一下具体框架的实现。

现在跳转和转发有了,对于模型的编写可以后面再来,那我就先说一下怎么讲数据从控制器传递到视图,之前我们的实现方式非常丑陋:

1 $viewPath = dirname(__FILE__) . '/../views/index.php';

2 if(file_exists($viewPath)) {

3     include $viewPath;

4 } else {

5     echo 'view does not exists';

6 }

现在我准备用更优雅一点的方式将数据传递到视图,现在先说一下怎么调用:

01

02 class TestController extends Controller {

03     public function test() {

04         $this->_assign(array(

05             'arr' => array(

06                 'test','test2'

07             ),

08             'str' => 'it is a str'

09         ));

10         $this->_display('test');

11     }

12 }

 

这就是今天我写之后的调用方式,如果你学过smarty,那么你会发现这和smarty很相似,的确,我写toper的时候也是受了smarty的影响,最开始的想法是视图这一块就使用smarty,后面想了一下,既然号称是自己的框架,那么视图这一块儿肯定也要全部自己写,虽然如此,但是我后面还是保留了assign,display这种写法,并且只要配置文件修改,完全可以将视图切换到smarty而不使用框架本身的实现。

好像扯得有点远了,首先说一下,为了代码的简单,我将assign和display的实现简化,大家理解思路就好,真实的框架的实现要复杂一些。

首先assign,它的功能是为变量赋值,这里我假设传递的参数都是关联数组,也就是常说的HashTable,它不应该直接调用View的接口,这接口实现怎么赋值:

1 protected  function _assign(Array $arr) {

2         View::assign($arr);

3     }

 

为了处理视图这一块的数据存储和展示,我定义了View.php这个文件,View::assign这个方法是它的一个静态方法,当然,实现的功能大家都懂的。。。

            具体View.php中怎么实现的呢?

1 private static $_data = array();

2     public static function assign($arr) {

3         foreach($arr as $key => $val) {

4             if(!is_int($key)) {

5                 //过滤掉如array('test','test2')这种数据

6                 self::$_data[$key] = $val;

7             }

8         }

9     }

由于assign是静态方法,数据又需要存储到这个类,所以需要定义一个静态的成员变量$_data,这个变量存储控制器传递的数据。因为之前在控制器的assign中已经进行了类型提示,所以可以保证在View中的assign传递的形参都是数组,现在只需要一个foreach然后依次存储即可,那为什么不直接使用self::$_data = $arr呢,这样只有一句话呢?

首先,数组中的数据有些可能是不对的,比如array('test','test2')我就不懂数据test和test2到底代表了什么,这样的数据应该在assign中就被剔除掉,如果你要求比较严苛,也可以直接给用户提示警告。

其次,有可能用户多次调用assign,如果直接使用引用,那么第二次调用assign就会把第一次的数据弄丢,这样是不可容忍的。

好,赋值搞定,然后就是怎么显示的问题了,在控制器中,还是直接调用接口,而不负责内部实现,但是在调用接口之前需要进行一定的格式化:

01 protected function _display($str) {

02         if(is_string($str)) {

03             $str = str_replace(array(

04                 '.','#'

05             ),array(

06                 '/','.'

07             ),$str);

08             View::display(MODULES_PATH . View::VIEW_BASE_PATH . $str . '.php');

09         }

10     }

为了视觉上的美观和其他一些XXX的原因,我们可以将表示路径的/在作为实参传递的时候变成.,这样假设要调用test/test2.php,那么只需要传递test.test2.php即可。当然,这样也存在一个问题,有时候需要使用.,就像刚才这个例子,实际上test.test2.php会被解析为test/test2/php,这样实际上是有问题的,那么怎么解决呢,我使用一个#代表.,这样刚才这个传递的时候就变成了test.test2#php。这样还有一个问题,.php基本上每个页面都有,那为什么还要传递进去呢,直接框架帮你加上就好了嘛,所以用户只需要输入test.test2就好,这样从逻辑上也容易理解,test模块下面的test2这个视图文件。如果你用过thinkphp,你会发现这和它的写法很类似,实际上我在最开始写的时候就是边看thinkphp源码边写的,所以很多东西都借鉴了它的思想。我个人比较讨厌使用#,所以我基本上在视图文件中没有使用过#,因为我觉得你自己不会这么无聊,去写类似于test.view.php这样的无意义的文件名,直接test.php就好了,这样的名字框架又帮你解决了一部分,所以基本上不存在这个问题了。

这儿还出现了一个常量View::VIEW_BASE_PATH,这个常量代表的含义是视图根目录的路径,这样传递进去的实际上是一个实际的绝对路径。

由于display是展示这个视图文件,那么肯定会使用include某一个文件,具体的实现如下:

1 public static function display($file) {

2         if(file_exists($file)) {

3             extract(self::$_data);

4             include $file;

5         } else {

6             throw new ViewException(ViewException::NOT_EXISTS_TEMPLATE);

7         }

8     }

extract就是讲数组打散,更多的请查询PHP手册。

这里由于可能这个视图文件不存在,所以需要判定一下,如果视图文件不存在,则直接抛出异常,注意,异常是使用了ViewException,这个类又是新定义的,传递的参数表示这个异常是因为视图模板不存在而引起的。

那我么来看看具体这个异常类的实现:

01

02 class ViewException extends BaseException {

03     const NOT_EXISTS_TEMPLATE = 1;

04     public function __construct($code = 0) {

05         switch($code) {

06             case ViewException::NOT_EXISTS_TEMPLATE:

07                 $msg = 'the template file is not exists';

08                 break;

09             default :

10                 $msg = 'unknown exception';

11                 break;

12         }

13         parent::__construct($msg,$code);

14     }

15 }

这个类它继承了BaseException,由于BaseException实现了debug模式开与关不同情况下展示内容不同,ViewException也具有这个特性,当debug关闭,抛出异常的时候,也只会跳转到错误页,不会直接展示异常,这样的处理更易维护。



성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

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

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기