web-dev-qa-db-fra.com

Faire correspondre les types de contenu de base de données à PHP les types

Les méthodes $wpdb query renvoient tous les résultats de la requête sous forme de chaînes. Par exemple, une colonne 'ID' renverrait une valeur de chaîne telle que '42' au lieu d'un entier 42.

Existe-t-il un moyen de configurer la classe de base de données WP pour que les types de contenu de la base de données correspondent à PHP types ? Ou dois-je continuer à le faire manuellement comme ci-dessous?

$results = $wpdb->get_results('SELECT * FROM my_table');

foreach ($results as $result)
{
    // All integer values
    foreach (array('id', 'user_id', 'comment_count') as $field)
    {
        $result->$field = (int) $result->$field;
    }
    // All float values
    foreach (array('price') as $field)
    {
        $result->$field = (float) $result->$field;
    }
    // All boolean values
    foreach (array('is_open', 'is_confirmed') as $field)
    {
        $result->$field = (bool) $result->$field;
    }
    // Etc.
}

Pourquoi déranger, vous pensez peut-être? Eh bien, pour commencer, il est amusant de travailler avec du code propre. Les valeurs entières ne doivent pas être stockées sous forme de chaînes. Lorsque vous créez une fonction personnalisée pour rechercher quelque chose, un produit, par exemple, j'aime pouvoir différencier le champ à rechercher en fonction du type de données de l'argument passé:

function load_product($id_or_slug)
{
    if (is_int($id_or_slug))
    {
        // Look up by ID
    }
    else
    {
        // Look up by slug
    }
}
6
Geert

Il n'y a aucun moyen de faire automatiquement cela avec wpdb. C’est vraiment une limitation de PHP que WordPress n’adresse pas. wpdb ne dispose d'aucun crochet ni d'aucune action susceptible de vous aider. Par conséquent, la meilleure chose à faire est d'écrire votre propre fonction d'encapsuleur et d'exécuter vos requêtes afin d'éviter de vous répéter.

Tout d’abord, vous pouvez consulter http://us2.php.net/manual/en/function.mysql-fetch-field.php pour rendre votre wrapper plus dynamique.

Deuxièmement, wpdb stocke ces informations dans wpdb :: col_info et est accessible via wpdb :: get_col_info (). Cette variable est remplacée après chaque requête, vous devez donc y accéder immédiatement. De plus, comme il est indexé numériquement, vous devez savoir dans quel ordre se trouve votre champ (ou le parcourir en boucle, ce qui représente une somme de travail inutile).

Je tire juste de la hanche ici, mais quelque chose comme ...

function get_typed_results($sql, $output = OBJECT) {
    global $wpdb;
    $rows = $wpdb->get_results($sql, ARRAY_N);
    $new_result = array();
    foreach ($rows as $row) {
        $new_row = array();
        foreach ($row as $i => $value) {
            if ( $wpdb->col_info[$i]->numeric ) {
                if ( $wpdb->col_info[$i]->type == 'float' || $wpdb->col_info[$i]->type == 'double' )
                    $new_row[$wpdb->col_info[$i]->name] = (float)$value;
                elseif ( $wpdb->col_info[$i]->type == 'bool' || $wpdb->col_info[$i]->type == 'boolean' )
                    $new_row[$wpdb->col_info[$i]->name] = (bool)$value;
                else
                    $new_row[$wpdb->col_info[$i]->name] = (int)$value;
            }
            elseif ( $wpdb->col_info[$i]->type == 'datetime' )
                $new_row[$wpdb->col_info[$i]->name] = strtotime($value);
            else
                $new_row[$wpdb->col_info[$i]->name] = $value;
        }
        if ($output == ARRAY_A) $new_result[] = $new_row;
        elseif ($output == OBJECT) $new_result[] = (object)$new_row;
        else $new_result[] = array_values($new_row);
    }
    return $new_result;
}

Je ne sais pas vraiment quels types sont retournés, s'ils sont flottants, doubles ou autre chose, vous voudrez donc les tester et les corriger le cas échéant. De plus, je suppose que les booléens sont considérés comme numériques, mais peut-être que c'est inexact - encore une fois, testez. Bonne chance!

2
Matthew Boynes