0
Class Foo {
   public function bar() {
     echo $a;
   }
}

$foo = new Foo();
$b = "Hello world";
/* here inject somehow $b into $foo->bar() */
$foo->bar(); //prints "Hello world"
$b = "I <3 php!";
$foo->bar(); //keeps printing "Hello world"

有没有办法在 php 中做类似的事情而不将变量 $b 作为参数传递给方法 bar() 或类构造函数?我也不想使用全局变量。

编辑1: 谁在问我为什么要做如此奇怪的事情:做这样的事情对我来说会很好......

class Controller {
   /**
   * @post(name="address", type="email", required="true")
   */
   public function foo() {
       do_something_with($address);
       //$address is equal to $_POST['address'] and have been checked
   }
}

编辑 2: 我不是在寻找如何在 php 中实现注释。应该已经有注释实现了。鉴于我知道如何声明自己的注释,我想知道是否可以“神奇地”在方法中声明和初始化变量

4

6 回答 6

2

好吧,您可能会为 PHP 的反射机制而发疯。你的方法中获取当前类的文档注释,然后尝试访问同名的全局变量,沿着这条线:ReflectionClass::getDocComment()

/**
 * Use `$a`
 */
Class Foo {
   public function bar() {
     $rc = new ReflectionClass('Foo');
     $docstr = $rc->getDocComment();
     // here we extract the value "a" from above's comment "Use `$a`":
     $varname = preg_replace('/.*`\$([a-z_]+)`.*/s', '$1', $docstr);
     global $$varname;
     echo $$varname;
   }
}

$a = 'Hi there';
$cls = new Foo();
$cls->bar(); // echos "Hi there"

但坦率地说,这看起来弊大于利,恕我直言,您应该重新考虑最初的方法。

于 2012-10-22T15:41:57.727 回答
2

,没有。即使有可能,您所要求的也是应该避免的严重反模式。它只是让我想起了超全球。

您可以使用的最接近的有用的方法是使用单例模式来创建存储变量的“注册表”对象。但是,建议使用依赖注入来传递依赖对象

然后,您可以使用变量“加载”您的注册表单例,然后获取对象内部的实例以访问您需要的内容。

使用单例注册表类

对于单例注册表如何工作的一个非常简单的示例:

<?php
class Registry
{
    private static $items = array();
    private static $instance;

    private function __construct(){}
    private function __clone(){}

    public static function getInstance()
    {
        if( !isset( self::$instance ) )
        {
            self::$instance = new Registry();
        }
        return self::$instance;
    }    


    public function __set( $key, $item )
    {
        self::$items[ $key ] = $item;
    }

    public function __get( $key )
    {
        if( isset ( self::$items[ $key ] ) )
        {
            return self::$items[ $key ];
        }
    }

    public function getAll()
    {
        return self::$items;
    }
}
?>

然后您可以加载您的注册表...并以类似的方式访问这些项目。

<?php

$registry = Registry::getInstance();
$registry->foo = "bar";
于 2012-10-22T15:10:22.603 回答
1

不,那里没有。您需要通过常规渠道传递价值。

(当然,总是有或多或少涉及的方式来破解运行时并覆盖内存中的值,但这不是您想要作为常规 PHP 脚本的一部分的事情。)

于 2012-10-22T15:09:31.867 回答
1

您几乎排除了访问类外变量的所有可能性。

那么答案是否定的。

于 2012-10-22T15:09:59.353 回答
0

不适用于标量,但它适用于对象和数组。

class Foo {

    protected $arr;
    public function __construct(&$arr) {
        $this->arr =& $arr;
    }

    public function bar()
    {
        echo $this->arr[0] . "\n";
    }
}

$var = array(0 => 'test');
$foo = new Foo($var);

$foo->bar(); // test

$var[0] = 'test2';
$foo->bar(); // test2

这不是通常使用的好模式。我唯一一次使用它是用一个对象替换对$_SESSION变量的依赖(在一个非常旧的系统中,请不要杀了我)。

于 2012-10-22T15:34:01.140 回答
-2

编辑:恭喜,批评者:我的回答不是 OP 的意图。

您要问的是OO的基本部分。您希望在对象中封装数据。对象的目的不是成为功能停车场。对象也应该包含数据。

所以使用二传手:

Class Foo {

    private $a;

    //no construction needed, if you don't want to set values there
    //or...if you do:
    public function __construct(){  // no variables passed to constructor
        $this->a = $_POST['a'];     // variable initialized anyway!
    }

    public function set_a($a){
        $this->a = $a;
    }
    public function bar() {
        echo $this->a;
    }
}

接着:

$foo = new Foo();
$foo->bar();  // prints that post value
$foo->set_a("Hello World");
$foo->bar();  // prints Hello World.
于 2012-10-22T15:15:15.440 回答