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"

変数 $b をパラメーターとしてメソッド bar() に渡すか、クラス コンストラクターに渡すことなく、php で同様のことを行う方法はありますか?? また、グローバル変数も使用したくありません。

EDIT 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
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 に答える
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 に答える
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の意図ではありませんでした。

あなたが求めているのは、オブジェクト指向の基本的な部分です。オブジェクト内にデータのカプセル化が必要です。オブジェクトの目的は、機能的な駐車場にすることではありません。オブジェクトにもデータが含まれているはずです。

したがって、セッターを使用します。

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 に答える