编写过 php 扩展的同学都知道,PHP 扩展的函数定义在 PHP_FUNCTION 宏方法之下,我们查找一下 PHP_FUNCTION(mysqli_options),可以在 ext/mysqli/mysqli_api.c 中找到相应的代码:
/* {{{ proto bool mysqli_options(object link, int flags, mixed values)
Set options */
PHP_FUNCTION(mysqli_options)
{
MY_MYSQL*mysql;
zval*mysql_link = NULL;
zval**mysql_value;
longmysql_option;
unsigned intl_value;
longret;
intexpected_type;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OlZ", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_INITIALIZED);
#if PHP_API_VERSION < 20100412
if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) {
#else
if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
#endif
if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
RETURN_FALSE;
}
}
expected_type = mysqli_options_get_option_zval_type(mysql_option);
if (expected_type != Z_TYPE_PP(mysql_value)) {
switch (expected_type) {
case IS_STRING:
convert_to_string_ex(mysql_value);
break;
case IS_LONG:
convert_to_long_ex(mysql_value);
break;
default:
break;
}
}
switch (expected_type) {
case IS_STRING:
ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_PP(mysql_value));
break;
case IS_LONG:
l_value = Z_LVAL_PP(mysql_value);
ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
break;
default:
ret = 1;
break;
}
RETURN_BOOL(!ret);
}
/* }}} */
这个函数主要是对 mysql_options 的一个封装
主要的流程是:调用 mysqli_options_get_option_zval_type 参数,根据传入的 mysql_option 判断 mysql_options 的第三个参数的类型,然后对传入的 mysql_value 进行相应的转化并调用 mysql_options
那么,我们看下 mysqli_options_get_option_zval_type 的实现:
/* {{{ mysqli_options_get_option_zval_type */
static int mysqli_options_get_option_zval_type(int option)
{
switch (option) {
#ifdef MYSQLI_USE_MYSQLND
#if PHP_MAJOR_VERSION >= 6
case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
#endif
case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
#endif
#endif /* MYSQLI_USE_MYSQLND */
case MYSQL_OPT_CONNECT_TIMEOUT:
#ifdef MYSQL_REPORT_DATA_TRUNCATION
case MYSQL_REPORT_DATA_TRUNCATION:
#endif
case MYSQL_OPT_LOCAL_INFILE:
case MYSQL_OPT_NAMED_PIPE:
#ifdef MYSQL_OPT_PROTOCOL
case MYSQL_OPT_PROTOCOL:
#endif /* MySQL 4.1.0 */
#ifdef MYSQL_OPT_READ_TIMEOUT
case MYSQL_OPT_READ_TIMEOUT:
case MYSQL_OPT_WRITE_TIMEOUT:
case MYSQL_OPT_GUESS_CONNECTION:
case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
case MYSQL_OPT_USE_REMOTE_CONNECTION:
case MYSQL_SECURE_AUTH:
#endif /* MySQL 4.1.1 */
#ifdef MYSQL_OPT_RECONNECT
case MYSQL_OPT_RECONNECT:
#endif /* MySQL 5.0.13 */
#ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
#endif /* MySQL 5.0.23 */
#ifdef MYSQL_OPT_COMPRESS
case MYSQL_OPT_COMPRESS:
#endif /* mysqlnd @ PHP 5.3.2 */
#ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
#endif /* MySQL 5.1.1., mysqlnd @ PHP 5.3.3 */
#if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
#endif
return IS_LONG;
#ifdef MYSQL_SHARED_MEMORY_BASE_NAME
case MYSQL_SHARED_MEMORY_BASE_NAME:
#endif /* MySQL 4.1.0 */
#ifdef MYSQL_SET_CLIENT_IP
case MYSQL_SET_CLIENT_IP:
#endif /* MySQL 4.1.1 */
case MYSQL_READ_DEFAULT_FILE:
case MYSQL_READ_DEFAULT_GROUP:
case MYSQL_INIT_COMMAND:
case MYSQL_SET_CHARSET_NAME:
case MYSQL_SET_CHARSET_DIR:
#if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
case MYSQL_SERVER_PUBLIC_KEY:
#endif
return IS_STRING;
default:
return IS_NULL;
}
}
/* }}} */
这里是有 MYSQL_OPT_READ_TIMEOUT 和 MYSQL_OPT_WRITE_TIMEOUT 的,从注释中我们发现是从 PHP 4.1.1 开始提供的,但是并没有对外提供接口,所以我们需要做的,仅仅是将他导出即可