¿Cómo preparar correctamente una sentencia SQL con %LIKE%?
Me gustaría usar una sentencia LIKE %texto% mientras sigo utilizando la clase $wpdb de WordPress para sanitizar y preparar la entrada.
SELECT column_1 from `prefix_my_table` WHERE column_2 LIKE '%something%';
He intentado algo como esto sin éxito:
$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %s;", like_escape($number_to_put_in_like));
¿Cómo se prepara correctamente una sentencia SQL %LIKE% usando la clase de base de datos de WordPress?
La función $wpdb->esc_like
existe en WordPress porque el escape regular de la base de datos no escapa los caracteres %
y _
. Esto significa que puedes agregarlos en tus argumentos para wpdb::prepare()
sin problema. Esto es también lo que veo en el código central de WordPress:
$wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');
Así que tu código se vería así:
$wpdb->prepare(
"SELECT
column_1
FROM
`{$wpdb->base_prefix}my_table`
WHERE
column_2 LIKE %s;",
'%' . $wpdb->esc_like($number_to_put_in_like) . '%'
);
También puedes agregar %%
en tu consulta para obtener un %
literal (wpdb::prepare()
usa vsprintf()
en segundo plano, que tiene esta sintaxis), pero recuerda que tu cadena no será entrecomillada, debes agregar las comillas tú mismo (lo cual no es lo que normalmente tienes que hacer en wpdb::prepare()
).

@FranciscoCorralesMorales: Para indicar que todo lo que está dentro debe ser considerado una expresión variable, de lo contrario solo vería $wpdb
e ignoraría el ->prefix
después de este.

@JanFabry Casi. Corregiría el comentario para decir: "... de lo contrario vería todo $wpdb->base_prefixmi_tabla
e intentaría buscar la propiedad base_prefixmi_tabla
en lugar de solo base_prefix
.

También es importante mencionar que los % están siendo reemplazados por un hash ridículamente largo. Lo cual parece incorrecto cuando haces var_dump de la salida SQL. Después de horas de búsqueda, se menciona aquí que esto es una corrección de seguridad de WordPress 4.8.3 para inyección SQL. https://stackoverflow.com/a/57914094/7977916

Necesitas duplicar los porcentajes para que no sean tratados como marcadores de fragmentos por wpdb->prepare()
:
$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %%%s%%;", $wpdb->esc_like( $number_to_put_in_like));
PD: No estoy seguro si esta es la mejor/única forma de hacerlo.

Recuerda que debes agregar las comillas alrededor de la cadena tú mismo, porque wpdb::prepare
solo las agregará para un %s
que no esté precedido por un %
. La parte final de tu consulta debería ser WHERE column_2 LIKE '%%%s%%'
.

Esta es una forma de hacerlo que he verificado y funciona:
$search_text = "%" . $_GET['some_text'] . "%";
$user_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM mix_library WHERE ml_setting_name LIKE %s",
$search_text
)
);
Reemplaza las variables según tus necesidades.

Deberías escapar los caracteres %
(usando like_escape()
). Consulta: http://codex.wordpress.org/Class_Reference/wpdb#Protect_Queries_Against_SQL_Injection_Attacks

$safe_sql = $wpdb->prepare("SELECT * FROM $wp_track_table $sql",["*yoursecretkey*".$_POST['search']."*yoursecretkey*"]);
$safe_sql = str_replace("*yoursecretkey*", "%", $safe_sql);
Encontré una solución adecuada con los códigos anteriores. Definitivamente pruébalo.

¿Así que tu enfoque es pasar una cadena aleatoria a prepare() y reemplazarla con porcentajes después? Se siente como si estuvieras luchando contra WordPress.
