PHP 5 CMS Framework Development / 2nd Edition
上QQ阅读APP看书,第一时间看更新

Exploring PHP—indirect references

The power and flexibility of an interpreted language is illustrated in PHP by the possibility of indirect references and other similar constructions. An indirect reference is illustrated with the following code:

$field = 'illustration';
$$field = 'a test string';
echo $illustration;

What will happen is that the phrase 'a test string' will be output. This example is artificial, but we will see how powerful this kind of thing is in the next section, when we consider how data objects can be loaded from the database. In fact, with our OO orientation, it will only rarely be necessary to use the double (or more) dollar signs for flexible references. In many contexts, such as referring to an object property or creating a new object, PHP will let us write a variable name where we might ordinarily write an actual name. So, we can refer to $object->$field when we have previously loaded $field with the name of one of the properties of $object. The same technique can be used with method names.

The value of this is clear if we want to create a data object whose properties are determined by the metadata stored in the database. A query will tell us what fields exist for a particular table, and we can use that information to easily create a data object that corresponds to a particular table row. Or, we can create a whole set of such objects. The metadata tells us about any fields that have not been provided in the data submitted to database handling methods, and they can be given default values depending on their type.

PHP will also help us to handle objects whose details we do not know. The function get_object_vars will return an associative array, where the keys and the names of properties and the values are the current values of the properties. This gives us a way to process all the public properties of an object, without prior knowledge of what they are.

Although not used in this chapter, a similar technique avoids tedious case statements, by using the value of a variable as the name of a method. Suppose we know that an application works differently according to what is in $task, which may have been obtained from the query string part of the URI. The variable can be used directly to invoke one of a number of possible methods within the current class simply by writing $this->$task(), possibly with the addition of some parameters. If $task did not contain the name of a method, the code would fail, but that can be avoided by testing with a standard PHP function method_exists($this, $task) and raising an error or ignoring the request if the result is not true.

The need to test for valid data is a reminder that there are security considerations for these techniques. If the field that is being used in place of writing the actual name has been received as user input, then it is clearly vital to validate it for acceptable values. In the case of calling a method, a simple test eliminates invalid names. Other security constraints may be needed, according to the circumstances.