Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Extra properties in the query response object. How to get only the properties I need?

Hello,

Here is my situation. I am using find() to look for a record in a db and I pass it to the ReflectionObject

$result = $this->find($id);
return $this->getResultObjects($result);

...
protected function getResultObjects($result)
{
    foreach ($result as $row) {
        $this->users->setProperty($row);
    }
}

...
public function setProperty($object)
{
    $reflection = new \ReflectionObject($object);

    foreach ($reflection->getProperties() as $property) {
        $property->setAccessible(TRUE);
        $key        = '_' . $property->getName();
        $this->$key = $property->getValue($object);
    }

    return $this;
}

if i leave this as is then i get Phalcon\Exception: Invalid __set property _di that is because i don't have a protected var $_di my model has only:

protected $_id;
protected $_name;
protected $_email;
protected $_password;

but if I var_dump($reflection->getProperties()); i get a lot more properties (see below) and i only want to pass to the ReflectionObject the properties that my model has

Is there a way to only grab the properties I need from the query result and ignore the rest of them?

edit: i know i could just type the name of the properties i want, but that defits the purpose of my getResultObjects() method, that automatically sets the class properties

array (size=18)
0 => &
object(ReflectionProperty)[128]
  public 'name' => string 'di' (length=2)
  public 'class' => string 'Application\Models\Users' (length=24)
1 => &
object(ReflectionProperty)[127]
  public 'name' => string 'usersEntity' (length=11)
  public 'class' => string 'Application\Models\Users' (length=24)
2 => &
object(ReflectionProperty)[126]
  public 'name' => string '_dependencyInjector' (length=19)
  public 'class' => string 'Phalcon\Mvc\Model' (length=17)
3 => &
object(ReflectionProperty)[125]
  public 'name' => string '_modelsManager' (length=14)
  public 'class' => string 'Phalcon\Mvc\Model' (length=17)
...
...
... i want only the ones below 
15 => &
object(ReflectionProperty)[143]
  public 'name' => string 'id' (length=2)
  public 'class' => string 'Application\Models\Users' (length=24)
16 => &
object(ReflectionProperty)[144]
  public 'name' => string 'name' (length=4)
  public 'class' => string 'Application\Models\Users' (length=24)
17 => &
object(ReflectionProperty)[145]
  public 'name' => string 'email' (length=5)
  public 'class' => string 'Application\Models\Users' (length=24)
18 => &
object(ReflectionProperty)[146]
  public 'name' => string 'password' (length=8)
  public 'class' => string 'Application\Models\Users' (length=24)


84.5k
Accepted
answer

I think the strategy of using ReflectionObject is not optimal here. Maybe a better approach would be query the models meta-data service:

public function setProperty($object)
{
    foreach ($object->getModelsMetaData()->getAttributes($object) as $property) {        
        $object->writeAttribute($property, $object->readAttribute($property));
    }
    return $this;
}

how would you rewrite the getProperty ?

im getting Warning: ReflectionClass::__construct() expects exactly 1 parameter, 0 .. so i think i need to rewrite this method as well

public function getProperties($object = NULL)
{
    $object = NULL == $object ? $this : $object;

    $array = array();

    $reflection = new \ReflectionObject($object);

    foreach ($reflection->getProperties(\ReflectionProperty::IS_PROTECTED) as $property) {
        $property->setAccessible(TRUE);
        if (!$property->isStatic()) {
            $array[preg_replace('/_/', '', $property->getName(), 1)] = $property->getValue($object);
        }
    }

    if (empty($array)) return '';

    return $array;
}


84.5k

I would not use \ReflectionClass or ReflectionObject either. Why not give a try to the meta-data service?

:) ok, will do

edited Jul '14

Just as an addon, this is what worked for me

public function setProperty($object)
{
    foreach ($object->getModelsMetaData()->getAttributes($object) as $property) {
        $key        = '_' . $property;
        $this->$key = $object->readAttribute($property);
    }

    return $this;
}

this $object->writeAttribute($property, $object->readAttribute($property)); doesn't set the properties, they become NULL, even if I add the _.

I would like to know why, but either way the code works using the meta-data

thanks