PHP:__compare ?

  在看《PHP之道》時有這麼一段代碼 php

<?php
$raw = '22. 11. 1968';
$start = \DateTime::createFromFormat('d. m. Y', $raw);
echo 'State date: ' . $start->format('m/d/Y') . "\n";

$end = clone $start;
$end->add(new \DateInterval('P1M6D'));

$diff = $end->diff($start);
echo "Difference: " . $diff->format('%m month, %d days (total: %a days)') . "\n";

if($start < $end) {
    echo "Start is before end!\n";
}

 `$start < $end` 引發了個人注意,印象中並無__compare之類的魔術方法,翻了下手冊確實沒找到,也沒相關實現,那爲何這裏能夠直接比較呢? git

由於這是built-in class,因此須要翻一下源碼。 github

已下的代碼都是 PHP 5.4.27 函數

 已`compare`爲關鍵字在 ext/date/php_date.c(DateTime在這實現)搜索,獲得這麼一個函數 ui

static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC)
{
	if (Z_TYPE_P(d1) == IS_OBJECT && Z_TYPE_P(d2) == IS_OBJECT &&
		instanceof_function(Z_OBJCE_P(d1), date_ce_date TSRMLS_CC) &&
		instanceof_function(Z_OBJCE_P(d2), date_ce_date TSRMLS_CC)) {
		php_date_obj *o1 = zend_object_store_get_object(d1 TSRMLS_CC);
		php_date_obj *o2 = zend_object_store_get_object(d2 TSRMLS_CC);

		if (!o1->time || !o2->time) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Trying to compare an incomplete DateTime object");
			return 1;
		}
		if (!o1->time->sse_uptodate) {
			timelib_update_ts(o1->time, o1->time->tz_info);
		}
		if (!o2->time->sse_uptodate) {
			timelib_update_ts(o2->time, o2->time->tz_info);
		}
		
		return (o1->time->sse == o2->time->sse) ? 0 : ((o1->time->sse < o2->time->sse) ? -1 : 1);
	}
	
	return 1;
}
能夠看出這就是__compare的實現部分,經過函數名繼續搜索,來到line:1950
static void date_register_classes(TSRMLS_D)
{
	zend_class_entry ce_date, ce_timezone, ce_interval, ce_period;

	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, NULL TSRMLS_CC);
	memcpy(&date_object_handlers_date, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
	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;
	.....
date_object_handlers_date 是一個 zend_object_handlers,結構是這樣的
struct _zend_object_handlers {
	/* general object functions */
	zend_object_add_ref_t					add_ref;
	zend_object_del_ref_t					del_ref;
	zend_object_clone_obj_t					clone_obj;
	/* individual object functions */
	zend_object_read_property_t				read_property;
	zend_object_write_property_t			write_property;
	zend_object_read_dimension_t			read_dimension;
	zend_object_write_dimension_t			write_dimension;
	zend_object_get_property_ptr_ptr_t		get_property_ptr_ptr;
	zend_object_get_t						get;
	zend_object_set_t						set;
	zend_object_has_property_t				has_property;
	zend_object_unset_property_t			unset_property;
	zend_object_has_dimension_t				has_dimension;
	zend_object_unset_dimension_t			unset_dimension;
	zend_object_get_properties_t			get_properties;
	zend_object_get_method_t				get_method;
	zend_object_call_method_t				call_method;
	zend_object_get_constructor_t			get_constructor;
	zend_object_get_class_entry_t			get_class_entry;
	zend_object_get_class_name_t			get_class_name;
	zend_object_compare_t					compare_objects;
	zend_object_cast_t						cast_object;
	zend_object_count_elements_t			count_elements;
	zend_object_get_debug_info_t			get_debug_info;
	zend_object_get_closure_t				get_closure;
	zend_object_get_gc_t					get_gc;
};
因此只有實現 zend_object_handlers.compare_objects才具有直接比較的功能,但這並無暴露給用戶層。


相關資料: spa

Objects comparison in PHP

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息