Methods

If you did read the last chapter, you're probably starting to think, "It all looks pretty much the same so far", and so far, you're right. Now that it's time to declare some object methods. However, you'll start to see some very definite, and much welcome, differences.

PHP_METHOD(Sample3_SecondClass, helloWorld) { php_printf("Hello World "); }

The PHP_METHOD() macro, introduced with version 2 of the Zend Engine, wraps itself around the PHP_FUNCTION() macro to combine the classname with the method name just as you did manually for PHP4 method declarations. By using this macro, namespacing conventions are kept consistent between extensions and your code becomes easier to parse by other maintainers.

Declaration

Defining a method implementation, like any other function, is only useful if it's linked into userspace by way of the class entry's function table. As with the PHP_METHOD() macro used for implementation, there are also new macros for declaration within the function list:

So far, all the method declarations you've seen have used ZEND_ACC_PUBLIC for their flags parameter. In practice, this value can be made up of any (or none) of the type flags listed in Table 11.1 Bitwise OR'd with exactly one of the visibility flags listed in Table 11.2, and optionally OR'd with one of the special method flags you'll encounter in the "Special Methods" section later in this chapter.

Table 11.1. Method Type Flags

Type Flag

Meaning

ZEND_ACC_STATIC

Method will be called statically. In practice, this simply means that even if the method is called via an instance, $thisor more accurately: this_ptrwill not be populated with the instance's scope.

ZEND_ACC_ABSTRACT

Method is not a true implementation. The current method should be overridden by a child class before being called directly.

ZEND_ACC_FINAL

Method cannot be overridden by child classes.

Table 11.2. Method Visibility Flags

Visibility Flag

Meaning

ZEND_ACC_PUBLIC

Callable from any scope or even outside of an object. This is the same visibility shared by all PHP4 methods.

ZEND_ACC_PROTECTED

Only callable from the class it was defined in, or one of its children or ancestors.

ZEND_ACC_PRIVATE

Only callable from the exact class it was defined by.

For example, because the Sample3_SecondClass::helloWorld() method you defined earlier has no need for an object instance, you could change its declaration from a simple ZEND_ACC_PUBLIC to ZEND_ACC_PUBLIC|ZEND_ACC_STATIC so the engine knows not to bother.

Special Methods

In addition to the ZE1 set of magic methods, ZE2 adds a large family of magic methods listed in Table 11.3 and found in the PHP online manual at http://www.php.net/language.oop5.magic.

Table 11.3. Zend Engine 2 Magic Methods

Method

Usage

__construct(...)

An alternative to the automatically called object constructor (previously defined as the method who's name matches the classname). If method implementation exist for both __construct() and classname(), __construct() will receive priority and be called during instantiation.

__destruct()

When the instance falls completely out of scopeor the request as a whole shuts downall instances implicit call their __destruct() methods to handle any last minute cleanup such as shutting down file and network handles.

__clone()

By default, all instances are passed around in truereference sets. As of PHP5, however, an instance can be explicitly copied using the clone keyword. When clone is called on an object instance, the __clone() method is implicitly called to allow an object to duplicate any internal resources as needed.

__toString()

When expressing an instance as a textual object, such as when using the echo or print statements, the __toString() method is automatically called by the engine. Classes implementing this magic method should return a string containing a representation of the object's current state.

__get($var)

If a script requests a property from an object instance that either does not exist in the standard properties table or is declared as non-public, the __get() magic method is called with the name of the property passed as the only parameter. Implementations may use their own internal logic to determine the most sensible return value to provide.

__set($var, $value)

Like__get(), __set() provides the opportunity to handle variable assignment when the variable being assigned is not in the standard properties table or is declared non-public. __set() implementations may choose to implicitly create these variables within the standard properties table, set the values within other storage mechanisms, or simply throw an error and discard the value.

__call($fname, $args)

Calling an undefined method on an object may be handled gracefully through the use of a __call() magic method implementation. This method receives two arguments: The method name being called, and a numerically indexed array containing the arguments passed to that method.

__isset($varname)

As of PHP 5.1.0, the calls to isset($obj->prop) will not only check for the prop property within $obj, they will also call into any defined __isset() method within $obj to dynamically evaluate if attempts to read or write the property would succeed given the dynamic __get() and __set() methods.

__unset($varname)

Like __isset(), PHP 5.1.0 introduced a simple OOP interface to the unset() function for properties that, although they might not exist within an objects standard properties table, might have meaning within the __get() and __set() dynamic property space.

Note

Extra magic method functionality is available through certain interfaces such as the ArrayAccess interface as well as several SPL interfaces.

Within an internal object implementation, each of these special "magic methods" can be implemented as any other method within your object by defining a PHP_ME() line with the right name and a PUBLIC access modifier. For __get(), __set(), __call(), __isset(), and __unset(), which require a precise number of arguments to be passed, you must define an appropriate arg_info struct that states that the method takes exactly 1 or 2 arguments. The following code snippets show arg_info structs and their corresponding PHP_ME() entries for each of the magic methods:

static ZEND_BEGIN_ARG_INFO_EX(php_sample3_one_arg, 0, 0, 1) ZEND_END_ARG_INFO() static ZEND_BEGIN_ARG_INFO_EX(php_sample3_two_args, 0, 0, 2) ZEND_END_ARG_INFO() static function_entry php_sample3_sc_functions[] = { PHP_ME(Sample3_SecondClass, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Sample3_SecondClass, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_ME(Sample3_SecondClass, __clone, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CLONE) PHP_ME(Sample3_SecondClass, __toString, NULL, ZEND_ACC_PUBLIC) PHP_ME(Sample3_SecondClass, __get, php_sample3_one_arg, ZEND_ACC_PUBLIC) PHP_ME(Sample3_SecondClass, __set, php_sample3_two_args, ZEND_ACC_PUBLIC) PHP_ME(Sample3_SecondClass, __call, php_sample3_two_args, ZEND_ACC_PUBLIC) PHP_ME(Sample3_SecondClass, __isset, php_sample3_one_arg, ZEND_ACC_PUBLIC) PHP_ME(Sample3_SecondClass, __unset, php_sample3_one_arg, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } };

Notice that __construct, __destruct, and __clone were OR'd with additional constants. These three access modifiers are specific to the methods they're named for and should never be used anywhere else.

Категории