¿Por qué mysqli_fetch_fields() me da resultados inexactos?

La length el resultado de mysqli_fetch_fields() me está dando resultados inexactos.

mysql > DESCRIBE Notices;

Field     Type               Null     Key     Default     Extra
Id        int(10) unsigned   NO       PRI     (NULL)      auto_increment
UserId    int(10) unsigned   NO       MUL     (NULL)
Title     char(255)          NO               (NULL)
Name      char(255)          NO               (NULL)
Summary   text               NO               (NULL)

Sin embargo,

class Db {
    public function exec($sql) {
        if (!$this->link) {
            $this->open();
        }
        if (($this->result = mysqli_query($this->link, $sql)) === false) {
            throw new Exception('<b>' . __METHOD__ . '</b>: ' . $sql . ': ' . mysqli_error($this->link));
        }
        return true;
    }
    public function field_info($table) {
        $sql = 'SELECT * FROM `' . $table . '` LIMIT 1';
        $this->exec($sql);
        return $this->field_info = $this->result->fetch_fields();
    }
}

$a  = $db->field_info('Notices');
print_r($a);

Produce la siguiente salida:

// Note: "max_length" is the maximum existing length in the result set,
// while "length" is the set maximum length in the table definition.

Array
(
    [0] => stdClass Object
        (
            [name] => Id
            [orgname] => Id
            [table] => Notices
            [orgtable] => Notices
            [def] =>
            [max_length] => 1
            [length] => 10
            [charsetnr] => 63
            [flags] => 49699
            [type] => 3
            [decimals] => 0
        )

    [1] => stdClass Object
        (
            [name] => UserId
            [orgname] => UserId
            [table] => Notices
            [orgtable] => Notices
            [def] =>
            [max_length] => 1
            [length] => 10
            [charsetnr] => 63
            [flags] => 53289
            [type] => 3
            [decimals] => 0
        )

    [2] => stdClass Object
        (
            [name] => Title
            [orgname] => Title
            [table] => Notices
            [orgtable] => Notices
            [def] =>
            [max_length] => 27
            [length] => 765
            [charsetnr] => 33
            [flags] => 4097
            [type] => 254
            [decimals] => 0
        )

    [3] => stdClass Object
        (
            [name] => Name
            [orgname] => Name
            [table] => Notices
            [orgtable] => Notices
            [def] =>
            [max_length] => 25
            [length] => 765
            [charsetnr] => 33
            [flags] => 4097
            [type] => 254
            [decimals] => 0
        )

    [4] => stdClass Object
        (
            [name] => Summary
            [orgname] => Summary
            [table] => Notices
            [orgtable] => Notices
            [def] =>
            [max_length] => 26
            [length] => 196605
            [charsetnr] => 33
            [flags] => 4113
            [type] => 252
            [decimals] => 0
        )
)

Si observa, verá que las longitudes informadas de los CHAR Los campos no coinciden. DESCRIBE me esta dando 255, mientras fetch_fields() me esta dando 765. ¿Por qué?

(La idea, en caso de que te lo estés preguntando, es producir un maxlength atributo para <input> etiquetas.)

preguntado el 03 de mayo de 12 a las 12:05

4 Respuestas

La longitud de tu campo es 255 personajes, pero la longitud reportada está en bytes.

Dado que MySQL está usando 3 bytes por carácter para colaciones UTF-8, obtienes 255*3 = 765 como su resultado.

Respondido el 08 de diciembre de 14 a las 13:12

¿Dónde dice que la longitud está en bytes? El documentación para mysqli_fetch_fields solo dice "El ancho del campo, como se especifica en la definición de la tabla". Además, solo obtiene el resultado incorrecto en Windows. Cuando ejecuta el mismo script en Linux, obtiene el resultado esperado, es decir 255. - Sebastián Zartner

@SebastianZartner. No. Estaba viendo problemas donde tanto PHP como MySQL se ejecutaban en Linux. (Con ambos en Ubuntu; y nuevamente con ambos en CentOS). - Trigonometría

Correcto, el comentario de arriba fue mi percepción de ayer. Aunque, como puede ver en mi respuesta a continuación, en realidad no está relacionado con el sistema operativo, sino que se define a través del conjunto de caracteres predeterminado del cliente. - Sebastián Zartner

La length así como la charsetnr valores en el mysqli_result::fetch_fields() / mysqli_fetch_fields() la salida obviamente depende del conjunto de caracteres predeterminado definido por el cliente.

Por ejemplo, un charsetnr of 33 significa UTF-8. Para ser precisos, en realidad representa la intercalación 'utf8_general_ci' del conjunto de caracteres 'utf8'. Esa información se puede recuperar ejecutando esta consulta:

SELECT * FROM information_schema.collations;

Se puede recuperar una lista de conjuntos de caracteres disponibles y su longitud de caracteres a través de esta consulta:

SELECT * FROM information_schema.character_sets;

El conjunto de caracteres del cliente predeterminado se puede cambiar mediante una llamada de PHP mysqli::set_charset() / mysqli_set_charset().

Ejemplo:

$dbHandle->set_charset('latin1');

La documentación de PHP para mysqli_fetch_fields() actualmente no incluye esa información, así que solicité agregarla en error 68573.

El conjunto de caracteres predeterminado también se puede definido dentro de la configuración del servidor as descrito en otro hilo.

Como este comportamiento de fetch_fields() es bastante confuso, solicité cambiarlo en error 68574.

contestado el 23 de mayo de 17 a las 13:05

Divido el resultado:

$result = mysqli_query($con,"SELECT * from tabla");
$campoTD = mysqli_fetch_fields($result);
  foreach ($campoTD as $campo){
    echo '<input maxlength='.number_format($campo[$i]->length / 3).' >';
    $i++;
  }

respondido 26 nov., 14:18

Tuve el mismo problema y descubrí que necesitas usar: $val->length;

no max_length, max_length es la longitud máxima de los valores en esa columna en particular, no la definición de la tabla.

Si desea la definición de la tabla, use 'longitud'.

$q = $mysqli->query("select * from table");

$finfo = $q->fetch_fields();

foreach ($finfo as $val) {

    echo $val->length;

}

árbitro: http://php.undmedlibrary.org/manual/de/function.mysqli-fetch-fields.php

Respondido 16 Abr '13, 23:04

Si. Vea el comentario en el código en mi pregunta, que ya indica ese punto. - Trigonometría

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.