Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 90 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
90
Dung lượng
1,83 MB
Nội dung
148 CHAPTER 6 ■ OBJECT-ORIENTED PHP Constructors and Destructors Often, you’ll want to execute a number of tasks when creating and destroying objects. For example, you might want to immediately assign several fields of a newly instantiated object. However, if you have to do so manually, you’ll almost certainly forget to execute all of the required tasks. Object-oriented programming goes a long way toward removing the possibility for such errors by offering special methods, called constructors and destructors, that automate the object creation and destruction processes. Constructors You often want to initialize certain fields and even trigger the execution of methods found when an object is newly instantiated. There’s nothing wrong with doing so immediately after instantiation, but it would be easier if this were done for you automatically. Such a mechanism exists in OOP, known as a constructor. Quite simply, a constructor is defined as a block of code that automatically executes at the time of object instantiation. OOP constructors offer a number of advantages: • Constructors can accept parameters, which are assigned to specific object fields at creation time. • Constructors can call class methods or other functions. • Class constructors can call on other constructors, including those from the class parent. This section reviews how all of these advantages work with PHP 5’s improved constructor functionality. ■Note PHP 4 also offered class constructors, but it used a different, more cumbersome syntax than that used in version 5. Version 4 constructors were simply class methods of the same name as the class they represented. Such a convention made it tedious to rename a class. The new constructor-naming convention resolves these issues. For reasons of compatibility, however, if a class is found to not contain a constructor satisfying the new naming convention, that class will then be searched for a method bearing the same name as the class; if located, this method is considered the constructor. PHP recognizes constructors by the name __construct. The general syntax for constructor declaration follows: function __construct([argument1, argument2, , argumentN]) { /* Class initialization code */ } As an example, suppose you wanted to immediately populate certain book fields with information specific to a supplied ISBN. For example, you might want to know the title and author of the book, in addition to how many copies the library owns, and how many are pres- ently available for loan. This code might look like this: Gilmore_5475.book Page 148 Friday, November 11, 2005 1:16 PM CHAPTER 6 ■ OBJECT-ORIENTED PHP 149 <?php class book { private $title; private $isbn; private $copies; public function __construct($isbn) { $this->setIsbn($isbn); $this->getTitle(); $this->getNumberCopies(); } public function setIsbn($isbn) { $this->isbn = $isbn; } public function getTitle() { $this->title = "Beginning Python"; print "Title: ".$this->title."<br />"; } public function getNumberCopies() { $this->copies = "5"; print "Number copies available: ".$this->copies."<br />"; } } $book = new book("159059519X"); ?> This results in: Title: Beginning Python Number copies available: 5 Of course, a real-life implementation would likely involve somewhat more intelligent get methods (methods that query a database, for example), but the point is made. Instantiating the book object results in the automatic invocation of the constructor, which in turn calls the setIsbn(), getTitle(), and getNumberCopies() methods. If you know that such method should be called whenever a new object is instantiated, you’re far better off automating the calls via the constructor than attempting to manually call them yourself. Additionally, if you would like to make sure that these methods are called only via the constructor, you should set their scope to private, ensuring that they cannot be directly called by the object or by a subclass. Gilmore_5475.book Page 149 Friday, November 11, 2005 1:16 PM 150 CHAPTER 6 ■ OBJECT-ORIENTED PHP Invoking Parent Constructors PHP does not automatically call the parent constructor; you must call it explicitly using the parent keyword. An example follows: <?php class Staff { protected $name; protected $title; function __construct() { echo "<p>Staff constructor called!</p>"; } } class Manager extends Staff { function __construct() { parent::__construct(); echo "<p>Manager constructor called!</p>"; } } $employee = new Manager(); ?> This results in: Staff constructor called! Manager constructor called! Neglecting to include the call to parent::__construct() results in the invocation of only the Manager constructor, like this: Manager constructor called! Invoking Unrelated Constructors You can invoke class constructors that don’t have any relation to the instantiated object, simply by prefacing __constructor with the class name, like so: classname::__construct() Gilmore_5475.book Page 150 Friday, November 11, 2005 1:16 PM CHAPTER 6 ■ OBJECT-ORIENTED PHP 151 As an example, assume that the Manager and Staff classes used in the previous example bear no hierarchical relationship; instead, they are simply two classes located within the same library. The Staff constructor could still be invoked within Manager’s constructor, like this: Staff::__construct() Calling the Staff constructor like this results in the same outcome as that shown in the previous example. ■Note You may be wondering why the extremely useful constructor-overloading feature, available in many OOP languages, has not been discussed. The answer is simple: PHP does not support this feature. Destructors Although objects were automatically destroyed upon script completion in PHP 4, it wasn’t possible to customize this cleanup process. With the introduction of destructors in PHP 5, this constraint is no more. Destructors are created like any other method, but must be titled __destruct(). An example follows: <?php class Book { private $title; private $isbn; private $copies; function __construct($isbn) { echo "<p>Book class instance created.</p>"; } function __destruct() { echo "<p>Book class instance destroyed.</p>"; } } $book = new Book("1893115852"); ?> Here’s the result: Book class instance created. Book class instance destroyed. Gilmore_5475.book Page 151 Friday, November 11, 2005 1:16 PM 152 CHAPTER 6 ■ OBJECT-ORIENTED PHP When the script is complete, PHP will destroy any objects that reside in memory. Therefore, if the instantiated class and any information created as a result of the instantiation reside in memory, you’re not required to explicitly declare a destructor. However, if less volatile data were created (say, stored in a database) as a result of the instantiation, and should be destroyed at the time of object destruction, you’ll need to create a custom destructor. Static Class Members Sometimes it’s useful to create fields and methods that are not invoked by any particular object, but rather are pertinent to, and are shared by, all class instances. For example, suppose that you are writing a class that tracks the number of Web page visitors. You wouldn’t want the visitor count to reset to zero every time the class was instantiated, and therefore you would set the field to be of the static scope: <?php class visitors { private static $visitors = 0; function __construct() { self::$visitors++; } static function getVisitors() { return self::$visitors; } } /* Instantiate the visitors class. */ $visits = new visitors(); echo visitors::getVisitors()."<br />"; /* Instantiate another visitors class. */ $visits2 = new visitors(); echo visitors::getVisitors()."<br />"; ?> The results are as follows: 1 2 Gilmore_5475.book Page 152 Friday, November 11, 2005 1:16 PM CHAPTER 6 ■ OBJECT-ORIENTED PHP 153 Because the $visitors field was declared as static, any changes made to its value (in this case via the class constructor) are reflected across all instantiated objects. Also note that static fields and methods are referred to using the self keyword and class name, rather than via the this and arrow operators. This is because referring to static fields using the means allowed for their “regular” siblings is not possible, and will result in a syntax error if attempted. ■Note You can’t use $this within a class to refer to a field declared as static. The instanceof Keyword Another newcomer to PHP 5 is the instanceof keyword. With it, you can determine whether an object is an instance of a class, is a subclass of a class, or implements a particular interface, and do something accordingly. For example, suppose you wanted to learn whether an object called manager is derived from the class Staff: $manager = new Staff(); if ($manager instanceof staff) echo "Yes"; There are two points worth noting here. First, the class name is not surrounded by any sort of delimiters (quotes). Including them will result in a syntax error. Second, if this comparison fails, then the script will abort execution! The instanceof keyword is particularly useful when you’re working with a number of objects simultaneously. For example, you might be repeatedly calling a particular function, but want to tweak that function’s behavior in accordance with a given type of object. You might use a case statement and the instanceof keyword to manage behavior in this fashion. Helper Functions A number of functions are available to help the developer manage and use class libraries. These functions are introduced in this section. class_exists() boolean class_exists(string class_name) The class_exists() function returns TRUE if the class specified by class_name exists within the currently executing script context, and returns FALSE otherwise. get_class() string get_class(object object) The get_class() function returns the name of the class to which object belongs, and returns FALSE if object is not an object. Gilmore_5475.book Page 153 Friday, November 11, 2005 1:16 PM 154 CHAPTER 6 ■ OBJECT-ORIENTED PHP get_class_methods() array get_class_methods (mixed class_name) The get_class_methods() function returns an array containing all method names defined by the class class_name. get_class_vars() array get_class_vars (string class_name) The get_class_vars() function returns an associative array containing the names of all fields and their corresponding values defined within the class specified by class_name. get_declared_classes() array get_declared_classes(void) The function get_declared_classes() returns an array containing the names of all classes defined within the currently executing script. The output of this function will vary according to how your PHP distribution is configured. For instance, executing get_declared_classes() on a test server produces a list of 63 classes. get_object_vars() array get_object_vars(object object) The function get_object_vars() returns an associative array containing the defined fields available to object, and their corresponding values. Those fields that don’t possess a value will be assigned NULL within the associative array. get_parent_class() string get_parent_class(mixed object) The get_parent_class() function returns the name of the parent of the class to which object belongs. If object’s class is a base class, then that class name will be returned. interface_exists() boolean interface_exists(string interface_name [, boolean autoload]) The interface_exists() function determines whether an interface exists, returning TRUE if it does and FALSE otherwise. is_a() boolean is_a(object object, string class_name) Gilmore_5475.book Page 154 Friday, November 11, 2005 1:16 PM CHAPTER 6 ■ OBJECT-ORIENTED PHP 155 The is_a() function returns TRUE if object belongs to a class of type class_name, or if it belongs to a class that is a child of class_name. If object bears no relation to the class_name type, FALSE is returned. is_subclass_of() boolean is_subclass_of (object object, string class_name) The is_subclass_of() function returns TRUE if object belongs to a class inherited from class_name, and returns FALSE otherwise. method_exists() boolean method_exists(object object, string method_name) The method_exists() function returns TRUE if a method named method_name is available to object, and returns FALSE otherwise. Autoloading Objects For organizational reasons, it’s common practice to place each class in a separate file. Returning to the library scenario, suppose the management application called for classes representing books, employees, events, and patrons. Tasked with this project, you might create a directory named classes and place the following files in it: Books.class.php, Employees.class.php, Events.class.php, and Patrons.class.php. While this does indeed facilitate class management, it also requires that each separate file be made available to any script requiring it, typically through the require_once() statement. Therefore, a script requiring all four classes would require that the following statements be inserted at the beginning: require_once("classes/Books.class.php"); require_once("classes/Employees.class.php"); require_once("classes/Events.class.php"); require_once("classes/Patrons.class.php"); Managing class inclusion in this manner can become rather tedious, and adds an extra step to the already often complicated development process. To eliminate this additional task, the concept of autoloading objects was introduced in PHP 5. Autoloading allows you to define a special __autoload function that is automatically called whenever a class is referenced that hasn’t yet been defined in the script. Returning to the library example, you can eliminate the need to manually include each class file by defining the following function: function __autoload($class) { require_once("classes/$class.class.php"); } Gilmore_5475.book Page 155 Friday, November 11, 2005 1:16 PM 156 CHAPTER 6 ■ OBJECT-ORIENTED PHP Defining this function eliminates the need for the require_once() statements, because when a class is invoked for the first time, __autoload() will be called, loading the class according to the commands defined in __autoload(). This function can be placed in some global application configuration file, meaning only that function will need to be made avail- able to the script. ■Note The require_once() function and its siblings are introduced in Chapter 10. Summary This chapter introduced object-oriented programming fundamentals, followed by an overview of PHP’s basic object-oriented features, devoting special attention to those enhancements and additions that are new to PHP 5. The next chapter expands upon this introductory information, covering topics such as inheritance, interfaces, abstract classes, and more. Gilmore_5475.book Page 156 Friday, November 11, 2005 1:16 PM 157 ■ ■ ■ CHAPTER 7 Advanced OOP Features Chapter 6 introduced the fundamentals of object-oriented PHP programming. This chapter builds on that foundation by introducing several of the more advanced OOP features that you should consider once you have mastered the basics. Specifically, this chapter introduces the following five features: • Object cloning: One of the major improvements to PHP’s OOP model in version 5 is the treatment of all objects as references rather than values. However, how do you go about creating a copy of an object if all objects are treated as references? By cloning the object, a feature that is new in PHP 5. • Inheritance: As mentioned in Chapter 6, the ability to build class hierarchies through inheritance is a key concept of OOP. This chapter introduces PHP 5’s inheritance features and syntax, and includes several examples that demonstrate this key OOP feature. • Interfaces: An interface is a collection of unimplemented method definitions and constants that serves as a class blueprint of sorts. Interfaces define exactly what can be done with the class, without getting bogged down in implementation-specific details. This chapter introduces PHP 5’s interface support and offers several examples demonstrating this powerful OOP feature. • Abstract classes: An abstract class is essentially a class that cannot be instantiated. Abstract classes are intended to be inherited by a class that can be instantiated, better known as a concrete class. Abstract classes can be fully implemented, partially imple- mented, or not implemented at all. This chapter presents general concepts surrounding abstract classes, coupled with an introduction to PHP 5’s class abstraction capabilities. • Reflection: As you learned in Chapter 6, hiding the application’s gruesome details behind a friendly interface (encapsulation) is one of the main OOP tenants. However, programmers nonetheless require a convenient means for investigating a class’s behavior. A concept known as reflection provides that capability, as described in this chapter. Advanced OOP Features Not Supported by PHP If you have experience in other object-oriented languages, you might be scratching your head over why the previous list of features doesn’t include one or more particular OOP features that you are familiar with from other languages. The reason might well be that PHP doesn’t support Gilmore_5475.book Page 157 Friday, November 11, 2005 1:16 PM [...]... this chapter, you learn how to log messages to both your operating system syslog and a custom log file • Exception handling: This long-awaited feature, prevalent among many popular languages (Java, C#, and Python, to name a few) and new to PHP 5, offers a standardized process for detecting, responding to, and reporting errors Historically, the development community has been notoriously lax in implementing... appropriate constructor If PHP had located a constructor in the Employee class, then it would have fired If you want both the Employee and Executive constructors to fire, then you need to place a call to parent:: construct() in the Executive constructor You also have the option to reference parent constructors in another fashion For example, suppose that both the Employee and Executive constructors should... pages If you’re new to OOP, the material should help you to better understand many of the key OOP concepts and inspire you to perform additional experimentation and research The next chapter introduces yet another new, and certainly long-awaited, feature of PHP 5: exception handling Gilmore_5475.book Page 177 Friday, November 11, 2005 1:16 PM CHAPTER 8 ■■■ Error and Exception Handling E ven if you... support will be integrated into a future version • Method overloading: The ability to implement polymorphism through functional overloading is not supported by PHP and, according to a discussion on the Zend Web site, probably never will be Learn more about why at http://www.zend.com /php/ ask_experts .php • Operator overloading: The ability to assign additional meanings to operators based upon the type of... 10:56 :37 example.com httpd: PHP Warning: fopen(/home/www/htdocs/subscribers.txt): failed to open stream: Permission denied in /home/www/htdocs/book /8/ displayerrors .php on line 3 When you write to a separate text file, the error messages look like this: [05-Dec-2005 10: 53: 47] PHP Warning: fopen(/home/www/htdocs/subscribers.txt): failed to open stream: Permission denied in /home/www/htdocs/book /8/ displayerrors .php. .. able to encounter and react to such unexpected errors in a graceful fashion, hopefully doing so without a loss of data or the crash of a program or system In addition, your application should be able to provide users with the feedback necessary to understand the reason for such errors and potentially adjust their behavior accordingly This chapter introduces several features PHP has to offer for handling... http://www.pear .php. net/package/PHPDoc) • PHPUnit2: A testing framework for performing unit tests (see http://www.pear .php. net/ package/PHPUnit2) Consider examining the contents of these packages to learn about the powerful ways in which they harness reflection to carry out useful tasks Summary This and the previous chapter introduced you to the entire gamut of PHP s OOP features, both old and new Although the PHP development... enabled during testing, and disabled when the site is live log_errors (On | Off) Scope: PHP_ INI_ALL; Default value: Off 179 Gilmore_5475.book Page 180 Friday, November 11, 2005 1:16 PM 180 CHAPTER 8 ■ ERROR AND EXCEPTION HANDLING Errors should be logged in every instance, because such records provide the most valuable means for determining problems specific to your application and the PHP engine Therefore,... adequate permissions to write to this file In addition, be sure to place this file outside of Gilmore_5475.book Page 181 Friday, November 11, 2005 1:16 PM CHAPTER 8 ■ ERROR AND EXCEPTION HANDLING the document root to lessen the likelihood that an attacker could happen across it and potentially uncover some information that is useful for surreptitiously entering your server When you write to the syslog, the... Executive has inherited from Employee, objects of type CEO also have all the members and methods that are available to Executive 1 63 Gilmore_5475.book Page 164 Friday, November 11, 2005 1:16 PM 164 CHAPTER 7 ■ ADVANCED OOP FEATURES Inheritance and Constructors A common question pertinent to class inheritance has to do with the use of constructors Does a parent class constructor execute when a child . 1 48 CHAPTER 6 ■ OBJECT-ORIENTED PHP Constructors and Destructors Often, you’ll want to execute a number of tasks when creating and destroying objects. For example, you might want to immediately. methods, called constructors and destructors, that automate the object creation and destruction processes. Constructors You often want to initialize certain fields and even trigger the execution. visitors. You wouldn’t want the visitor count to reset to zero every time the class was instantiated, and therefore you would set the field to be of the static scope: < ?php class visitors