在看《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