【问题标题】:PHP define scope for included filePHP定义包含文件的范围
【发布时间】:2010-10-06 11:52:24
【问题描述】:

我有很多 PHP 视图文件,我曾经使用简单的 include 语句将它们包含在我的控制器中。它们都使用在视图类中声明的方法,它们就像 $view->method();然而,我最近决定,如果包含也由这个视图类完成会更好。但是,这会更改包含文件的范围,因此不再定义 $view。 这是一个代码示例:

in someViewFile.php (BOTH siuations)
    <html>
    <head><title><?php echo $view->getAppTitle(); ?></title>
    etc.
OLD SITUATION in controller:
    $view = new view;
    include('someViewFile.php'); //$view is defined in someViewFile.php
NEW SITUATION in controller:
    $view = new view;
    $view->show('someViewFile'); //$view is not defined in someViewFile.php

现在我在视图类中使用它解决了这个问题:

public function show($file){
    $view = &$this;
    include($file.".php");
}

是否有声明包含文件的范围,或者这是解决问题的最佳方法?

这些示例是粗略简化的。

【问题讨论】:

    标签: php include scope


    【解决方案1】:

    这是一个简化但功能强大的视图类,我已经看到很多并且使用了很多。
    正如您在下面的代码中看到的:您使用模板文件的文件名实例化一个视图。
    客户端代码(可能是控制器)可以将数据发送到视图中。此数据可以是您需要的任何类型,甚至可以是其他视图。
    渲染父视图时将自动渲染嵌套视图。
    希望这会有所帮助。

    // simple view class
    class View {
        protected $filename;
        protected $data;
    
        function __construct( $filename ) {
            $this->filename = $filename;
        }
    
        function escape( $str ) {
            return htmlspecialchars( $str ); //for example
        }
    
        function __get( $name ) {
            if( isset( $this->data[$name] ) {
                return $this->data[$name];
            }
            return false;
        }
    
        function __set( $name, $value ) {
            $this->data[$name] = $value;
        }
    
        function render( $print = true ) {
            ob_start();
            include( $this->filename );
            $rendered = ob_get_clean();
            if( $print ) {
                echo $rendered;
                return;
            }
            return $rendered;
        }
    
        function __toString() {
            return $this->render();
        }
    }
    

    用法

    // usage
    $view = new View( 'template.phtml' );
    $view->title = 'My Title';
    $view->text = 'Some text';
    
    $nav = new View( 'nav.phtml' );
    $nav->links = array( 'http://www.google.com' => 'Google', 'http://www.yahoo.com' => 'Yahoo' );
    
    $view->nav = $nav;
    
    echo $view;
    

    模板

    //template.phtml
    <html>
        <head>
            <title><?php echo $this->title ?></title>
        </head>
        <body>
            <?php echo $this->nav ?>
            <?php echo $this->escape( $this->text ) ?>
        </body>
    </html>
    
    //nav.phtml
    <?php foreach( $this->links as $url => $link ): ?>
        <a href="<?php echo $url ?>"><?php echo $link ?></a> 
    <?php endforeach ?>
    

    【讨论】:

    • 我认为有一个小错字,上面写着“filname”?
    • 确实,成员及其用法是filname,其中分配是filename。我试图编辑它,但编辑需要 6 个字符的更改。 翻白眼
    • @meouw 非常感谢!我一直对模板有逆向思维。我可以在没有任何框架的情况下将它用于我的项目。
    • 进一步简化了视图类,希望得到反馈。
    • 你需要 2 关闭如果看到这一行if( isset( $this-&gt;data[$name] ) {
    【解决方案2】:

    您无法更改 include() 范围,不,因此您的方法可能与您描述的情况一样好。虽然我自己会跳过丑陋的 PHP4 兼容 & 符号。

    【讨论】:

      【解决方案3】:

      我所做的,(我不知道它有多好)很简单

      extract($GLOBALS);
      include $view.".php";
      

      确实有效

      干杯!

      【讨论】:

        【解决方案4】:

        View 类的更简化版本:

        Class View {
        
            protected $filename;
        
            function __construct($filename){
                $this->filename = $filename;
            }
        
            function display(){
                global $session; //put global variables here
        
                include Cfg::ROOT . '/views/' . $this->filename;    
            }
        
            function assign($key, $val){
                $this->$key = $val;
            }
        
        }
        

        在控制器中:

        $view = new View('homepage.php');
        $view->assign('page_title',$page_title); //assign all needed variables from controller
        $view->display();
        

        在模板/视图文件中:

        echo $this->page_title;
        

        【讨论】:

          【解决方案5】:

          也许这与我的 php-settings 或其他有关,但如果我在函数中包含一个文件,则该包含的文件将只具有该函数变量的范围。

          $a = 1; // This variable isn't visible for the included file
          
          function render()
          {
              $b = 2; // This variable is
              include('template.php');
          }
          
          
          // ----------------------------------------
          // template.php
          
          <html>
          <body>
          <?=$a?> // wont show
          <?=$b?> // will show
          </body>
          </html>
          

          我想我会选择这样的:

          function render($template, $variables)
          {
              extract($variables);
              include($template);
          }
          

          用法:

          render('templates/mytemplate.php', array(a=>1, b=>2));
          

          【讨论】:

            【解决方案6】:

            扩展 Quano 所提供的功能:

            更进一步,在全局执行范围内包含变量(否则必须在 include 的内部使用 global 调用)。这个想法是,您希望 include 像包含在您的主应用程序范围或定义的范围中一样工作。

            考虑这个类:

            class PHPInclude {
                private static $globalsList = array(
                        'GLOBALS','_SERVER','_GET','_POST','_FILES',
                        '_REQUEST','_SESSION','_ENV','_COOKIE'
                    );
                public static function phpInclude($file,$variables=array()) {
                    if ( file_exists($file) ) {
                        $globs = array();
                        foreach ( $GLOBALS as $key => $value ) {
                            if ( !in_array($key,sefl::$globalsList) ) {
                                array_push($globs,$key);
                            }
                        }
                        foreach ( $globs as $key ) {
                            global $$key;
                        }
                        foreach ( $variables as $variable ) {
                            global $$variable;
                        }
                        unset($globs,$key,$value);
                        ob_start();
                        include $file;
                        return ob_get_clean();
                    }
                    return '';
                }
            }
            

            如下使用:

            $foo = 'bar';
            function testScope() {
                $woo = 'sah';
                PHPInclude::phpInclude('file.phtml',array($woo));
            }
            

            该示例将自动包含$foo,因为它在全局范围内,并且$woo 因为它在本地范围内而被添加。

            我还没有将$this 作为任意变量进行测试,但我的蜘蛛感应器告诉我it won't work (warning)

            【讨论】:

            【解决方案7】:

            我找到了一个很好的解决方案。只需创建一个匿名函数并调用它。仅适用于 PHP 7+。

            $arg1=1;
            call_user_func(function()use($arg1,$arg2,...){
             $values=$arg1+$arg2;
             // $values is limited in scope inside this function
            }
            

            例如:

            $values='HEY!';
            
            //included code
            $arg1=1;
            $arg2=2;
            call_user_func(function()use($arg1,$arg2,...){
             $values=$arg1+$arg2;
             // $values is limited in scope inside this function
            }
            
            echo $values;
            // echos HEY!
            

            【讨论】:

              猜你喜欢
              • 2012-09-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-05
              • 2011-01-13
              • 1970-01-01
              • 1970-01-01
              • 2016-12-08
              相关资源
              最近更新 更多