クラスごとに適切なエクスポート/エンコード関数を作成する方がよいと思いますが(エンコードのためだけにプライベート値とパブリック値の両方からパブリックオブジェクトを構築します-非常に賢く、phpのリフレクション機能を使用できます) -代わりに-次のコードを利用できます。
/// example class B
class TestB {
private $value = 123;
}
/// example class A
class TestA {
private $prop;
public function __construct(){
$this->prop = new TestB();
}
}
function json_encode_private($obj){
/// export the variable to find the privates
$exp = var_export($obj, true);
/// get rid of the __set_state that only works 5.1+
$exp = preg_replace('/[a-z0-9_]+\:\:__set_state\(/i','((object)', $exp);
/// rebuild the object
eval('$enc = json_encode('.$exp.');');
/// return the encoded value
return $enc;
}
echo json_encode_private(new TestA());
/// {"prop":{"value":123}}
したがって、上記は機能するはずですがeval
、phpのどこでも使用することはお勧めしません-遠くでアラームベルが静かに鳴るからです:)
アップデート
作成力の一部、または少なくともそれらの力の範囲を制限eval
する使用可能なものを使用するのではなく、これを少し安全にする可能性があるものについて考えただけです...create_function
function json_encode_private($obj){
$exp = var_export($obj, true);
$exp = preg_replace('/[a-z0-9_]+\:\:__set_state\(/i','((object)', $exp);
$enc = create_function('','return json_encode('.$exp.');');
return $enc();
}
アップデート2
単純な関数のみを使用して(evalを使用せずに)、プライベートプロパティを持つオブジェクトをパブリックプロパティを持つオブジェクトに変換する別の方法を試す機会がありました。以下は、使用しているPHPのどのバージョンでもテストする必要があります。これも、変換されたプライベートプロパティのプレフィックスがおかしいため、信頼できない可能性があります(コードのコメントを参照)。\0
Class Name
\0
この奇妙なプレフィックス動作の詳細については、http:
//uk3.php.net/language.types.array.php#language.types.array.castingをご覧ください。
とにかく、テストクラスを使用します。
class RandomClass {
private $var = 123;
private $obj;
public function __construct(){
$this->obj = (object) null;
$this->obj->time = time();
}
}
次の関数を使用して、パブリックオブジェクトに変換できます。
function private_to_public( $a ){
/// grab our class, convert our object to array, build our return obj
$c = get_class( $a ); $b = (array) $a; $d = (object) null;
/// step each property in the array and move over to the object
/// usually this would be as simple as casting to an object, however
/// my version of php (5.3) seems to do strange things to private
/// properties when casting to an array... hence the code below:
foreach( $b as $k => $v ){
/// for some reason private methods are prefixed with a \0 character
/// and then the classname, followed by \0 before the actual key value.
/// This must be some kind of internal protection causing private
/// properties to be ignored. \0 is used by some languges to terminate
/// strings (not php though, as far as i'm aware).
if ( ord($k{0}) === 0 ) {
/// trim off the prefixed weirdnesss..?!
$e = substr($k, 1 + strlen($c) + 1);
/// unset the $k var first because it will remember the \0 even
/// if other values are assigned to it later on....?!
unset($k); $k = $e;
}
/// so if we have a key, either public or private - set our value on
/// the destination object.
if ( $k !== '' && $k !== NULL && $k !== FALSE ) {
$d->{$k} = $v;
}
}
return $d;
}
したがって、すべてをまとめると、次のようになります。
$a = new RandomClass();
echo json_encode( private_to_public( $a ) );
/// {"var":123,"obj":{"time":1349777323}}
繰り返しになりますが、最善/最も信頼できる方法は、クラスごとに変換メソッドを特注でコーディングするか、Class Reflectionを使用してある種の一般化されたソリューションを作成することですが、後者ははるかに複雑で、StackOverflowの回答よりも複雑です...少なくとも私が自由に使える時間;)
詳細情報
上記のコードは、どこからでもオブジェクトにアクセスしようとしたときに機能します。これを実装する理由は、私の最初の試みが明らかに次のものを使用することだったためです。
echo json_encode( get_object_vars($a) );
/// you will get {} which isn't what you expect
使用したい場合get_object_vars
は、すべてのプロパティにアクセスできるコンテキストから、つまり公開しているクラス内から使用する必要があるようです。
public function getAllProperties(){
return get_object_vars( $this );
}
したがって、上記をRandomClass定義に追加したと想像してください。
echo json_encode( $a->getAllProperties() );
/// you will get {"var":123,"obj":{"time":1349777323}}
これは、クラスのメンバーがパブリックまたはプライベートのすべてのクラスのプロパティにアクセスできるために機能します。つまり、私が言うように、この方法での作業ははるかに優れています。優れていますが、常に可能とは限りません。