• 一周试用yii开发一个带各种该有功能的web程序(三)


      接上篇,为什么index 模版里没有任何有关require,inculde类型关键字,却任然有我们认为“多余”的字符出现。因为在至少我的认知里html的结构该是<html><head></head><body></body></html>这样的,而index.php模版中存在这样的结构,而如果那里采用特殊技术的话会不会存在html标签在包含html标签,那就不是一个标准的html文档了。而我们查看源码生成的html源码时也发现了该html源码内容为:

        <div id="content">
        <html>
    <head>
    </head>
    <body>
    <center>这是我自己的第一个页面,虽然将原来的大段内容删除了。不在是一个博客</center>
    <a href="/admin/post/index/">指向admin/post/index.php的内容</a>
    </body>
    </html></div><!-- content -->
    
        <div class="clear"></div>

    即现在生成的页面是由一些其他页面加上我们自己的index.php结合生成的!

    但是,他是在那里实现的呢?

    先看我们的控制器:

    class SiteController extends Controller
    {
        public function actions()
        {
            return array(
                // captcha action renders the CAPTCHA image displayed on the contact page
                'captcha'=>array(
                    'class'=>'CCaptchaAction',
                    'backColor'=>0xFFFFFF,
                ),
                // page action renders "static" pages stored under 'protected/views/site/pages'
                // They can be accessed via: index.php?r=site/page&view=FileName
                'page'=>array(
                    'class'=>'CViewAction',
                ),
            );
        }
    
        /**
         * This is the default 'index' action that is invoked
         * when an action is not explicitly requested by users.
         */
        public function actionIndex()
        {
    
            $this->render('index');
        }

    这里的actionIndex就是我们访问localhost/index.php要调用的方法。但是我们的除了自己编写的那点代码外,其他的模版呢?

    可以查看父类,有没有一种可能,在做控制器实例化或者其他操作时调用了那个其他模版的程序,然后,index.php的内容作为一个运行后的string参数传入进去最终得到我们想要的页面?

    class Controller extends CController
    {
        /**
         * @var string the default layout for the controller view. Defaults to '//layouts/column1',
         * meaning using a single column layout. See 'protected/views/layouts/column1.php'.
         */
        public $layout='//layouts/column1';

    这里可以注意到有$layout。

    最终我们定位到layout文件夹,如下图:

    column1.php的内容有:

    <?php $this->beginContent('//layouts/main'); ?>
    <div id="content">
        <?php echo $content; ?>
    </div><!-- content -->
    <?php $this->endContent(); ?>

    这里已经有一些眉目了,可以看到<div id="content">了,因为我们知道id属性在html中的单一页面是唯一的,而我们刚才查看html页面也有一个<div id="content">,那么肯定是在调用actionIndex这个控制器方法的时候会将返回的字符串作为变量名为$content的变量赋值给另外一个作用模块,而这个作用模块主要是页面布局。由此,可以分析出protected/component/Controller.php的类我们也可以模拟编写出来一个其他的页面布局,让我们的逻辑控制器(如SiteController.php)来继承,达到更换布局,而展示内容不变的目的,此为推断,后面我会给出示例。

      由上面一些推断,总结出yii的装饰功能。

      要完成只显示我们自己的页面。可以将column1.php文件修改为

    <?php //$this->beginContent('//layouts/main'); ?>
    <div id="content">
        <?php echo $content; ?>
    </div><!-- content -->
    <?php //$this->endContent(); ?>

    当然编码问题也要注意,在index.php中加入<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>就会如愿看到:

    现在看$this->beginContent和$this->endContent()到底为我们做了什么工作。

    1. 首先需要明确这里的$this指的是什么,这个变量当然指的是控制器。

      修改columns.php的内容为:

      

    <?php //$this->beginContent('//layouts/main'); ?>
    <div id="content">
        <?php print_r($this) ?>
        <?php echo $content; ?>
    </div><!-- content -->
    <?php //$this->endContent(); ?>

      有图为证:

      也就是说,beginContent和endContent也是我们的SiteController的一个方法,查看没有,那么一定是父类方法了。

    2. 分析/frameworks/web/CBaseController.php的内容。

      

        public function beginContent($view=null,$data=array())
        {
            $this->beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data));
        }

      查看到这个罪魁祸首了。追根溯源,通过一堆工厂实现类方法调用可以查看到最终会汇集到/framework/web/CContentDecorator.php文件。

      CContentDecorator.php核心:

      

        protected function decorate($content)
        {
            $owner=$this->getOwner();
            if($this->view===null)
                $viewFile=Yii::app()->getController()->getLayoutFile(null);
            else
                $viewFile=$owner->getViewFile($this->view);
            if($viewFile!==false)
            {
                $data=$this->data;
                $data['content']=$content;
                return $owner->renderFile($viewFile,$data,true);
            }
            else
                return $content;
        }

    即$this->beginContent("layout_path"),这里可以看到一个关键点是'content',即为什么我们要使用$content在模版中进行展示了。

    那么更重要的main.php中控制的数据该展示在何处?

    原来的main.php中的内容:

        <?php endif?>
    
        <?php echo $content; ?>
    
        <div class="clear"></div>
    
        <div id="footer">
            Copyright &copy; <?php echo date('Y'); ?> by My Company.<br/>
            All Rights Reserved.<br/>
            <?php echo Yii::powered(); ?>
        </div><!-- footer -->
    
    </div><!-- page -->
    
    </body>
    </html>

    注意main.php中也存在这个$content

    所以,将该内容移动到Copyright下,查看页面已经出现变化了。

      即在main.php中也是通过$content来进行控制。

    但是在这里除了页面的调试布局外,当我们想查看某个类的某个方法是否存在时,有没有更好的处理方法呢?下篇处理该问题吧。

  • 相关阅读:
    高可用的MongoDB集群-实战篇
    【转载】特征选择常用算法综述
    【转载】Pytorch tutorial 之Datar Loading and Processing
    论文笔记系列-Well Begun Is Half Done:Generating High-Quality Seeds for Automatic Image Dataset Construction from Web
    重新定义Pytorch中的TensorDataset,可实现transforms
    【转载】机器学习之特征工程
    Pytorch里的CrossEntropyLoss详解
    Python日志模块logging用法
    【转载】如何进行数据变换
    【转载】使用sklearn优雅地进行数据挖掘
  • 原文地址:https://www.cnblogs.com/CLTANG/p/2650741.html
Copyright © 2020-2023  润新知