Core Web Application Development with PHP and MySQL

Here are a number of other operations we will have the opportunity to use on classes and specific object instances.

Comparing Objects

You can use the various comparison operators PHP makes available (== and ===) on objects, but their behavior is worth noting.

  • comparison operator (==) This works on objects by making sure that both objects are of the same type and have the same values for their member data. If either of these is not true, the operator evaluates to FALSE.

  • identity operator (===) This works on objects by indicating if the two objects being compared are the same instance of the class. Otherwise, it evaluates to FALSE.

Cloning Objects

As we mentioned in previous chapters, when you assign an object from one variable to another, you do not copy it, but merely assign a handle or reference to it.

<?php $a = new SomeClass(); $b = $a; // $a and $b point to the same underlying instance of SomeClass ?>

However, situations will arise where we will actually want to assign a full copy of an existing object to a new variable. This is known as cloning, and is done via the clone operator.

<?php $a = new SomeClass(); $b = clone $a; // $b now is a NEW object with all the member variables set // to the values they had in $a ?>

When you clone an object in PHP, the language creates a new instance of the class and assigns copies of the corresponding variables in the original instance to this new object's member variables by default. However, this is a shallow copy, meaning that if one of those member variables is itself a reference to an object, only that reference is copied.

If the default behavior for cloning is not sufficient for your needs, you can implement the __clone function in your class, which PHP calls after it has performed the shallow copy of the member variables. If one of our member variables was a connection to a database, we might want to establish a new connection to the same database when our object is cloned.

<?php class CloneDemo { public $dbconnection; public $connect_string; public function __clone() { // $connect_string is copied for us. $this->dbconnection = $this->reestablish_connection( $this->connect_string); } // etc. } ?>

Now, whenever the object is cloned, the __clone method is called and the connection is also cloned.

User-Friendly Output

Normally, when you call print or echo with an object, you get output similar to the following:

Object id #5

This is largely unhelpful and tells us little about the object. However, we do not always want to use var_dump, print_r, or var_export, since they can be entirely too detailed for our needs.

To get around this, PHP allows us to define a method called __toString on our classes to call the print and echo functions. We can use this to represent the object as we would like and help ourselves with debugging.

<?php class Product implements IProduct { // etc. public function __toString() { return get_class($this) . ", Name: " . $this->get_Name() . ", Price: " . $this->get_PricePerUnit() . "<br/>\n"; } // etc. } ?>

The only caveat to using this function is that it is only called when your class is the sole item passed to a print or echo call.

<?php $prod = new LocalProduct("1-02-11", "Master Fishin' Pole", "Master Fishin' Poles are the ...", 12.99); // // this will print: // "LocalProduct: Name = Master Fishin' Pole, Price: 12.99" // echo $prod; // // this will print: // "About this product: Object id #3<br/>\n" // echo "About this product: " . $prod . "<br/>\n"; ?>

Type Hinting

As we have seen repeatedly throughout this book, PHP takes a dynamic approach to typing and doesn't require us to declare types when we want to use variables or add parameters to functions. However, one place where PHP does give us some extra control of typing is in passing parameters to functions. Programmers now have the option of providing a type hintthis is a way to tell PHP that we expect a parameter to be of a certain class. However, we cannot do this with things that are not objects (for example, integers or strings).

<?php function get_product_info(IProduct $in_product) { // etc. } ?>

In the previous code snippet, the function expects its sole parameter to be of type IProduct. This means that any class that implements IProduct, such as our LocalProduct, NavigationPartnerProduct, or SuperBoatsProduct classes, is acceptable as a parameter to this function. If we wanted the function to only accept function classes that we have written in-house and inherit from Product, we could declare it as follows:

<?php function get_product_info(Product $in_product) { // etc. } ?>

If you try to pass a parameter that does not match the type hint, PHP gives you an error.

Fatal error: Argument 1 must be an object of class IProduct in c:\Inetpub\wwwroot\phpwebapps\src\chapter04\hints on line 7

Autoloading

An additional feature in PHP provides for automatic loading of include files which we will make quick mention of here in case you run across code that use it.

Since most of our class definitions will be in separate files that we can reuse and share between web application scripts, we are obliged to require or include (see Chapter 3, "Code Organization and Reuse," for more details) those files in any script that uses those classes.

PHP5 provides the ability to skip these inclusions, if you so desire, by letting you implement a special function in your script called __autoload. This function receives the name of a class for which PHP cannot find a definition as a parameter. Therefore, you can determine which file you wish to include inside of this function, and then issue the appropriate require or include (or require_once or include_once) operation.

<?php // // all our classes are in files with the pattern: // "classname".inc // function __autoload($in_className) { require_once("$in_className.inc"); } ?>

Again, we will not use this functionality in the book since we will always strive to be explicit and deliberate in our coding. Also, this functionality will not work if our autoloaded class inherits from a base class that is in a separate file that has not been loaded.

Категории