/** * Resolves the service * * @param array $parameters * @param Phalcon\DiInterface $dependencyInjector * @return mixed */ PHP_METHOD(Phalcon_DI_Service, resolve){ zval *parameters = NULL, *dependency_injector = NULL, *shared; zval *shared_instance, *found = NULL, *instance = NULL, *definition; zval *builder, *name, *exception_message; PHALCON_MM_GROW(); phalcon_fetch_params(1, 0, 2, ¶meters, &dependency_injector); if (!parameters) { PHALCON_INIT_VAR(parameters); } if (!dependency_injector) { PHALCON_INIT_VAR(dependency_injector); } PHALCON_OBS_VAR(shared); phalcon_read_property_this(&shared, this_ptr, SL("_shared"), PH_NOISY_CC); /** * Check if the service is shared */ if (zend_is_true(shared)) { PHALCON_OBS_VAR(shared_instance); phalcon_read_property_this(&shared_instance, this_ptr, SL("_sharedInstance"), PH_NOISY_CC); if (Z_TYPE_P(shared_instance) != IS_NULL) { RETURN_CCTOR(shared_instance); } } PHALCON_INIT_VAR(found); ZVAL_BOOL(found, 1); PHALCON_INIT_VAR(instance); PHALCON_OBS_VAR(definition); phalcon_read_property_this(&definition, this_ptr, SL("_definition"), PH_NOISY_CC); if (Z_TYPE_P(definition) == IS_STRING) { /** * String definitions can be class names without implicit parameters */ if (phalcon_class_exists(definition, 1 TSRMLS_CC)) { if (Z_TYPE_P(parameters) == IS_ARRAY) { if (phalcon_fast_count_ev(parameters TSRMLS_CC)) { if (phalcon_create_instance_params(instance, definition, parameters TSRMLS_CC) == FAILURE) { return; } } else { PHALCON_INIT_NVAR(instance); if (phalcon_create_instance(instance, definition TSRMLS_CC) == FAILURE) { return; } } } else { PHALCON_INIT_NVAR(instance); if (phalcon_create_instance(instance, definition TSRMLS_CC) == FAILURE) { return; } } } else { ZVAL_BOOL(found, 0); } } else { /** * Object definitions can be a Closure or an already resolved instance */ if (likely(Z_TYPE_P(definition) == IS_OBJECT)) { if (phalcon_is_instance_of(definition, SL("Closure") TSRMLS_CC)) { if (Z_TYPE_P(parameters) == IS_ARRAY) { PHALCON_INIT_NVAR(instance); PHALCON_CALL_USER_FUNC_ARRAY(instance, definition, parameters); } else { PHALCON_INIT_NVAR(instance); PHALCON_CALL_USER_FUNC(instance, definition); } } else { PHALCON_CPY_WRT(instance, definition); } } else { /** * Array definitions require a 'className' parameter */ if (Z_TYPE_P(definition) == IS_ARRAY) { PHALCON_INIT_VAR(builder); object_init_ex(builder, phalcon_di_service_builder_ce); PHALCON_INIT_NVAR(instance); phalcon_call_method_p3(instance, builder, "build", dependency_injector, definition, parameters); } else { PHALCON_INIT_NVAR(found); ZVAL_BOOL(found, 0); } } } /** * If the service can't be built, we must throw an exception */ if (PHALCON_IS_FALSE(found)) { PHALCON_OBS_VAR(name); phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC); PHALCON_INIT_VAR(exception_message); PHALCON_CONCAT_SVS(exception_message, "Service '", name, "' cannot be resolved"); PHALCON_THROW_EXCEPTION_ZVAL(phalcon_di_exception_ce, exception_message); return; } /** * Update the shared instance if the service is shared */ if (zend_is_true(shared)) { phalcon_update_property_this(this_ptr, SL("_sharedInstance"), instance TSRMLS_CC); } RETURN_CCTOR(instance); }
/** * Resolves the service based on its configuration * * @param string $name * @param array $parameters * @return mixed */ PHP_METHOD(Phalcon_DI, get){ zval *name, *parameters = NULL, *services, *service, *instance = NULL; zval *exception_message; PHALCON_MM_GROW(); phalcon_fetch_params(1, 1, 1, &name, ¶meters); if (!parameters) { PHALCON_INIT_VAR(parameters); } /** * A valid service alias is a string */ if (Z_TYPE_P(name) != IS_STRING) { PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service alias must be a string"); return; } PHALCON_OBS_VAR(services); phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); if (phalcon_array_isset(services, name)) { /** * The service is registered in the DI */ PHALCON_OBS_VAR(service); phalcon_array_fetch(&service, services, name, PH_NOISY); PHALCON_INIT_VAR(instance); phalcon_call_method_p2(instance, service, "resolve", parameters, this_ptr); } else { /** * The DI also acts as builder for any class even if it isn't defined in the DI */ if (phalcon_class_exists(name, 1 TSRMLS_CC)) { if (Z_TYPE_P(parameters) == IS_ARRAY) { if (phalcon_fast_count_ev(parameters TSRMLS_CC)) { PHALCON_INIT_NVAR(instance); if (phalcon_create_instance_params(instance, name, parameters TSRMLS_CC) == FAILURE) { return; } } else { PHALCON_INIT_NVAR(instance); if (phalcon_create_instance(instance, name TSRMLS_CC) == FAILURE) { return; } } } else { PHALCON_INIT_NVAR(instance); if (phalcon_create_instance(instance, name TSRMLS_CC) == FAILURE) { return; } } } else { PHALCON_INIT_VAR(exception_message); PHALCON_CONCAT_SVS(exception_message, "Service '", name, "' wasn't found in the dependency injection container"); PHALCON_THROW_EXCEPTION_ZVAL(phalcon_di_exception_ce, exception_message); return; } } /** * Pass the DI itself if the instance implements Phalcon\DI\InjectionAwareInterface */ if (Z_TYPE_P(instance) == IS_OBJECT) { if (phalcon_method_exists_ex(instance, SS("setdi") TSRMLS_CC) == SUCCESS) { phalcon_call_method_p1_noret(instance, "setdi", this_ptr); } } RETURN_CCTOR(instance); }
/** * Resolves the service * * @param array $parameters * @param Phalcon\DIInterface $dependencyInjector * @return object */ PHP_METHOD(Phalcon_DI_Service, resolve){ zval *parameters = NULL, *dependency_injector = NULL, name = {}, shared = {}, shared_instance = {}, definition = {}, builder = {}; int found = 0, ishared = 0; phalcon_fetch_params(0, 0, 2, ¶meters, &dependency_injector); if (!parameters) { parameters = &PHALCON_GLOBAL(z_null); } if (!dependency_injector) { dependency_injector = &PHALCON_GLOBAL(z_null); } phalcon_return_property(&shared, getThis(), SL("_shared")); phalcon_return_property(&shared_instance, getThis(), SL("_sharedInstance")); ishared = zend_is_true(&shared); /* Check if the service is shared */ if (ishared && Z_TYPE(shared_instance) != IS_NULL) { RETURN_CTORW(&shared_instance); } phalcon_return_property(&definition, getThis(), SL("_definition")); if (Z_TYPE(definition) == IS_STRING) { /* String definitions can be class names without implicit parameters */ if (phalcon_class_exists(&definition, 1) != NULL) { found = 1; if (Z_TYPE_P(parameters) == IS_ARRAY) { RETURN_ON_FAILURE(phalcon_create_instance_params(return_value, &definition, parameters)); } else { RETURN_ON_FAILURE(phalcon_create_instance(return_value, &definition)); } } } else if (likely(Z_TYPE(definition) == IS_OBJECT)) { /* Object definitions can be a Closure or an already resolved instance */ found = 1; if (instanceof_function_ex(Z_OBJCE(definition), zend_ce_closure, 0)) { if (likely(Z_TYPE_P(dependency_injector) == IS_OBJECT)) { PHALCON_CALL_CE_STATICW(&definition, zend_ce_closure, "bind", &definition, dependency_injector); } if (Z_TYPE_P(parameters) == IS_ARRAY) { PHALCON_CALL_USER_FUNC_ARRAYW(return_value, &definition, parameters); } else { PHALCON_CALL_USER_FUNCW(return_value, &definition); } } else { PHALCON_CPY_WRT(return_value, &definition); } } else if (Z_TYPE(definition) == IS_ARRAY) { found = 1; /* Array definitions require a 'className' parameter */ object_init_ex(&builder, phalcon_di_service_builder_ce); PHALCON_CALL_METHODW(return_value, &builder, "build", dependency_injector, &definition, parameters); } if (!EG(exception)) { if (found) { if (ishared) { phalcon_update_property_zval(getThis(), SL("_sharedInstance"), return_value); } /* Update the shared instance if the service is shared */ phalcon_update_property_bool(getThis(), SL("_resolved"), 1); } else { phalcon_return_property(&name, getThis(), SL("_name")); PHALCON_THROW_EXCEPTION_FORMATW(phalcon_di_exception_ce, "Service '%s' cannot be resolved", Z_STRVAL(name)); } } }