Avis de non-responsabilité important: la bonne façon de procéder n'est PAS de modifier la structure de votre table, mais d'utiliser wp_usermeta. Ensuite, vous n'aurez pas besoin de créer de SQL personnalisé pour interroger vos publications (bien que vous ayez toujours besoin de SQL personnalisé pour obtenir une liste de tous ceux qui relèvent d'un superviseur particulier - dans la section Admin, par exemple). Cependant, puisque l'OP a demandé d'écrire du SQL personnalisé, voici la meilleure pratique actuelle pour injecter du SQL personnalisé dans une requête WordPress existante.
Si vous effectuez des jointures complexes, vous ne pouvez pas simplement utiliser le filtre posts_where, car vous devrez également modifier les sections de la jointure, de la sélection et éventuellement du groupe par ou de l'ordre de la requête.
Le mieux est d'utiliser le filtre 'posts_clauses'. Il s'agit d'un filtre très utile (à ne pas abuser!) Qui vous permet d'ajouter / modifier les différentes parties du SQL généré automatiquement par les nombreuses lignes de code dans le noyau WordPress. La signature de rappel du filtre est:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
et il attend que vous reveniez $clauses
.
Les clauses
$clauses
est un tableau qui contient les clés suivantes; chaque clé est une chaîne SQL qui sera directement utilisée dans la dernière instruction SQL envoyée à la base de données:
- où
- par groupe
- joindre
- commandé par
- distinct
- des champs
- limites
Si vous ajoutez une table à la base de données (ne faites cela que si vous ne pouvez absolument pas tirer parti de post_meta, user_meta ou taxonomies), vous devrez probablement toucher plusieurs de ces clauses, par exemple, le fields
(le "SELECT" partie de l'instruction SQL), la join
(toutes vos tables, à l'exception de celle de votre clause "FROM"), et peut-être la orderby
.
Modification des clauses
La meilleure façon de le faire est de sous-référencer la clé appropriée du $clauses
tableau que vous avez obtenue du filtre:
$join = &$clauses['join'];
Maintenant, si vous modifiez $join
, vous serez en fait en train de modifier directement $clauses['join']
afin que les modifications soient apportées $clauses
lorsque vous le retournerez.
Préserver les clauses originales
Il y a de fortes chances (non, sérieusement, écoutez) que vous souhaitiez conserver le SQL existant que WordPress a généré pour vous. Sinon, vous devriez probablement regarder le posts_request
filtre à la place - c'est la requête complète mySQL juste avant qu'elle ne soit envoyée à la base de données, afin que vous puissiez la remplir complètement avec la vôtre. Pourquoi voudriez-vous faire ça? Vous ne le faites probablement pas.
Donc, afin de préserver le SQL existant dans les clauses, n'oubliez pas d'ajouter aux clauses, pas de les affecter (c'est-à-dire: $join .= ' {NEW SQL STUFF}';
ne pas utiliser $join = '{CLOBBER SQL STUFF}';
. Notez que parce que chaque élément du $clauses
tableau est une chaîne, si vous souhaitez y ajouter, vous voudrez probablement insérer un espace avant tout autre jeton de caractère, sinon vous créerez probablement une erreur de syntaxe SQL.
Vous pouvez simplement supposer qu'il y aura toujours quelque chose dans chacune des clauses, et n'oubliez donc pas de commencer chaque nouvelle chaîne avec un espace, comme dans:, $join .= ' my_table
ou, vous pouvez toujours ajouter une petite ligne qui n'ajoute un espace que si vous devez:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
C'est une chose stylistique plus que toute autre chose. Le point important à retenir est: toujours laisser un espace AVANT votre chaîne si vous ajoutez à une clause qui contient déjà du SQL!
Mettre ensemble
La première règle de développement de WordPress est d' essayer d'utiliser autant de fonctionnalités de base que possible. C'est le meilleur moyen de pérenniser votre travail. Supposons que l'équipe principale décide que WordPress utilisera désormais SQLite ou Oracle ou un autre langage de base de données. Tout mySQL manuscrit peut devenir invalide et casser votre plugin ou votre thème! Mieux vaut laisser WP générer autant de SQL que possible, et ajouter simplement les bits dont vous avez besoin.
Donc, le premier ordre du jour consiste à tirer parti WP_Query
de générer autant de votre requête de base que possible. La méthode exacte que nous utilisons pour ce faire dépend en grande partie de l' endroit où cette liste de messages est censée apparaître. Si c'est une sous-section de la page (pas votre requête principale) que vous utiliseriez get_posts()
; si c'est la requête principale, je suppose que vous pouvez l'utiliser query_posts()
et en finir, mais la bonne façon de le faire est d'intercepter la requête principale avant qu'elle ne frappe la base de données (et consomme des cycles de serveur), utilisez donc le request
filtre.
D'accord, vous avez donc généré votre requête et le SQL est sur le point d'être créé. Eh bien, en fait, il a été créé, mais pas envoyé à la base de données. En utilisant le posts_clauses
filtre, vous allez ajouter votre table de relations avec les employés dans le mix. Appelons cette table {$ wpdb-> prefix}. 'user_relationship', et c'est une table d'intersection. (Soit dit en passant, je vous recommande de généraliser cette structure de table et de la transformer en une table d'intersection appropriée avec les champs suivants: 'relation_id', 'user_id', 'related_user_id', 'relation_type'; c'est beaucoup plus flexible et puissant. .. mais je m'égare).
Si je comprends ce que vous voulez faire, vous voulez transmettre un ID de leader et ne voir que les publications de ses suiveurs. J'espère avoir bien compris. Si ce n'est pas bien, vous devrez prendre ce que je dis et l'adapter à vos besoins. Je m'en tiendrai à la structure de votre table: nous avons un leader_id
et un follower_id
. Ainsi, le JOIN sera {$wpdb->posts}.post_author
activé en tant que clé étrangère du 'follower_id' sur votre table '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;
}