在看《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之类的魔术方法,翻了下手册确实没找到,也没相关实现,那为什么这里可以直接比较呢?
因为这是built-in class,所以需要翻一下源码。
已下的代码都是 PHP 5.4.27
已`compare`为关键字在 ext/date/php_date.c(DateTime在这实现)搜索,得到这么一个函数
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_tadd_ref;
zend_object_del_ref_tdel_ref;
zend_object_clone_obj_tclone_obj;
/* individual object functions */
zend_object_read_property_tread_property;
zend_object_write_property_twrite_property;
zend_object_read_dimension_tread_dimension;
zend_object_write_dimension_twrite_dimension;
zend_object_get_property_ptr_ptr_tget_property_ptr_ptr;
zend_object_get_tget;
zend_object_set_tset;
zend_object_has_property_thas_property;
zend_object_unset_property_tunset_property;
zend_object_has_dimension_thas_dimension;
zend_object_unset_dimension_tunset_dimension;
zend_object_get_properties_tget_properties;
zend_object_get_method_tget_method;
zend_object_call_method_tcall_method;
zend_object_get_constructor_tget_constructor;
zend_object_get_class_entry_tget_class_entry;
zend_object_get_class_name_tget_class_name;
zend_object_compare_tcompare_objects;
zend_object_cast_tcast_object;
zend_object_count_elements_tcount_elements;
zend_object_get_debug_info_tget_debug_info;
zend_object_get_closure_tget_closure;
zend_object_get_gc_tget_gc;
}; 所以只有实现
zend_object_handlers.compare_objects才具备直接比较的功能,但这并没有暴露给用户层。
相关资料: