2017-10-27 13 views
0

更新

私はduskwuffの答えに基づいて解決策を見つけました。彼は私が尋ねた質問に答えました。これは将来の誰かのためのものです - 主に自分。__getと__setの関数をトリガする際の問題

彼が発行さを述べたように、私は保護された属性$attributesではなく__get__setが適切にトリガすることを可能にするオブジェクト自体に値を割り当てるために__constructorを更新しました$this->{$key} = $val;

に嘘をつきました。

私はコードの残りの部分をそのまま残しました。


最近私は新しいプロジェクトに取り組み始めました。私はそれほど馴染みがありません。 MongoDBとSql Serverからレコードを取得するためのカスタムクラスが用意されています。すべてのSql ServerとMongoモデルは、クラスを、対応するMongoModelクラスとMsSqlModelクラスを中間にして拡張します。

例:私はVendorモデルファイルにCryptarchクラスとEncryptableクラスを含めましテスト目的のために>MongoModel extends DatabaseModelVendor extends MongoModel>DatabaseModel extends Model

class Model implements JsonSerializable, IteratorAggregate { 
    ... 
    public function __construct($attributes = []) { 
     foreach ($attributes as $key => $val) 
      $this->{$key} = $val; 
    } 
    ... 
    public function &__get($key) { 
     if ($this->isPrivateKey($key)) { 
      return $this->$key; 
     } else { 
      return $this->attributes[$key]; 
     } 
    } 

    public function __set($key, $value) { 
     if ($this->isPrivateKey($key)) { 
      $this->$key = $value; 
     } else { 
      $this->attributes[$key] = $value; 
     } 
    } 
    ... 
} 

Cryptarchには2つの機能しかありませんencryptdecrypt - 必要に応じて投稿できますが、私はセキュリティ専門家ではないので特別なことはありません。道のうちそれと

trait Encryptable { 

    public function &__get($key) { 

     $value = parent::__get($key); 

     if (in_array($key, $this->encryptable)) { 
      return Cryptarch::decrypt($value); 
     } 

     return $value; 

    } 

    public function __set($key, $value) { 

     if (in_array($key, $this->encryptable)) { 
      $value = Cryptarch::encrypt($value); 
     } 

     parent::__set($key, $value); 

    } 

} 

class Vendor extends MongoModel 
{ 
    use Encryptable; 

    protected $encryptable = [ 
     'ssn' 
    ]; 
    ... 
} 

、私は自動的にモデルの属性は、(暗号化)を設定するか、または(復号化)を取得しているときに、機密情報を暗号化/復号化しようとしています。私var_dump($res->ssn)私は値を復号化されたのではなく、暗号化値を取得する場合 $res = Vendor::load('myid'); :私のページで

は、私は単に私がテストしたいレコードをロードしています。

値を$res->ssn = 'somethingelse';およびvar_dump($res->ssn)に設定すると、出力はstring(13) "somethingelse"となります。

しかし、私はEncryptableから__set機能を削除し、出力$res->ssnしようとすると、私は適切に復号化された値を取得します。

私はCryptarch::decrypt($val)でパラメータをvar_dumpた場合、私はDB(暗号化)から正しい値を取得する - ないbool(false)openssl_decryptたいものだ、それは暗号化された値を返しますが、私はvar_dumpしようとすると「復号化された」復号化機能に起因するとexit;失敗した場合は返します。私は($val = 'encryptedstring';)DBからの直接値で復号化するパラメタを無効にし、var_dump復号化された結果は正常に動作します。

ここでは、ページ/サイトの残りの部分は、Encryptableの特性を使用してVendorで動作します。私はまだ値を設定し、それらを保存し、それらをフェッチすることができます。ハングアップの原因となっているのは、bool(false)openssl_decrypt)の代わりに同じ値を返します。失敗した場合は値を設定しても暗号化されません。

答えて

2

PHPの制限があります。__get__setのマジック関数は、オブジェクトに存在しない属性にアクセスしたときにのみ起動します。それらは存在する属性に対して決して呼び出されません。

__setの実装が含まれています:オブジェクトの属性を設定することができ

$this->$key = $value; 

。この方法で作成された属性は、__getまたは__setメソッドを呼び出さなくなります。

+0

だから、私が望む属性/データが暗号化/復号化される必要があるかどうかを自動的にチェックする最良の方法は何ですか?私は一種の喪失です。もともとは、 'Model'クラスに列/属性を暗号化/復号化するための追加機能をセットアップしましたが、余分なステップを削除することでよりうまくいくように思えました。 –

+2

フィールドにアクセスするときではなく、オブジェクトをデータベースに格納する/データベースからロードするときに、暗号化/復号化を実行するのが私の傾向です。 – duskwuff

+0

申し訳ありません、私はそれを感謝します! –

関連する問題