PHP中变量的类和对象范围

Class & Object Scope for Variable Variables in PHP

提问人:mmtalon 提问时间:3/3/2016 最后编辑:mmtalon 更新时间:3/8/2016 访问量:174

问:

问题 1) 为什么变量/变量对 42-50 行不可见,但对 456-472 行可见。我以为和属于同一个对象,因此应该对两个功能都可见。
问题 2) 在哪里初始化?
$this->$templateparse_and_return()$this->fetchparse_and_return$this->fetch$this->$template$this->$template

bar.tpl 和 foo.tpl 是单独的文件

    <!-- bar.tpl -->
    <HTML>
    <HEAD><TITLE>Feature world - {PAGETITLE}</TITLE></HEAD>
    <BODY BGCOLOR=BLACK TEXT=WHITE>
    <H1>{PAGETITLE}</H1>
    {PAGECONTENT}
    </BODY>
    </HTML> 
    -->

    <!--
    foo.tpl 

    This does not do anything obvious. Please look at {NAME}.
    demo.php3
    -->

索引 .php 文件

<?php

include "FastTemplate.php";

$tpl = new FastTemplate(".");
$tpl->define(array(foo => "foo.tpl", bar => "bar.tpl"));

$tpl->assign(NAME, "me");
$tpl->assign(PAGETITLE, "Welcome!");


$tpl->parse(PAGECONTENT, "foo"); 

echo $tpl->parse_and_return("bar");

?>

