Descargo de responsabilidad importante: la forma correcta de hacer esto NO es modificar la estructura de su tabla, sino usar wp_usermeta. Entonces no necesitará crear ningún SQL personalizado para consultar sus publicaciones (aunque aún necesitará algo de SQL personalizado para obtener una lista de todos los que informan a un supervisor en particular, por ejemplo, en la sección Administrador). Sin embargo, dado que el OP preguntó sobre la escritura de SQL personalizado, esta es la mejor práctica actual para inyectar SQL personalizado en una consulta de WordPress existente.
Si está haciendo uniones complejas, no puede simplemente usar el filtro posts_where, porque también necesitará modificar la unión, la selección y posiblemente el grupo por u ordenar por secciones de la consulta.
Su mejor opción es usar el filtro 'posts_clauses'. Este es un filtro muy útil (¡no se debe abusar!) Que le permite agregar / modificar las diversas partes del SQL que se generan automáticamente por las muchas líneas de código dentro del núcleo de WordPress. La firma de devolución de llamada del filtro es:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
y espera que regrese $clauses
.
Las cláusulas
$clauses
es una matriz que contiene las siguientes claves; cada clave es una cadena SQL que se usará directamente en la declaración SQL final enviada a la base de datos:
- dónde
- agrupar por
- unirse
- ordenar
- distinto
- campos
- límites
Si está agregando una tabla a la base de datos (solo haga esto si no puede aprovechar post_meta, user_meta o taxonomías) probablemente necesitará tocar más de una de estas cláusulas, por ejemplo, el fields
(el "SELECCIONAR" parte de la instrucción SQL), join
(todas sus tablas, excepto la de su cláusula "FROM"), y quizás el orderby
.
Modificando las Cláusulas
La mejor manera de hacerlo es subreferenciar la clave relevante de la $clauses
matriz que obtuvo del filtro:
$join = &$clauses['join'];
Ahora, si modifica $join
, en realidad estará modificando directamente, $clauses['join']
por lo que los cambios se realizarán $clauses
cuando lo devuelva.
Preservando las Cláusulas Originales
Es probable que (no, en serio, escuche) desee conservar el SQL existente que WordPress generó para usted. De lo contrario, probablemente debería mirar el posts_request
filtro; esa es la consulta completa de mySQL justo antes de que se envíe a la base de datos, por lo que puede bloquearla totalmente con la suya. Por qué querrías hacer esto? Probablemente no lo hagas.
Por lo tanto, para preservar el SQL existente en las cláusulas, recuerde agregar a las cláusulas, no asignarlas (es decir: $join .= ' {NEW SQL STUFF}';
no usar $join = '{CLOBBER SQL STUFF}';
. Tenga en cuenta que debido a que cada elemento de la $clauses
matriz es una cadena, si desea agregarle, probablemente desee insertar un espacio antes de cualquier otro token de caracteres; de lo contrario, probablemente creará algún error de sintaxis SQL.
Puede suponer que siempre habrá algo en cada una de las cláusulas, y recuerde comenzar cada nueva cadena con un espacio, como en:, $join .= ' my_table
o, siempre puede agregar una pequeña línea que solo agrega un espacio si necesita:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Eso es algo estilístico más que cualquier otra cosa. Lo importante para recordar es: ¡ siempre deje un espacio ANTES de su cadena si va a agregar a una cláusula que ya tiene algo de SQL!
Poniendo todo junto
La primera regla del desarrollo de WordPress es tratar de utilizar la mayor cantidad de funciones básicas que pueda. Esta es la mejor manera de preparar su trabajo para el futuro. Supongamos que el equipo central decide que WordPress ahora usará SQLite u Oracle o algún otro lenguaje de base de datos. ¡Cualquier MySQL escrito a mano puede volverse inválido y romper su plugin o tema! Es mejor dejar que WP genere la mayor cantidad de SQL posible por sí mismo, y solo agregue los bits que necesita.
Entonces, el primer orden de negocios es aprovechar WP_Query
para generar la mayor cantidad posible de su consulta base. El método exacto que usamos para hacer esto depende en gran medida de dónde se supone que debe aparecer esta lista de publicaciones. Si es una subsección de la página (no es su consulta principal) que usaría get_posts()
; si es la consulta principal, supongo que podría usarla query_posts()
y terminar con ella, pero la forma correcta de hacerlo es interceptar la consulta principal antes de que llegue a la base de datos (y consuma los ciclos del servidor), así que use el request
filtro.
Bien, entonces has generado tu consulta y el SQL está a punto de ser creado. Bueno, de hecho, ha sido creado, simplemente no enviado a la base de datos. Al usar el posts_clauses
filtro, agregará la tabla de relaciones de sus empleados a la mezcla. Llamemos a esta tabla {$ wpdb-> prefijo}. 'user_relationship', y es una tabla de intersección. (Por cierto, le recomiendo que genere esta estructura de tabla y la convierta en una tabla de intersección adecuada con los siguientes campos: 'relacion_id', 'id_usuario', 'related_user_id', 'relacion_tipo'; esto es mucho más flexible y poderoso. .. pero yo divago).
Si entiendo lo que quieres hacer, quieres pasar la identificación de un líder y luego ver solo las publicaciones de los seguidores de ese líder. Espero haber acertado. Si no está bien, tendrá que tomar lo que digo y adaptarlo a sus necesidades. Me quedaré con la estructura de su mesa: tenemos a leader_id
y a follower_id
. Por lo tanto, JOIN estará {$wpdb->posts}.post_author
activado como una clave foránea para 'follower_id' en su tabla 'user_relationship'.
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}