In the last section of this chapter, Zeev discusses the object model brought by the Zend engine, specifically how it differs from the model in previous versions of PHP.
When we developed PHP3 in the summer of 1997, we didn't The plan was to make PHP object-oriented. At that time, there were no ideas related to classes and objects. PHP3 is a purely process-oriented language. However, support for classes was added in the PHP3 alpha version on the evening of 1997.8.27. Added A new feature for PHP only required minimal discussion at that time because there were too few people exploring PHP at that time. So from August 1997, PHP took the first step towards an object-oriented programming language.
Really, this is just the first step. Because there are very few relevant ideas in this design, the support for objects is not strong enough. Using objects in this version is just a cool way to access arrays. Instead of using $foo ["bar"], you can use the nicer-looking $foo->bar. The main advantage of the object-oriented approach is to store functionality through member functions or methods. A typical code block is shown in Example 6.18. But It is actually not much different from the approach in Example 6.19.
Listing 6.18 PHP 3 object-oriented programming Object-oriented programming in PHP3
class Example
{
var $value = "some value";
function PrintValue()
{
print $this->value;
}
}
$obj = new Example();
$obj->PrintValue();
?> Listing 6.19 PHP 3 structural programming PHP3 Structured programming in PHP3
function PrintValue($arr)
{
print $arr["value"];
}
function CreateExample()
{
$arr["value"] = "some value";
$arr["PrintValue"] = "PrintValue";
return $arr;
}
$arr = CreateExample();
//Use PHP's indirect reference
$arr["PrintValue"]($arr);
?> Above we write two lines of code in the class, or Pass the array to the function explicitly. But considering that these two options are not any different in PHP3, we can still access the array using the object model as just a "syntactic whitewash".
Want to use People who used PHP for object-oriented development, especially those who wanted to use design patterns, quickly found that they hit a wall. Fortunately, at that time (PHP3 era), not many people wanted to use PHP for object-oriented development.
PHP4 changed this situation. The new version brings the concept of reference, which allows different identifiers in PHP to point to the same address in memory. This means that you can use two or more Name to name the same variable, as in Example 6.20.
Listing 6.20 PHP 4 references References in PHP4
$a = 5;
//$b points to the same place in memory as $a $b and $a point to the same address in memory
$b = & $a;
//we're changing $b, since $a is pointing to Change $b, the address pointed to changes
//the same place - it changes too The address pointed to by $a also changes Change
$b = 7;
//prints 7 Output 7
print $a;
?> Since building a network of objects pointing to each other is the basis of all object-oriented design patterns , this improvement is of great significance. While references allow the creation of more powerful object-oriented applications, PHP's treatment of objects and other types of data the same way brings great pain to developers. As any PHP4 programmer will Let me tell you, the application will suffer from WTMA (Way Too Many Ampersands&) syndrome. If you want to build a practical application, you will feel extremely painful. Take a look at Example 6.21 and you will understand.
Listing 6.21 Problems with objects in PHP 4 Problems using objects in PHP4
1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 5;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me ->value;
21 }
22 }
23
24 function CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case " foo":
28 $obj = new MyFoo();
29 break;
30 case "bar":
31 $obj = new MyBar();
32 break;
33 }
34 return $obj;
35 }
36
37 $global_obj = CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj-> ;getValue() . "n";
41 print "Value is " . $global_obj->getValueFromMe() . "n";
Let's discuss it step by step. First, there is a MyFoo class. In the constructor, we give $this->me a reference and set
We have three other member functions: One sets this-> ;The value of value; one returns the value of this->value; the other returns the value of this->value->me. But isn't --$this the same thing? MyFoo::getValue() and MyFoo: Isn't the value returned by :getValueFromMe() the same?
First, we call CreateObject("foo"), which will return an object of type MyFoo. Then we call MyFoo::setValue(7). Finally , we call MyFoo::getValue() and MyFoo::getValueFromMe(), expecting to get the return value 7.
Of course, if we get 7 in any case, the above example will not be the least meaningful in this book Example. So I’m sure you’ve guessed it — we don’t get two 7s.
But what result will we get, and more importantly, why?
We will The results obtained are 7 and 5 respectively. As for why---there are three good reasons.
First, look at the constructor. When inside the constructor, we establish between this and this->me Reference. In other words, this and this->me are the same thing. But we are inside the constructor. When the constructor ends, PHP needs to re-create the object (the result of new MyFoo, line 28) and assign it to $obj . Because objects are not specialized, just like any other data type, assigning X to Y means that Y is a copy of X. That is, obj will be a copy of new MyFoo, which is a copy of The object of the function. What about Obj->me? Because it is a reference, it still points to the original object - this. Voila-obj and obj->me are no longer the same thing - change it One does not change the other.
The above is the first reason. There are other reasons similar to the first. Miraculously we are going to overcome the problem of instantiating objects (line 28). Once we put When the value returned by CreateObject is assigned to global_object, we still run into the same problem - global_object will become a copy of the return value, and again, global_object and global_object->me will no longer be the same. This is the second reason.
But, actually we can’t go that far — once CreateObject returns $obj, we will destroy the reference (line 34). This is the third reason.
So, how do we Correct this? There are two options. One is to add ampersands everywhere, like in Example 6.22 (lines 24, 28, 31, 37). 2. If you are lucky enough to use PHP5, you can forget the above All this, PHP5 will automatically consider these issues for you. If you want to know how PHP5 considers these issues, continue reading.
Listing 6.22 WTMA syndrome in PHP 4 WTMA syndrome in PHP4
1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 2;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me ->value;
21 }
22 };
23
24 function &CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo":
28 $obj =& new MyFoo();
29 break;
30 case "bar":
31 $obj =& new MyBar();
32 break ;
33 }
34 return $obj;
35 }
36
37 $global_obj =& CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj- >getValue() . "n";
41 print "Value is " . $global_obj->getValueFromMe() . "n"; PHP5 is the first PHP version to treat objects differently from other types of data From the user's perspective, this proves to be very clear - in PHP5, objects are always passed by reference, while other types of data (such as integer, string, array) are passed by value. Most notably, There is no need to use the & symbol to indicate passing objects by reference.
Object-oriented programming makes extensive use of object networks and complex relationships between objects, all of which require the use of references. In previous versions of PHP , the reference needs to be specified explicitly. Therefore, moving objects by reference is now used by default, and objects are copied only when copying is explicitly requested, which is better than before.
How is it implemented?
Before PHP5, all values were stored in a special structure called zval (Zend Value). These values could be stored in simple values, such as numbers and strings, or complex values such as arrays and objects. When the value When passed to or returned from a function, these values are copied, creating a structure with the same contents at another address in memory.
In PHP5, the values are still stored in the zval structure, but the object Except. Objects exist in a structure called Object Store, and each object has a different ID. In Zval, the object itself is not stored, but the pointer of the object is stored. When copying a zval structure holding an object, for example, we By passing an object as a parameter to a function, we don't copy any data. We just keep the same object pointer and let another zval notify the Object Store that this particular object now points to. Since the object itself is located in the Object Store, we Any changes it makes will affect all zval structures holding pointers to the object. This additional indirection makes it appear as if PHP objects are always passed by reference, in a transparent and efficient manner.
Using PHP5, we can now go back to Example 6.21 and remove all the ampersands, and everything will still work fine. Not a single ampersand is used when we hold a reference in the constructor (line 4). < ;Full article complete>