FastTemplate 类/FastTemplate.php 文件

        <?php

        class FastTemplate {

                var $start;

                var $ERROR = "";

                var $LAST = "";

                var $ROOT = "";

                var $FILELIST = array ( );

                var $PARSEVARS = array ( );

                var $LOADED = array ( );

                var $HANDLE = array ( );

                var $UPDT_TIME = '60';

                var $COMMENTS_START = "{*";

                var $COMMENTS_END = "*}";

                var $PATTERN_VARS_VARIABLE = array ( );

                var $PATTERN_VARS_DEFINE = array ( );

                FUNCTION FastTemplate($pathToTemplates = "") {

                    if (! empty ( $pathToTemplates )) {

                         $this->set_root ( $pathToTemplates );

                    }

                    $this->start = $this->utime (); 
                } 

                FUNCTION parse_and_return($tpl_name) {

                    $HREF = 'TPL';
                    $this->parse ( $HREF, $tpl_name );
                    $result = trim ( $this->fetch ( $HREF ) );
                    $this->clear_href ( $HREF );
                    RETURN $result;

                }

                FUNCTION set_root($root) {

                    $trailer = substr ( $root, - 1 );

                         if ((ord ( $trailer )) != 47) {
                             $root = "$root" . chr ( 47 );
                         }

                         if (is_dir ( $root )) {
                             $this->ROOT = $root;
                         } else {
                             $this->ROOT = "";
                             $this->error ( "dir [$root] is not a directory" );
                         }

                } 

                FUNCTION get_root() {

                    RETURN $this->ROOT;

                } 

                FUNCTION utime() {
                    $time = explode ( " ", microtime () );
                    $usec = ( double ) $time [0];
                    $sec = ( double ) $time [1];
                    RETURN $sec + $usec;
                } 

                FUNCTION get_template($template) {

                    if (empty ( $this->ROOT )) {
                     $this->error ( "Root not valid.", 1 );
                     RETURN FALSE;
                    }
                    if (empty ( $template )) {
                     $this->error ( "Template name is empty.", 1 );
                     RETURN FALSE;
                    };
                    $filename = "$this->ROOT" . "$template";

                    $contents = ((function_exists ( 'file_get_contents' ))) ? file_get_contents ( $filename ) : implode ( "\n", file ( $filename ) );

                     RETURN trim ( $contents );

                } 

                FUNCTION parseParamString($string) {

                            $matches=array();
                            if (preg_match_all ( '/\{([a-z0-9_]+)\}/i', $string, $matches )) {

                                    FOR($i = 0; $i < count ( $matches [0] ); $i ++) {
                                            $string = str_replace ( $matches [0] [$i], $this->PARSEVARS [$matches [1] [$i]], $string );
                                    }

                            }
                            RETURN $string;
                }

                FUNCTION value_defined($value, $field = '', $params = '') {

                    $var = $this->PARSEVARS [$value];

                    if ($field {0} == '.') {

                         $field = substr ( $field, 1 );

                    }

                    # echo "$value, $field, $params <BR>";
                    if (is_object ( $var )) {

                         if (method_exists ( $var, $field )) {

                             eval ( '$return = $var->' . $field . '(' . $this->parseParamString ( $params ) . ');' );
                             RETURN ((! empty ( $return )) || ($return === TRUE));

                         } ELSEif ((strcasecmp ( $field, 'id' ) != 0) && method_exists ( $var, 'get' )) {

                             $result = $var->get ( $field );
                             RETURN (! empty ( $result ) || $result === TRUE);

                         } ELSEif ((strcasecmp ( $field, 'id' ) == 0) && method_exists ( $var, 'getId' )) {

                             $result = $var->getId ();
                             RETURN (! empty ( $result ) || $result === TRUE);

                         }

                    } else {

                     RETURN (! empty ( $var ) || $var === TRUE);

                    }

                }

                FUNCTION parse_defined($template) {

                    $lines = split ( "\n", $template );
                    $newTemplate = "";
                    $ifdefs = FALSE;
                    $depth = 0;
                    $needparsedef [$depth] ["defs"] = FALSE;
                    $needparsedef [$depth] ["parse"] = TRUE;

                    WHILE ( list ( $num, $line ) = each ( $lines ) ) {

                         if (((! $needparsedef [$depth] ["defs"]) || ($needparsedef [$depth] ["parse"])) && (strpos ( $line, "IFDEF:" ) === FALSE) && (strpos ( $line, "IFNDEF:" ) === FALSE) && (strpos ( $line, "ELSE" ) === FALSE) && (strpos ( $line, "ENDIF" ) === FALSE)) {

                         $newTemplate .= trim ( $line ) . "\n";

                         }

                         if (preg_match ( "/<!--\s*IFDEF:\s*([a-zA-Z_][a-zA-Z0-9_]+)(\.|\-\>)?([a-zA-Z_][a-zA-Z0-9_]+)?\(?(\s*\,?\".*\"\s*\,?|\s*\,?[a-z0-9\_]*\s*\,?)\)?\s*-->/i", $line, $regs )) {

                                 $depth ++;
                                 $needparsedef [$depth] ["defs"] = TRUE;

                                 if ($this->value_defined ( $regs [1], $regs [3], $regs [4] )){

                                     $needparsedef [$depth] ["parse"] = $needparsedef [$depth - 1] ["parse"]; 

                                 }else{

                                     $needparsedef [$depth] ["parse"] = FALSE;

                                 }

                         }

                         if (preg_match ( "/<!--\s*IFNDEF:\s*([a-zA-Z_][a-zA-Z0-9_]+)(\.|\-\>)?([a-zA-Z_][a-zA-Z0-9_]+)?\(?(\s*\,?\".*\"\s*\,?|\s*\,?[a-z0-9\_]*\s*\,?)\)?\s*-->/i", $line, $regs )) {

                             $depth ++;
                             $needparsedef [$depth] ["defs"] = TRUE;

                         }
                         if (! $this->value_defined ( $regs [1], $regs [3], $regs [4] )){

                             $needparsedef [$depth] ["parse"] = $needparsedef [$depth - 1] ["parse"]; 

                         }else{

                             $needparsedef [$depth] ["parse"] = FALSE;}

                         }

                        // ELSE block
                        if (preg_match ( "/<!--\s*ELSE\s*-->/i", $line )) {

                             if ($needparsedef [$depth] ["defs"]){

                                 $needparsedef [$depth] ["parse"] = (! ($needparsedef [$depth] ["parse"]) & $needparsedef [$depth - 1] ["parse"]);

                             }

                             if (preg_match ( "/<!--\s*ENDIF\s*-->/i", $line )) {

                                 $needparsedef [$depth] ["defs"] = FALSE;
                                 $depth --;

                             }
                        }

                    if ($depth){

                     $this->error ( 'Some nonclosed IDEFS blocks', 0 );

                    }
                    RETURN $newTemplate;
                }

                FUNCTION parse_template($template, $ft_array) {

                    $matches=array();

                    if (preg_match_all ( '/\{([a-zA-Z_][a-zA-Z0-9_]+)(\.|\-\>)([a-zA-Z_][a-zA-Z0-9_]+)\(?(\s*\,?\".*?\"\s*\,?|\s*\,?[a-z0-9\_]*\s*\,?)\)?\}/i', $template, $matches )) {

                         FOR($i = 0; $i < count ( $matches [0] ); ++ $i) {

                             $obj = $ft_array [$matches [1] [$i]];

                             if ((is_object ( $obj ) && method_exists ( $obj, $matches [3] [$i] ))) {

                                 eval ( '$return = $obj->' . $matches [3] [$i] . '(' . $this->parseParamString ( $matches [4] [$i] ) . ');' );
                                 $template = str_replace ( $matches [0] [$i], $return, $template );

                             } else if (is_object ( $obj ) && ($matches [3] [$i] == 'id') && method_exists ( $obj, 'getId' )){

                                 $template = str_replace ( $matches [0] [$i], $obj->getId (), $template ); 

                             }else if (is_object ( $obj ) && method_exists ( $obj, 'get' )){

                             $template = str_replace ( $matches [0] [$i], $obj->get ( $matches [3] [$i] ), $template ); }else if (! is_object ( $obj )){
                                 $template = str_replace ( $matches [0] [$i], '', $template );

                             }

                         } //end for loop
                    } //end if 


                    if (preg_match_all ( '/<\!\-\-\s*#include\s+file="([\{\}a-zA-Z0-9_\.\-\/]+)"\s*\\-\->/i', $template, $matches )) {

                         FOR($i = 0; $i < count ( $matches [0] ); $i ++) {

                             $file_path = $matches [1] [$i];

                             FOREACH ( $ft_array as $key => $value ) {

                                 if (! empty ( $key )) {

                                     $key = '{' . "$key" . '}';
                                     $file_path = str_replace ( "$key", "$value", "$file_path" );

                                 }

                             } //foreach

                             $content = '';

                             if (! isset ( $ft_array [$file_path] )) {

                                 if (! file_exists ( $file_path )){

                                    $file_path = $this->ROOT . $file_path;

                                 }

                                 if (! file_exists ( $file_path )){

                                    $file_path = $this->ROOT . basename ( $file_path );

                                 }

                                 if (file_exists ( $file_path )) {

                                    $content = ((function_exists ( 'file_get_contents' ))) ? file_get_contents ( $file_path ) : implode ( "\n", file ( $file_path ) );

                                 } else {

                                    $content = '';

                                 }
                             } else {

                                 $content = $ft_array [$file_path];
                                 $template = str_replace ( $matches [0] [$i], $content, $template );

                             }
                         } //for
                    } //end preg_match_all

                    reset ( $ft_array );

                    WHILE ( list ( $key, $val ) = each ( $ft_array ) ) {

                         if (! (empty ( $key ))) {

                             if (gettype ( $val ) != "string") {

                                 settype ( $val, "string" );

                             }

                             $key = '{' . "$key" . '}'; 
                             $template = str_replace ( "$key", "$val", "$template" ); 

                         }

                    }


                    $template = ereg_replace ( "{([A-Za-z0-9_\.]+)}", "", $template ); 

                    $template = preg_replace ( "/(<!--\s*IFDEF:\s*([a-zA-Z_][a-zA-Z0-9_]+)(\.|\-\>)?([a-zA-Z_][a-zA-Z0-9_]+)?\(?(\s*\,?\".*?\"\s*\,?|\s*\,?[a-z0-9\_]*\s*\,?)\)?\s*-->)/i", "\n$0\n", $template );
                    $template = preg_replace ( "/(<!--\s*IFNDEF:\s*([a-zA-Z_][a-zA-Z0-9_]+)(\.|\-\>)?([a-zA-Z_][a-zA-Z0-9_]+)?\(?(\s*\,?\".*?\"\s*\,?|\s*\,?[a-z0-9\_]*\s*\,?)\)?\s*-->)/i", "\n$0\n", $template );
                    $template = preg_replace ( "/(<!--\s*ELSE\s*-->)/i", "\n\\0\n", $template );
                    $template = preg_replace ( "/(<!--\s*ENDIF\s*-->)/i", "\n\\0\n", $template );

                     WHILE ( list ( $num, $line ) = each ( $lines ) ) {

                        if (! $inside_block) {

                            $template .= "$line\n";

                        }

                    }
                    $template = $this->parse_defined ( $template );

                    RETURN $template;
                } 

                FUNCTION parse($ReturnVar, $FileTags) {

                    FOREACH ( $this->PATTERN_VARS_DEFINE as $value ){

                         $this->multiple_assign_define ( "$value" );

                    }

                    FOREACH ( $this->PATTERN_VARS_VARIABLE as $value ){

                         $this->multiple_assign ( "$value" );

                    }

                    $append = FALSE;
                    $this->LAST = $ReturnVar;
                    $this->HANDLE [$ReturnVar] = 1;

                    if (gettype ( $FileTags ) == "array") {

                         unset ( $this->$ReturnVar ); 

                         WHILE ( list ( $key, $val ) = each ( $FileTags ) ) {

                             if ((! isset ( $this->$val )) || (empty ( $this->$val ))) {

                                 $this->LOADED ["$val"] = 1;
                                 $fileName = $this->FILELIST ["$val"];
                                 $this->$val = $this->get_template ( $fileName );

                             }

                             $this->$ReturnVar = $this->parse_template ( $this->$val, $this->PARSEVARS );
                             //  For recursive calls.
                             $this->assign ( array ($ReturnVar => $this->$ReturnVar ) );
                         }

                    } else {

                        $val = $FileTags;

                        if ((substr ( $val, 0, 1 )) == '.') {

                            $append = TRUE;
                            $val = substr ( $val, 1 );

                        }

                        if ((! isset ( $this->$val )) || (empty ( $this->$val ))) {

                            $this->LOADED ["$val"] = 1;
                            $fileName = $this->FILELIST ["$val"];
                            $this->$val = $this->get_template ( $fileName );

                        }

                        if ($append) {

                            if (isset ( $this->$ReturnVar )) {

                                $this->$ReturnVar .= $this->parse_template ( $this->$val, $this->PARSEVARS );

                            } else {

                                $this->$ReturnVar = $this->parse_template ( $this->$val, $this->PARSEVARS );

                            }

                        } else {

                            $this->$ReturnVar = $this->parse_template ( $this->$val, $this->PARSEVARS );

                        }

                        $this->assign ( array ($ReturnVar => $this->$ReturnVar ) );

                    }
                    RETURN;
                }

                FUNCTION getfast($template = "") {

                    if (empty ( $template )) {

                        $template = $this->LAST;

                    }

                    // "$this->$template" not initialize here!
                    if ((! (isset ( $this->$template ))) || (empty ( $this->$template ))) {

                         $this->error ( "Nothing parsed, nothing printed", 0 );

                         RETURN;

                    } else {

                         if (! get_magic_quotes_gpc ()){

                             $this->$template = stripslashes ( $this->$template );

                         }

                         RETURN $this->$template;

                    }
                } 

                FUNCTION fetch($template = "") {

                    if (empty ( $template )) {

                         $template = $this->LAST;

                    }

                    if ((! (isset ( $this->$template ))) || (empty ( $this->$template ))) {

                         $this->error ( "Nothing parsed, nothing printed", 0 );
                         RETURN "";

                    }

                    RETURN ($this->$template);
                }

                FUNCTION define($fileList, $value = null) {

                    if ((gettype ( $fileList ) != "array") && ! is_null ( $value )){

                     $fileList = array ($fileList => $value );

                    }

                    WHILE ( list ( $FileTag, $FileName ) = each ( $fileList ) ) {

                         $this->FILELIST ["$FileTag"] = $FileName;

                    }
                    RETURN TRUE;
                }

                FUNCTION clear_href($href) {

                    if (! empty ( $href )) {

                         if ((gettype ( $href )) != "array") {

                                 unset ( $this->PARSEVARS [$href] );
                                 RETURN;

                         } else {

                            FOREACH ( $href as $value ){

                                    unset ( $this->PARSEVARS [$value] );
                                    RETURN;

                            }

                         }

                    } else {

                         // Empty - clear them all
                         $this->clear_assign ();

                    }

                    RETURN;
                }

                FUNCTION clear_assign() {

        if (! (empty ( $this->PARSEVARS ))) {

            WHILE ( list ( $Ref, $Val ) = each ( $this->PARSEVARS ) ) {

                unset ( $this->PARSEVARS ["$Ref"] );

            }
        }

                }

                FUNCTION assign_from_array($Arr, $Keys) {

                    if (gettype ( $Arr ) == "array") {

                         foreach ( $Keys as $k ){

                            if (! empty ( $k )){

                               $this->PARSEVARS [strtoupper ( $k )] = str_replace ( '&amp;#', '&#', $Arr [$k] );

                            }

                         }
                    }
                }

                FUNCTION assign($ft_array, $trailer = "") {

                    if (gettype ( $ft_array ) == "array") {

                         WHILE ( list ( $key, $val ) = each ( $ft_array ) ) {

                             if (! (empty ( $key ))) {

                                 if (! is_object ( $val )){

                                     $this->PARSEVARS ["$key"] = str_replace ( '&amp;#', '&#', $val );

                                 } else{

                                     $this->PARSEVARS ["$key"] = $val; 

                                 }

                            }

                         }

                    } else {

                         if (! empty ( $ft_array )) {

                             if (! is_object ( $trailer )){

                                $this->PARSEVARS ["$ft_array"] = str_replace ( '&amp;#', '&#', $trailer ); 

                             }else{

                                $this->PARSEVARS ["$ft_array"] = $trailer; 

                             }
                         }

                    }
                }

                FUNCTION get_assigned($ft_name = "") {

                    if (empty ( $ft_name )) {

                        RETURN FALSE;

                    }

                    if (isset ( $this->PARSEVARS ["$ft_name"] )) {

                        RETURN ($this->PARSEVARS ["$ft_name"]);

                    } else {

                     RETURN FALSE;

                    }

                }

                FUNCTION error($errorMsg, $die = 0) {

                        $this->ERROR = $errorMsg;
                        echo "ERROR: $this->ERROR <BR> \n";

                    if ($die == 1) {

                        exit ();

                    }
                    RETURN;
                } 

                FUNCTION multiple_assign($pattern) {

                    WHILE ( list ( $key, $value ) = each ( $GLOBALS ) ) {

                        if (substr ( $key, 0, strlen ( $pattern ) ) == $pattern) {

                           $this->assign ( strtoupper ( $key ), $value );

                        }
                    }
                    reset ( $GLOBALS );

                } 

                FUNCTION multiple_assign_define($pattern) {

                    $ar = get_defined_constants ();

                    FOREACH ( $ar as $key => $def ){

                         if (substr ( $key, 0, strlen ( $pattern ) ) == $pattern){

                             $this->assign ( strtoupper ( $key ), $def );

                         }

                    }

                } 

        } // End Class

    ?>
