2010-05-12 18 views
20

Estoy tratando de crear un objeto PHP (5) que pueda recorrer sus propiedades, creando una consulta SQL basada solo en sus propiedades públicas, no en las privadas.Detectar si una propiedad de objeto es privada en PHP

Como este método de objetos primarios debe ser utilizado por objetos secundarios, no puedo simplemente omitir las propiedades privadas por nombre (no sabré qué son en los objetos secundarios).

¿Existe una manera simple de detectar desde el interior de un objeto cuáles de sus propiedades son privadas?

Aquí está un ejemplo simplificado de lo que tengo hasta ahora, pero esta salida incluye el valor de $ bar:

class testClass { 

    public $foo = 'foo'; 
    public $fee = 'fee'; 
    public $fum = 'fum'; 

    private $bar = 'bar'; 

    function makeString() 
    { 
     $string = ""; 

     foreach($this as $field => $val) { 

      $string.= " property '".$field."' = '".$val."' <br/>"; 

     } 

     return $string; 
    } 

} 

$test = new testClass(); 
echo $test->makeString(); 

proporciona la salida:

property 'foo' = 'foo' 
property 'fee' = 'fee' 
property 'fum' = 'fum' 
property 'bar' = 'bar' 

me gustaría que para no incluir 'bar'.

Si hay una forma mejor de iterar solo a través de las propiedades públicas de un objeto, eso funcionaría también aquí.

Respuesta

9

Puede usar Reflection para examinar las propiedades de la clase. Para obtener solo propiedades públicas y protegidas, perfile un filtro adecuado para el método ReflectionClass::getProperties.

Aquí hay un rápido ejemplo de su método makeString usándolo.

public function makeString() 
{ 
    $string = ""; 
    $reflection = new ReflectionObject($this); 
    $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC); 
    foreach ($properties as $property) { 
     $name = $property->getName(); 
     $value = $property->getValue($this); 
     $string .= sprintf(" property '%s' = '%s' <br/>", $name, $value); 
    } 
    return $string; 
} 
+0

Gracias, creo que powtac te ganó en unos 30 segundos, pero sí, eso funciona exactamente como es necesario. – Hippyjim

+0

Sí, creo que se pasó demasiado tiempo haciendo una bonita respuesta con enlaces limpios y ordenados a los documentos. Lección aprendida, respuestas rápidas y sucias de aquí en adelante! :-) – salathe

1
foreach (get_class_vars(get_class($this)) .... 
+0

También está la clase de reflexión y el método mágico __get() – powtac

+0

Tienes razón, devuelve los valores del alcance actual -> $ esto significa que todos ... – powtac

+0

Me temo que ignoro el clase de reflexión - Voy a tener que hacer un poco de búsqueda en Google. Gracias por el puntero. – Hippyjim

1

Puede usar una matriz para almacenar propiedades públicas, agregar algún método de envoltura y usar una matriz para insertar datos en SQL.

18

Comprobar el código de http://php.net/manual/reflectionclass.getproperties.php#93984

public function listProperties() { 
    $reflect = new ReflectionObject($this); 
    foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC /* + ReflectionProperty::IS_PROTECTED*/) as $prop) { 
     print $prop->getName() . "\n"; 
    } 
    } 
+2

Eso es exactamente lo que necesitaba. Gracias por la lección! – Hippyjim

2

Si lanzas el objeto a un arreglo antes de iterar sobre ella, los miembros privados y protegidos tendrá prefijos especiales:

class Test{ 
    public $a = 1; 
    private $b = 1; 
    protected $c = 1; 
} 
$a = new Test(); 
var_dump((array) $a); 

muestra esto:

array(3) { 
    ["a"]=> 
    int(1) 
    ["Testb"]=> 
    int(1) 
    ["*c"]=> 
    int(1) 
} 

También hay caracteres ocultos que no se muestran. Pero puedes escribir código para detectarlos. Por ejemplo, la expresión regular /\0\*\0(.*)$/ coincidirá con las claves protegidas, y /\0.*\0(.*)$/ coincidirá con las privadas. En ambos, el primer grupo de captura coincide con el nombre del miembro.

4

una solución más rápida que he encontrado:

class Extras 
{ 
    public static function get_vars($obj) 
    { 
     return get_object_vars($obj); 
    } 
} 

y luego llamar dentro de sus TestClass:

$vars = Extras::get_vars($this); 

additional reading in PHP.net

0

Puede utilizar API de reflexión para comprobar la visibilidad de propiedades:

$rp = new \ReflectionProperty($object,$property); 
if($rp->isPrivate) { 
    // Run if the property is private 
} else { 
    // Run if the property is Public or Protected 
} 
Cuestiones relacionadas