Using getProperties to get the list of declared properties
lang_of_article_differ
want_proper_trans
Reflection
gives to user possibility to get information about class, function(method of the class), class properties, modules and function parameters. Also Reflection gives possibility to create instances of classes (even with private constructors), invoking method of classes and passing values to properties and so on.
consider we have some class called Post
:
class Post {
public $id;
/**
* this field contains blog post's title
*/
public $title;
/**
* And this one its main content
*/
public $body;
public function save() {
// this method saves model data to databse
}
}
Imagine its a model class that is binded to database table and can be created or updated in it via method save()
:
$somePost->save();
I suggest save
method would have similar to next implementation (shitty code):
public function save() {
$sqlQuery = '';
$setClause = '`title`="'.$this->title.'",'.
'`body` = "'.$this->body.'"';
if ($this->id > 0) {
$sqlQuery = 'UPDATE `post` SET '.$setClause.' WHERE id = '.$this->id;
} else {
$sqlQuery = 'INSERT INTO `post` SET '.$setClause.', id = '.$this->id;
}
return $this->db->execute($sqlQuery);
}
What can we say about this code? Its hardcoded and can be used only in case of Post
class. And what happen if we add some extra column, for example num_views
which would save the number of post's views? - Yes, we should have our save
method rewriten.
How can we solve this problem in general case? - By using a reflection api.
First usage of reflection api
Lets rewrite our save
method:
public function save() {
$class = new \ReflectionClass($this);
$tableName = strtolower($class->getShortName);
$propsToImplode = [];
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { // consider only public properties of the providen
$propertyName = $property->getName();
$propsToImplode[] = '`'.$propertyName.'` = "'.$this->{$propertyName}.'"';
}
$setClause = implode(',',$propsToImplode); // glue all key value pairs together
$sqlQuery = '';
if ($this->id > 0) {
$sqlQuery = 'UPDATE `'.tableName.'` SET '.$setClause.' WHERE id = '.$this->id;
} else {
$sqlQuery = 'INSERT INTO `'.tableName.'` SET '.$setClause.', id = '.$this->id;
}
try {
return $this->db->execute($sqlQuery);
} catch (\Exception $e) {
// proper handling of exception
}
}
In this case we dynamically get the table name (we use lowercased name of the class as a table name) and all the fields that should be updated or inserted.
Now we can use this method not only in Post
class but in any class which should have such functionality and it would work as we expect.
I get the properties of the class which has only public visibility by providing a parameter to getProperties
method of ReflectionClass
instance:
$class->getProperties(\ReflectionProperty::IS_PUBLIC);
getProperties
method of ReflectionClass
returns array of ReflectionProperty
objects. In this lesson we only used method getName
which returns name of the property. e.g title
for
public $title;
You can omit this this parameter to get all properties. Or you can get private or protected properties. You also can check for some visibility by methods of ReflectionProperty
: isPublic
,isPrivate
or isProtected
instead.
Here's what i think you need to know about getting properties on the fly in your php scripts.