Actualizar múltiples filas con $wpdb->update en WordPress usando IN como en SQL normal

1 ago 2014, 17:08:52
Vistas: 15.3K
Votos: 7

Me preguntaba si es posible usar $wpdb->update para actualizar valores en múltiples filas como con IN en SQL "normal".

Quiero lograr algo como este ejemplo:

UPDATE [tabla]
SET [columna_1] = [valor_actualizado]
WHERE [columna_2] IN ([ids_separados_por_coma])

He estado buscando cómo funcionaría esto, pero aún no encuentro otra pregunta sobre esto o algún tipo de respuesta/publicación que explique si se puede hacer o no.

Por ahora estoy usando una consulta directa, pero sería mejor con una simple línea de código.

3
Comentarios

No hay razón para que no funcione.

Mark Kaplun Mark Kaplun
1 ago 2014 17:18:14

¿Pero CÓMO? Intenté añadir una cadena separada por comas como valor en el array where, pero solo actualizó el primer id.

Ludvig Sjöbeck Ludvig Sjöbeck
1 ago 2014 17:54:53

hmm, veo que personas con más conocimiento que yo ya lo respondieron ;)

Mark Kaplun Mark Kaplun
1 ago 2014 18:41:20
Todas las respuestas a la pregunta 1
5
12

Como puedes ver en el código fuente el signo = está codificado de forma fija en el método wpdb::update(), por lo que, por defecto, no es posible usar IN para el método de actualización.

La forma más sencilla de lograr esto es usando wpdb::query() con tu consulta SQL, solo asegúrate de escapar correctamente todos los valores.

Ejemplo:

function wpdb_update_in( $table, $data, $where, $format = NULL, $where_format = NULL ) {

    global $wpdb;

    $table = esc_sql( $table );

    if( ! is_string( $table ) || ! isset( $wpdb->$table ) ) {
        return FALSE;
    }

    $i          = 0;
    $q          = "UPDATE " . $wpdb->$table . " SET ";
    $format     = array_values( (array) $format );
    $escaped    = array();

    foreach( (array) $data as $key => $value ) {
        $f         = isset( $format[$i] ) && in_array( $format[$i], array( '%s', '%d' ), TRUE ) ? $format[$i] : '%s';
        $escaped[] = esc_sql( $key ) . " = " . $wpdb->prepare( $f, $value );
        $i++;
    }

    $q         .= implode( $escaped, ', ' );
    $where      = (array) $where;
    $where_keys = array_keys( $where );
    $where_val  = (array) array_shift( $where );
    $q         .= " WHERE " . esc_sql( array_shift( $where_keys ) ) . ' IN (';

    if( ! in_array( $where_format, array('%s', '%d'), TRUE ) ) {
        $where_format = '%s';
    }

    $escaped = array();

    foreach( $where_val as $val ) {
        $escaped[] = $wpdb->prepare( $where_format, $val );
    }

    $q .= implode( $escaped, ', ' ) . ')';

    return $wpdb->query( $q );
}

Luego úsalo así:

wpdb_update_in(
  'posts', // tabla
  array( 'post_author' => '1', 'post_status' => 'draft' ), // datos
  array( 'post_author' => array( '2', '3', '4', '5' ) ), // where
  array( '%d', '%s' ), // formato
  '%d' // formato where
);

El SQL ejecutado será:

UPDATE wp_posts
SET post_author = 1, post_status = 'draft'
WHERE post_author IN (2, 3, 4, 5)
1 ago 2014 18:29:41
Comentarios

No he trabajado mucho en WP, así que no estaba al tanto del código fuente. Me aseguraré de guardarlo como referencia para el futuro. Me gusta tu solución y la marcaré como la respuesta.

Ludvig Sjöbeck Ludvig Sjöbeck
4 ago 2014 10:13:36

Wordpress con código hardcodeado y difícil de usar...

Vishal Kumar Sahu Vishal Kumar Sahu
11 sept 2017 01:00:12

Lo encontré útil, pero parece que algunas cosas han cambiado desde que se hizo esta respuesta. Primero, la firma de implode() ha cambiado el orden de los parámetros desde PHP 7.4. Además, ¿no pude entender qué era $wpdb->$table? Al final lo eliminé.

JDandChips JDandChips
16 jun 2021 17:21:28

también existe el formato %f para autorizar

ZalemCitizen ZalemCitizen
21 abr 2024 00:55:24

Las cosas han cambiado en 10 años, sí :)

$wpdb->$table es la forma correcta de obtener el nombre completo de la tabla. No deberías usar, por ejemplo, "wp_content" sino $wpdb->content, porque el prefijo podría cambiar, y en multisitio cambiará definitivamente.

Esto no ha cambiado. Pero hoy tenemos el marcador %i para escapar nombres de tablas.

Respecto a %f, sí, eso se añadió relativamente hace poco junto con el %i mencionado anteriormente.

gmazzap gmazzap
2 may 2024 21:03:10