“set names” vs mysqli_set_charset — besides affecting mysqli_escape_string, are they identical?

前端 未结 4 555
遥遥无期
遥遥无期 2021-01-04 09:53

It seems to be common knowledge to use mysql_set_charset / mysqli::set_charset instead of the direct MySQL query set names.

The reason often cited is that se

4条回答
  •  借酒劲吻你
    2021-01-04 10:24

    Calling SET NAMES on the connection is equivalent to calling set_charset, provided you call neither get_charset nor mysql_real_escape_string (and friends).


    When you call set_charset, PHP does two things. First, it calls SET NAMES on the connection. Second, it remembers what charset you set. That state information is later used only in the get_charset and mysql_real_escape_string (and friends) functions. Therefore, if you don't use these functions, then you may consider the two equivalent.

    Let's walk the source:

    1. Userland functions mysql_set_charset and mysqli_set_charset call...
    2. Engine function mysql_set_character_set calls...
    3. Engine macro mysqlnd_set_character_set, which is defined as:

      #define mysqlnd_set_character_set(conn, cs) \ ((conn)->data)->m->set_charset((conn)->data, (cs)))

      and expands to...

    4. MYSQLND_METHOD(mysqlnd_conn_data, set_charset) which contains the following code (numbered for discussion, these are not actual source line numbers):

     1   if (PASS == conn->m->local_tx_start(conn, this_func)) {
     2      char * query;
     3      size_t query_len = mnd_sprintf(&query, 0, "SET NAMES %s", csname);
     4 
     5      if (FAIL == (ret = conn->m->query(conn, query, query_len))) {
     6          php_error_docref(NULL, E_WARNING, "Error executing query");
     7      } else if (conn->error_info->error_no) {
     8          ret = FAIL;
     9      } else {
    10           conn->charset = charset;
    11      }
    12      mnd_sprintf_free(query);
    13 
    14      conn->m->local_tx_end(conn, this_func, ret);
    15   }
    

    As you can see, PHP calls SET NAMES on the connection itself (line 3). PHP also tracks the charset just set (line 10). The comments further discuss what happens with conn->charset, but suffice to say it winds up only being in get_charset and mysql_real_escape_string (and friends).

    So, if you don't care about this state, and you agree to use neither get_charset nor mysql_real_escape_string, then you may call SET NAMES on the connection itself with no ill effect.

    As an aside, and I've never done this, but it looks like compiling PHP with -DPHP_DEBUG=1 will enable substantial debugging through various DBG macros. That may be useful in seeing how your code is passing through this block.

提交回复
热议问题