2017-06-24 6 views
1

PHPでは、宣言されていないクラスのプロパティ/変数は、デフォルトで「public」可視性になります。PHP:宣言されていないクラスのプロパティのデフォルトの可視性をprotected/privateに変更する

デフォルトの可視性を「保護」(またはプライベート)に変更する方法はありますか(一部ではありますが、すべてではありません)。

私はそれらをすべて正常に宣言することをお勧めします。しかし、この場合は、たくさんの列を持つSQLビューからのモデルクラスのレイヤーがたくさんあります。私はこれらを "保護された"デフォルトにしたいと思っています(私のフロントエンドの開発者がHTMLエスケープなしで生の値を使用するのを防ぐため)。そして、 "public"アクセスが必要なときは、そう宣言します。つまり、セキュリティ関連の記事を見ると、「ブラックリスト保護/非公開」ではなく、「ホワイトリストに公開」したいと考えています。

答えて

2

このレベルの可視性コントロールが必要な場合は、クラスを宣言しなければなりません。あなたの質問に直接、いいえ、視界を動的に設定する方法はありません。

ドキュメントにはstdClassオブジェクトタイプへの特定のセッションがありませんが、(object)を使用して変換する配列は、数値以外のインデックスをパブリックプロパティとして追加したstdClassオブジェクトになります。 http://php.net/manual/en/language.types.object.php#language.types.object.casting

一般的な解決策は、protectedというプロパティを持つクラスであり、配列になり、値を保持することになります。あまりにもインデックスを期待して、生の値またはエスケープされた値のどちらかを返すアクセスメソッドを記述する必要があります。

+0

お返事ありがとうございます。明確にするために、名前付きクラスを定義しています(クラス名はSQLビュー名と一致しています)。これらのクラスは私のフレームワークのベースモデルクラスを拡張しているので、データは自動的にオブジェクトに取り込まれ、配列やstdClassオブジェクトなどを扱うことはありません。しかし、私はどのような場合でも、クラスの宣言されていないプロパティのデフォルトの可視性を変更する方法はないと思いますか?1つの保護された配列にすべてのフィールドを格納するのは良いカスタムソリューションですが、私はフレームワークの動作を保持して、各フィールドを別々のオブジェクトプロパティに入れたいと考えています。 – YeB

1

あなたはあなたが求めていることを達成するためにリフレクションを使用しなければなりません。

<?php 
class MyClass { 
    private $myProperty = true; 
} 

$class = new ReflectionClass("MyClass"); 
$property = $class->getProperty("myProperty"); 
$property->setAccessible(true); 

$obj = new MyClass(); 
echo $property->getValue($obj); // Works 
echo $obj->myProperty; // Doesn't work (error) 
?> 

参照してください。その場合にはReflectionProperty::setAccessible

のためのPHPマニュアル、おそらくマジックメソッドを使用する必要があります。これらの線に沿って何か。

class Person { 

    private $properties = [ 
     'first_name' => ['visibility'=>'public','value'=>null] 
     'last_name' => ['visibility'=>'public','value'=>null], 
     'income' => ['visibility'=>'private','value'=>null] 
    ]; 

    function __get($name) { 
     if (array_key_exists($name, $this->properties) && $this->properties[$name]['visibility'] == 'public') 
      return $this->properties[$name]; 
    } 

    function __set($name, $value) { 
     if (array_key_exists($name, $this->properties) && $this->properties[$name]['visibility'] == 'public') 
      $this->properties[$name] = $value); 
    } 
} 
+0

お返事ありがとうございます。私が誤解していない限り、私はあなたが最初にプライベートとしてすべてのプロパティを宣言する必要があります示唆していると思いますか? 'private $ myProperty' ... **宣言されていない**プロパティのデフォルトの可視性を変更することを求めています。すなわち、私は、プロパティの名前が何であるかも知らないと仮定します。 – YeB

+0

2番目の考えでは、プロパティが別の "プロパティ"クラスのインスタンスであるクラスを作成し、_properties_が動的なのでReflectionを使用することができます。基本的には、すべてのクラスのために独自の「ベース」クラスを作成して意味がありますか? "オートボクシング"と考えてください。 –

+0

また、[jasny/meta](https://packagist.org/packages/jasny/meta)を使用すると、特性によって目立たないクラスや配列にメタデータを割り当てることができます。 –

0

いいえありません。

しかし、あなたのクラスは実際には未定義のプロパティを使うべきではありません。ほとんどの場合、これはコード内に「問題」(完全な「間違い」ではない場合)があることを示します。

あなた実際の問題について:私は個人的に私のdata mappersにこのようなコードを使用します。

public function applyValues($instance, array $parameters) 
{ 
    foreach ($parameters as $key => $value) { 
     $method = 'set' . str_replace('_', '', $key); 
     if (method_exists($instance, $method)) { 
      $instance->{$method}($value); 
     } 
    } 
} 

PHPのメソッド名は大文字と小文字は区別されませんので、このアプローチはcamelCaseunder_score命名の両方で動作しますSQLの規約。

この方法は基本的に「ホワイトリスト」として機能します。ドメインオブジェクトにセッターが定義されている場合は、その値が適用されます。そうでない場合、無視されます。 Twigを使用している場合は(おそらく)、<p>{{ entity.content }}</p>には$entity->getContent()が呼び出されます。

関連する問題