提问人:mmtalon 提问时间:3/3/2016 最后编辑:mmtalon 更新时间:3/8/2016 访问量:174
PHP中变量的类和对象范围
Class & Object Scope for Variable Variables in PHP
问:
问题 1) 为什么变量/变量对 42-50 行不可见,但对 456-472 行可见。我以为和属于同一个对象,因此应该对两个功能都可见。
问题 2) 在哪里初始化?$this->$template
parse_and_return()
$this->fetch
parse_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 ( '&#', '&#', $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 ( '&#', '&#', $val );
} else{
$this->PARSEVARS ["$key"] = $val;
}
}
}
} else {
if (! empty ( $ft_array )) {
if (! is_object ( $trailer )){
$this->PARSEVARS ["$ft_array"] = str_replace ( '&#', '&#', $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
?>
答:
回答我的第一个问题:
变量“$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,但可以使用任何名称。
结束语 - 我的目标是通过排除所有变量并使用更直接的编码方法来简化此代码。在我看来,过度使用变量(指针)会使你的代码变得复杂且难以理解。
评论