1. 程式人生 > >php原始碼之DateTime類

php原始碼之DateTime類

1.宣告在php_date.h

/* Advanced Interface */
PHP_METHOD(DateTime, __construct);
PHP_METHOD(DateTime, __wakeup);
PHP_METHOD(DateTime, __set_state);
PHP_METHOD(DateTime, createFromImmutable);
/*其他方法,以對映的方式,複用該擴充套件中定義的其他函式上去*/

2.php_date.c中

方法引數定義略

方法陣列定義如下

static const zend_function_entry date_funcs_date[] = {
	PHP_ME(DateTime,			__construct,		arginfo_date_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
	PHP_ME(DateTime,			__wakeup,			NULL, ZEND_ACC_PUBLIC)
	PHP_ME(DateTime,			__set_state,		arginfo_date_set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
	PHP_ME(DateTime,			createFromImmutable,	arginfo_date_method_create_from_immutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
	PHP_ME_MAPPING(createFromFormat, date_create_from_format,	arginfo_date_create_from_format, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
	PHP_ME_MAPPING(getLastErrors, date_get_last_errors,	arginfo_date_get_last_errors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
	PHP_ME_MAPPING(format,		date_format,		arginfo_date_method_format, 0)
	PHP_ME_MAPPING(modify,		date_modify,		arginfo_date_method_modify, 0)
	PHP_ME_MAPPING(add,			date_add,			arginfo_date_method_add, 0)
	PHP_ME_MAPPING(sub,			date_sub,			arginfo_date_method_sub, 0)
	PHP_ME_MAPPING(getTimezone, date_timezone_get,	arginfo_date_method_timezone_get, 0)
	PHP_ME_MAPPING(setTimezone, date_timezone_set,	arginfo_date_method_timezone_set, 0)
	PHP_ME_MAPPING(getOffset,	date_offset_get,	arginfo_date_method_offset_get, 0)
	PHP_ME_MAPPING(setTime,		date_time_set,		arginfo_date_method_time_set, 0)
	PHP_ME_MAPPING(setDate,		date_date_set,		arginfo_date_method_date_set, 0)
	PHP_ME_MAPPING(setISODate,	date_isodate_set,	arginfo_date_method_isodate_set, 0)
	PHP_ME_MAPPING(setTimestamp,	date_timestamp_set, arginfo_date_method_timestamp_set, 0)
	PHP_ME_MAPPING(getTimestamp,	date_timestamp_get, arginfo_date_method_timestamp_get, 0)
	PHP_ME_MAPPING(diff,			date_diff, arginfo_date_method_diff, 0)
	PHP_FE_END
};

其中,PHP_ME_MAPPING作用是把第一個引數名作為方法名,對映到已經定義的函式上去,舉個例子

PHP_ME_MAPPING(format,		date_format,		arginfo_date_method_format, 0)

//展開為   注意,zif_date_format是函式指標

{    "format", 
     zif_date_format,
     { 
        { 1, 0, 0, 0 },
        { "format", 0,0, 0},
     },
     1, 
     0
}

正常類的內部方法展開,舉個例子

PHP_ME(DateTime,			__construct,		arginfo_date_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
//展開為
{    "__construct", 
     zim_DateTime___construct, 
     { 
        { 0, 0, 0, 0 },  //第一個為必要引數數目,為0個
        { "time", 0,0, 0},
        { "timezone", 0,0, 0},
     },
     2,//引數數量最大值
     ZEND_ACC_CTOR|ZEND_ACC_PUBLIC   //函式許可權標誌
}

方法的定義:

對映方式的方法定義,同普通函式的定義。

類自己的方法的定義如下:

/* {{{ proto DateTime::__construct([string time[, DateTimeZone object]])
   Creates new DateTime object
*/
PHP_METHOD(DateTime, __construct)
{
	zval *timezone_object = NULL;
	char *time_str = NULL;
	size_t time_str_len = 0;
	zend_error_handling error_handling;

	ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 2)
		Z_PARAM_OPTIONAL
		Z_PARAM_STRING(time_str, time_str_len)
		Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
	ZEND_PARSE_PARAMETERS_END();

	zend_replace_error_handling(EH_THROW, NULL, &error_handling);
	php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1);
	zend_restore_error_handling(&error_handling);
}
/* }}} */

//展開即為

void zim_DateTime___construct(zend_execute_data *execute_data, zval *return_value)
{

    zval *timezone_object = NULL;
	char *time_str = NULL;
	size_t time_str_len = 0;
	zend_error_handling error_handling;

	ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 2)
		Z_PARAM_OPTIONAL
		Z_PARAM_STRING(time_str, time_str_len)
		Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
	ZEND_PARSE_PARAMETERS_END();

	zend_replace_error_handling(EH_THROW, NULL, &error_handling);
	php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1);
	zend_restore_error_handling(&error_handling);

}

3.在模組初始化時註冊自定義的類

static void date_register_classes(void);//宣告

/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(date)
{
	REGISTER_INI_ENTRIES();
	date_register_classes();//呼叫


static void date_register_classes(void) /* {{{ */    //定義
{

    //......忽略.....  以下就是註冊DateTime類的區域
	INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
	ce_date.create_object = date_object_new_date;
	date_ce_date = zend_register_internal_class_ex(&ce_date, NULL);
	memcpy(&date_object_handlers_date, &std_object_handlers, sizeof(zend_object_handlers));
	date_object_handlers_date.offset = XtOffsetOf(php_date_obj, std);
	date_object_handlers_date.free_obj = date_object_free_storage_date;
	date_object_handlers_date.clone_obj = date_object_clone_date;
	date_object_handlers_date.compare_objects = date_object_compare_date;
	date_object_handlers_date.get_properties = date_object_get_properties;
	date_object_handlers_date.get_gc = date_object_get_gc;
	zend_class_implements(date_ce_date, 1, date_ce_interface);