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:

  • PHP_ME(classname, methodname, arg_info, flags)

    PHP_ME() adds a classname portion to the PHP_FE() macro from Chapter 5, "Your First Extension," as well as a new parameter at the end that provides access control modifiers such as public, protected, private, static, abstract, and a few other options. To declare the helloWorld method you just defined, you might use an entry like:

    PHP_ME(Sample3_SecondClass,helloWorld,NULL,ZEND_ACC_PUBLIC)
  • PHP_MALIAS(classname, name, alias, arg_info, flags)

    Just like the PHP_FALIAS() macro, this declaration allows you to assign a new namegiven in the name parameterto an existing method implementation from the same class, specified by alias. For example, to give a duplicate name to your helloWorld method you might use:

    PHP_MALIAS(Sample3_SecondClass, sayHi, helloWorld,
     NULL, ZEND_ACC_PUBLIC)
  • PHP_ABSTRACT_ME(classname, methodname, arg_info)

    Abstract methods in internal classes are just like abstract userspace methods. They're used as placeholders for within ancestral classes that expect their descendants to provide true implementations according to a specific API. You will typically use this macro within Interfaces, which are a specialized form of class entry.

  • PHP_ME_MAPPING(methodname, functionname, arg_info)

    This last form of method declaration macro is aimed primarily at extensions that export a dual OOP/non-OOP interface such as the MySQLi extension where the mysqli_query() procedural function and MySQLi::query() method are both serviced by the same internal implementation. Assuming you already had a procedural function, such as the sample_hello_world() that you wrote in Chapter 5, you would use this declaration macro to alias it to a method in the following manner (note that mapped methods are always public, non-static, non-final):

    PHP_ME_MAPPING(hello, sample_hello_world, NULL)

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.


The PHP Life Cycle

Variables from the Inside Out

Memory Management

Setting Up a Build Environment

Your First Extension

Returning Values

Accepting Parameters

Working with Arrays and HashTables

The Resource Data Type

PHP4 Objects

PHP5 Objects

Startup, Shutdown, and a Few Points in Between

INI Settings

Accessing Streams

Implementing Streams

Diverting the Stream

Configuration and Linking

Extension Generators

Setting Up a Host Environment

Advanced Embedding

Appendix A. A Zend API Reference

Appendix B. PHPAPI

Appendix C. Extending and Embedding Cookbook

Appendix D. Additional Resources



Extending and Embedding PHP
Extending and Embedding PHP
ISBN: 067232704X
EAN: 2147483647
Year: 2007
Pages: 175
Authors: Sara Golemon

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net