get_constructor

coder_study發表於2019-11-05

本文支援建立最簡單的物件

struct _zend_object {
    zend_refcounted_h gc;    //引用計數
    uint32_t          handle; // TODO: may be removed ???
    zend_class_entry *ce;  //所屬類
    const zend_object_handlers *handlers;  //物件操作處理函式
    HashTable        *properties;
    zval              properties_table[1];  //普通屬性值陣列
};
struct _zend_object_handlers {
    /* offset of real object header (usually zero) */
    int                                     offset;
    /* general object functions */
    zend_object_free_obj_t                  free_obj;
    zend_object_dtor_obj_t                  dtor_obj;
    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_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_do_operation_t              do_operation;
    zend_object_compare_zvals_t             compare;
};
typedef union _zend_function *(*zend_object_get_constructor_t)(zend_object *object);
ZEND_API zend_object_handlers std_object_handlers = {
    0,                                      /* offset */

    zend_object_std_dtor,                   /* free_obj */
    zend_objects_destroy_object,            /* dtor_obj */
    zend_objects_clone_obj,                 /* clone_obj */

    zend_std_read_property,                 /* read_property */
    zend_std_write_property,                /* write_property */
    zend_std_read_dimension,                /* read_dimension */
    zend_std_write_dimension,               /* write_dimension */
    zend_std_get_property_ptr_ptr,          /* get_property_ptr_ptr */
    NULL,                                   /* get */
    NULL,                                   /* set */
    zend_std_has_property,                  /* has_property */
    zend_std_unset_property,                /* unset_property */
    zend_std_has_dimension,                 /* has_dimension */
    zend_std_unset_dimension,               /* unset_dimension */
    zend_std_get_properties,                /* get_properties */
    zend_std_get_method,                    /* get_method */
    NULL,                                   /* call_method */
    zend_std_get_constructor,               /* get_constructor */
    zend_std_object_get_class_name,         /* get_class_name */
    zend_std_compare_objects,               /* compare_objects */
    zend_std_cast_object_tostring,          /* cast_object */
    NULL,                                   /* count_elements */
    zend_std_get_debug_info,                /* get_debug_info */
    zend_std_get_closure,                   /* get_closure */
    zend_std_get_gc,                        /* get_gc */
    NULL,                                   /* do_operation */
    NULL,                                   /* compare */
};
ZEND_API union _zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */
{
    zend_function *constructor = zobj->ce->constructor;
    zend_class_entry *scope;

    if (constructor) {
        if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) {
            //公共方法
            /* No further checks necessary */
        } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
            //私有方法
            /* Ensure that if we're calling a private function, we're allowed to do so.
             */
            if (EG(fake_scope)) {
                scope = EG(fake_scope);
            } else {
                scope = zend_get_executed_scope();
            }
            if (UNEXPECTED(constructor->common.scope != scope)) {
                if (scope) {
                    zend_throw_error(NULL, "Call to private %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(scope->name));
                    constructor = NULL;
                } else {
                    zend_throw_error(NULL, "Call to private %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name));
                    constructor = NULL;
                }
            }
        } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
            /* Ensure that if we're calling a protected function, we're allowed to do so.
             * Constructors only have prototype if they are defined by an interface but
             * it is the compilers responsibility to take care of the prototype.
             */
            if (EG(fake_scope)) {
                scope = EG(fake_scope);
            } else {
                scope = zend_get_executed_scope();
            }
            if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), scope))) {
                if (scope) {
                    zend_throw_error(NULL, "Call to protected %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(scope->name));
                    constructor = NULL;
                } else {
                    zend_throw_error(NULL, "Call to protected %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name));
                    constructor = NULL;
                }
            }
        }
    }

    return constructor;
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結