0

私は私の試みで3つのトリックを使用しています:

  • リフレクションは動的クラス プロパティでは使用できません
  • 動的クラス プロパティにアクセスするときは、__get() または __set() を呼び出す必要があります。
  • debug_backtrace() を利用して、次のようなものをエミュレートできますprivate

Fooプライベートな非静的プロパティを持つクラスの場合、外部のスコープがその値を変更すること$barを禁止したいと考えています。$thisしたがって、私はこのようにしています:

/** @property object $bar */
class Foo{
    public function __get($k){
        if($k === "bar") return $this->bar;
    }
    public function __set($k, $v){
        if($k === "bar"){
            $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
            if($trace[0]["object"] !== $this or $trace[0]["file"] !== __FILE__) throw new RuntimeException("Illegal access");
            $this->bar = $v;
        }
    }
}

これは (テストされていませんが) 3 種類のアクセスに対して無敵である必要があります。

  • 直接アクセス
    • debug_backtrace() は、呼び出しコンテキストが $this からのものかどうかをチェックします。$this の外への直接アクセスは許可されません。
  • 反射プロパティ
    • PHP の致命的なエラー: キャッチされていない ReflectionException: プロパティ バーが存在しません
    • リフレクションは動的プロパティでは機能しません。その存在を検出することすらありませんReflectionClass::hasProperty():-)
  • Closure::bind
    • テストされていませんが、 debug_backtrace() はFILEとは異なる「ファイル」を返す必要があると思いますが、クロージャを定義したファイルを返します。私は の正しい使い方しか持ってFooいないので、正しいコードがロードされている限り気にしません。

ファイルを書き込む権限がなく、クラス メソッドを再定義する拡張機能がないが、任意の PHP コードを読み込むことができると仮定すると、このFoo->barプロパティを変更するメソッドはありますか?

4

1 に答える 1

1

少しいじくり回した後、あなたが達成しようとしていることは不可能であり、無意味であるという結論に達しました。その理由を説明します。

クラス プロパティには、 publicprotected、およびprivateの 3 つの可視性があります。publicの場合、簡単な代入で値を変更できます。

$foo->bar = "new value";

でこれをインターセプトできます__set()か? PHPマニュアルから:

__set() は、アクセスできないプロパティにデータを書き込むときに実行されます。

パブリックプロパティは常にアクセス可能です。したがって、呼び出されないため、インターセプトしてチェックを行う機会はまったくあり__set()ません。

次に、プロパティがprotectedまたはprivateの場合、クラスで宣言する必要があります。つまり、その値を使用ReflectionPropertyまたはClosure::bind変更できます。

最後に、値を別の場所に保存することで、 が実際に__set()呼び出されることを確認できます。たとえば、同じオブジェクトの別の名前で、または別のオブジェクトでも。残念ながら、値をどこに保存しても、上記の説明が再び適用されるため、意味がありません。

于 2017-01-09T00:48:52.057 に答える