web-dev-qa-db-fra.com

Est-ce une mauvaise pratique d'aller directement à la base de données mysql lors du développement d'un plugin?

Ceci est un exemple du plugin Vote it Up :

//Run this to create an entry for a post in the voting system. Will check if the post exists. If it doesn't, it will create an entry.
function SetPost($post_ID) {
    global $wpdb;

    //prevents SQL injection
    $p_ID = $wpdb->escape($post_ID);

    //Check if entry exists
    $id_raw = $wpdb->get_var("SELECT ID FROM ".$wpdb->prefix."votes WHERE post='".$p_ID."'");
    if ($id_raw != '') {
        //entry exists, do nothing
    } else {
        //entry does not exist
        $wpdb->query("INSERT INTO ".$wpdb->prefix."votes (post, votes, guests, usersinks, guestsinks) VALUES(".$p_ID.", '', '', '', '') ") or die(mysql_error());
    }
}

//Run this to create an entry for a user in the voting system. Will check if the user exists. If it doesn't, it will create an entry.
function SetUser($user_ID) {
    global $wpdb;

    //prevents SQL injection
    $u_ID = $wpdb->escape($user_ID);

    //Check if entry exists
    $id_raw = $wpdb->get_var("SELECT ID FROM ".$wpdb->prefix."votes_users WHERE user='".$u_ID."'");
    if ($id_raw != '') {
        //entry exists, do nothing
    } else {
        //entry does not exist
        $wpdb->query("INSERT INTO ".$wpdb->prefix."votes_users (user, votes, sinks) VALUES(".$u_ID.", '', '') ") or die(mysql_error());
    }
}

