2

我改编了一个非常简单的View类来传递变量,以便Controller我可以直接调用变量,例如ViewView

<?php echo $name; ?>

并不是

<?php echo $this->name; ?>

所有视图变量都存储在一个名为 vars 的关联数组中,例如$vars['name'] = "test",并具有__set分配变量的函数设置,例如

$v = new View;
$v->name="test";
$v->out(); 

因此,在out()传递变量并包含我添加的视图 HTML 的函数中:

    foreach($this->vars as $key=>$val) {
      $$key=$val;
    }
include $this->view_file;

然后我测试了如果我$this在模板中使用并添加一个相应的变量会发生什么

$v->this = "test_this";

我的假设是代码将失败,因为$this无法重新分配,或者即使重新分配 -请参阅此处- 代码将失败,因为$this已重新分配所以

include $this->view_file;

行不通!

相反,它奏效了。 ,当使用或等于$this直接调用但仍指向原始值时!echo $this;var_dump($this);"test_this"$this->view_file

怎么会这样?

然后我重新测试使用extract($this->vars, EXTR_OVERWRITE)$this没有被触动!

一般来说,将变量传递给视图并避免函数冲突的正确方法是什么

function out($view, $toString = false)
{
    extract($this->vars);
    include $view;
}

并且 vars 可能有一个名为 view 或“this”的 var,或者模板可能会使用该$viewvar。

  1. 别担心,只要确保不要分配一个名为 view 的 var。
  2. 在函数中使用长变量名out(),例如$longVarNameSoThatThereWillNotBeCollisions.
  3. 将函数所需的所有变量分配给$this->temp$this->temp['view']然后unset($view)- 以及$this- 谁在他们的正确头脑中会使用一个名为$thisin的变量View
4

2 回答 2

4

为了解释为什么您仍然能够访问对象属性,即使您已经设法绕过 reassigning 的保护$this,您必须查看为编译脚本生成的操作码。

使用操作码访问对象属性FETCH_OBJ_R

当您编写诸如

$myObject = new testClass;
$myObject->property

编译后的代码FETCH_OBJ_R使用两个参数生成。第一个是包含对象的变量,第二个是属性的名称。

如果您使用 Vulcan 反汇编程序,输出可能如下所示:

FETCH_OBJ_R                                      $1      !1, 'property'

$1是存储返回值的位置,!1是包含对象的变量。

但是,如果您使用$this生成的输出访问该属性,则略有不同。

FETCH_OBJ_R                                      $1      'property'

带有一个参数的操作码将属性查找解析为从中调用它的对象。

因此,您的问题的答案$this->property在编译时已解决。即使你破产了$this,位置property也已经确定了。

于 2012-07-10T15:29:37.070 回答
0

这让我有点感兴趣,看来你是对的,使用变量变量赋值给$this.

正如你所说:

<?php
$var = 'this';
$$var = 'hello';

echo $this;

有效,而

<?php
$this = 'hello';

echo $this;

没有。

也许在 bugs.php.net 上报告,看看是否有官方答案?

现有成员$this仍在工作而实际价值$this完全不同的事实绝对不应该发生,并且必须是某种形式的核心问题。我唯一能想到的是,它以某种方式$this被用作魔术上下文变量(当然这并不奇怪,毕竟是 PHP!),而不是真正的“真实”变量。从变量变量赋值的错误(这显然$this应该发生!)允许向开发人员显示一个虚假变量的事实。

魔法测试:

<?php

class ThisTest {
    public function SetAndUseThis() {
        $var = 'this';
        $$var = 'that';
        var_dump($this);
        var_dump($this->variable);
        var_dump($this->AnotherMethod());
    }

    public $variable = 'i am a variable';

    public function AnotherMethod()
    {
        return 9.0;
    }
}

$inst = new ThisTest();
$inst->SetAndUseThis();

结果是:

string(4) "that" string(15) "i am a variable" float(9)
于 2012-07-10T14:55:44.457 回答