PHP 范围 变量

评论

0赞 3/3/2016
请修正问题主题
0赞 mmtalon 3/4/2016
达贡,请帮忙。解决问题主题需要什么?我真正想要的只是有人告诉我为什么变量“$this->$template”在调用函数 (parse_and_return) 中不可见,而对被调用的函数 (fetch) 可见。

答:

0赞 mmtalon 3/8/2016 #1

回答我的第一个问题:

变量“$this->$template”对 parse_and_return() 不可见有两个原因;

原因1:“$this->$template”变量指向 FastTemplate 类的实例变量$TPL,该变量在调用 parse() 之前不存在。parse() 函数解析 bar.tpl 文件并解析此文件的 FastTemplate {VARS}。在 FastTemplate 对象中创建实例变量$TPL并分配 bar.tpl 文件的内容。$TPL变量在创建之前对任何成员函数都不可见。

原因二:$template是局部变量,$this->$template是局部变量;仅本地到 fetch() 函数。由于这些变量的作用域是局部变量,因此,如果您尝试在其他成员函数中使用它们,它们将生成并出错。但是,创建$TPL实例变量后,只需使用 $this->TPL 即可从任何成员函数访问其数据值。

回答我的第二个问题:

如上所述,“$this->$template”是一个局部变量变量,指的是使用 bar.tpl 文件内容值初始化的实例变量$TPL。这个$TPL变量在parse()函数内的第382-388行附近或行上初始化。以下表达式用于初始化$TPL:“$this->$ReturnVar = $this->parse_template ($this->$val, $this->PARSEVARS )”。

$ReturnVar 变量是 parse() 函数定义中的第一个参数,例如 FUNCTION parse($ReturnVar, $FileTags)。向$ReturnVar变量传递了一个字符串值为“TPL”的参数。现在,您可以使用变量变量来访问变量的地址,在本例中,通过使用 $$ReturnVar 来访问字符串“TPL”的地址。由于“TPL”是 FastTemplate 对象的实例变量,因此必须使用伪变量“$this->”来访问它。因此,变量变量的结构为 $this->$ReturnVar。这将创建 $TPL 变量并访问其地址,并为该地址分配 bar.tpl 文件的内容。

巧合的是,在此示例中,对象被命名为 $tpl,但可以使用任何名称。

结束语 - 我的目标是通过排除所有变量并使用更直接的编码方法来简化此代码。在我看来,过度使用变量(指针)会使你的代码变得复杂且难以理解。