//Returns the vote count
function GetVotes($post_ID, $percent = false) {
    global $wpdb;

    //prevents SQL injection
    $p_ID = $wpdb->escape($post_ID);

    //Create entries if not existant
    SetPost($p_ID);

    //Gets the votes
    $votes_raw = $wpdb->get_var("SELECT votes FROM  ".$wpdb->prefix."votes WHERE post='".$p_ID."'");
    $sinks_raw = $wpdb->get_var("SELECT usersinks FROM  ".$wpdb->prefix."votes WHERE post='".$p_ID."'");
    $guestvotes_raw = $wpdb->get_var("SELECT guests FROM  ".$wpdb->prefix."votes WHERE post='".$p_ID."'");
    $guestsinks_raw = $wpdb->get_var("SELECT guestsinks FROM  ".$wpdb->prefix."votes WHERE post='".$p_ID."'");
/* Deprecated
    $uservotes_raw = $wpdb->get_var("SELECT votes FROM ".$wpdb->prefix."votes_users WHERE user='".$u_ID."'");
    $usersinks_raw = $wpdb->get_var("SELECT sinks FROM ".$wpdb->prefix."votes_users WHERE user='".$u_ID."'");
*/

    //Put it in array form
    $votes = explode(",", $votes_raw);
    $sinks = explode(",", $sinks_raw);
    $guestvotes = explode(",", $guestvotes_raw);
    $guestsinks = explode(",", $guestsinks_raw);
/* Deprecated
    $uservotes = explode(",", $uservotes_raw);
    $usersinks = explode(",", $usersinks_raw);
*/
    $uservotes = 0;
    $usersinks = 0;

    $initial = 0; //Initial no. of votes [will be placed at -1 when all posts receive votes]

(etc...)

Beaucoup de gens m'ont dit que c'était une mauvaise pratique d'aller directement à la base de données mysql. Que le code puisse se briser dans les futures versions de Wordpress.

Ou est-il nécessaire dans certains plugins comme Vote it Up?

3
janoChen

Bonjour @ janoChen:

La réponse correcte est: "Cela dépend."

En général, il est préférable d’utiliser des fonctions WordPress intégrées plutôt que d’utiliser le SQL direct lorsque certaines fonctions intégrées peuvent vous fournir ce dont vous avez besoin. Cependant, les réponses à de nombreux Les questions que je vois ici sur WPSE sont (malheureusement) "vous devez utiliser le SQL direct pour cela car WordPress ne fournit tout simplement pas une fonction (n efficace) pour vous fournir ce dont vous avez besoin."

Dans le cas du plugin Vote It Up, on peut soutenir que leur choix de SQL direct était correct car il n’existait pas d’endroit efficace pour stocker les votes dans la base de données WordPress. D'autre part, certains argueraient du fait qu'ils auraient dû utiliser wp_postmeta et wp_usermeta pour stocker ces informations. Personnellement, je suis sur la clôture pour un plugin de vote; Je devrais en mettre en place un (ce que j'ai fait, mais c'était il y a presque 2 ans et j'ai beaucoup appris depuis) ​​ pour vraiment avoir un avis sur la meilleure façon de le faire.

Une chose que je dirai est que, presque chaque fois que possible, je préfère utiliser les tableaux intégrés avec WordPress plutôt que d’ajouter de nouveaux tableaux. L'ajout d'une table a un impact plus important que l'ajout de code SQL pour accéder aux tables existantes. Cela dit, je pourrais peut-être apprendre à utiliser les méta-tables pour un plug-in de vote, mais honnêtement, je ne peux pas le dire sans équivoque, à moins que et jusqu'à ce que j'essaie réellement d'implémenter une telle fonctionnalité.

METTRE À JOUR

Je viens de lire le code de c.bavota et à certains égards, il est bon, à d'autres égards, cela me trouble. J'aime le fait qu'il utilise post meta, mais je n'aime pas qu'il mette la liste des user_ids séparés par des virgules dans un champ post meta. Que se passe-t-il lorsqu'un message obtient 25 000 votes? Il est clair que son code ne s’adapte pas à un site à fort trafic. Et son code ralentirait considérablement l'obtention d'une liste de tous les messages votés par un utilisateur donné pour tout site comportant un grand nombre de messages.

S'il doit placer tous les identifiants d'utilisateur pour les votes dans un méta-champ, il doit le faire de manière plus évolutive, comme stocker les identifiants de post-traitement dans les méta-utilisateurs, car il est peu probable qu'un utilisateur vote 25 000 fois, voire 2500 fois. Ou il pourrait stocker des votes en incorporant l'ID utilisateur dans la méta clé de publication, c'est-à-dire "user_vote_{$user_id}" (bien que peut-être 25 000 méta-enregistrements poseraient eux-mêmes des problèmes.)

OTOH, si vous avez vraiment besoin de suivre les votes par utilisateur, c'est là que je pourrais argumenter pour une table et que le SQL direct pourrait avoir un sens.

De plus, il lance son propre service Web au lieu d'utiliser la fonctionnalité intégrée AJAX pour les services Web. Bien que je n'aime pas que la fonctionnalité intégrée ne soit pas RESTful, je ne pense pas que ce soit une bonne idée de recréer une infrastructure de service Web à moins que vous ne le fassiez correctement. Faire les choses correctement inclurait la sécurité intégrée et le code de c.bavota ne s’inquiète pas de la sécurité; pas d'échappée des valeurs $_POST, pas d'utilisation de nonces, rien.

Et son code pourrait facilement sous-comptabiliser les votes si deux personnes ou plus votent en même temps. Ce qui est un peu effrayant, c’est que ce type vend des thèmes premium et que ses articles de procédures contiennent un code qui enfreint plusieurs meilleures pratiques connues. Mais je pense qu'il n'est pas unique en tant que fournisseur de thèmes ayant des problèmes de sécurité ou d'évolutivité. <soupir>.

J'ai laissé un commentaire sur ces problèmes en lui suggérant d'avertir immédiatement ses utilisateurs et de le mettre à jour avec de meilleures techniques, mais il est actuellement en modération. Espérons qu'il le publie.

UPDATE2

Pourquoi utiliser des fonctions telles que update_post_meta() plutôt que de mettre à jour directement la base de données? Plusieurs raisons, mais beaucoup plus importantes pour les plugins ou les thèmes que vous envisagez de distribuer que pour le code que vous écrivez pour votre propre site (bien que, dans l'idéal, cela soit également utile pour ce dernier.):

  1. Par chance, WordPress risque de modifier la structure de la base de données méta. Ils l'ont déjà fait et pourraient le faire à nouveau. Si vous utilisez les fonctions intégrées au lieu de SQL, votre code continuera à fonctionner, mais il est évident que le code SQL direct se brisera lors d'une mise à niveau de WordPress.

  2. Si vous utilisez update_post_meta(), cela fonctionnera pour un site unique et Multisite. Le code SQL direct fonctionnera pour l’un mais pas l’autre.

  3. Si vous utilisez update_post_meta() et que quelqu'un souhaite utiliser un plug-in qui stocke les valeurs fréquemment utilisées dans MemCached , votre code le supportera, mais pas si vous écrivez en SQL direct.

  4. En général, si un plugin ou un thème pose un update_post_meta(), le hook fonctionnera si vous utilisez update_post_meta() mais pas si vous utilisez du SQL direct.

  5. Et je suis sûr qu'il y a d'autres raisons pour lesquelles je ne peux pas penser maintenant.

Qu'il suffise de dire que l'utilisation des fonctions intégrées offre une robustesse et une flexibilité incomparables; utilisez donc directement SQL lorsque vous ne pouvez pas le faire avec des fonctions intégrées. JMTCW.

6
MikeSchinkel

Pour la plupart des plugins, il suffit d'utiliser WordPress Options-API . Bien que cela fonctionne bien pour les boutons, les chaînes et autres choses simples, des plugins plus complexes ont parfois besoin de leur propre table de base de données. Si vous vous trouvez dans une telle situation, vous devez suivre les directives officielles à la page Créer des tables avec des plugins .

Il n’ya rien de mal à aller directement dans la base de données tant que vous vérifiez l’entrée correctement et que vous vous assurez que votre code est complètement sécurisé. WordPress a beaucoup de fonctions qui rendent cela beaucoup plus facile (voir à nouveau: Créer des tables avec des plugins ), c'est pourquoi je le recommande personnellement de cette façon.

1
marvinhagemeister