在开发插件时直接访问MySQL数据库是不是一种糟糕的做法?

时间:2011-03-28 作者:janoChen

这是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]
(等等……)

我从许多人那里听说,直接访问mysql数据库是一种不好的做法。这些代码可能会在未来版本的Wordpress中分解。

或者它在一些插件中是必要的,比如投票?

2 个回复
最合适的回答,由SO网友:MikeSchinkel 整理而成

你好@janoChen:

正确答案是:"It depends."

一般来说,当有内置函数可以提供您所需的内容时,使用内置WordPress函数比使用direct SQL要好

在Vote It Up插件的情况下,他们选择的直接SQL是正确的,这是有争议的,因为WordPress数据库中没有一个有效的地方来存储投票。另一方面,也有人认为他们应该使用wp_postmetawp_usermeta 存储该信息。就个人而言,我对投票插件持怀疑态度;实际上,我必须实现一个(我已经做到了,但那是将近两年前的事了,从那以后我学到了很多)才能真正对最好的方法有一个看法。

我要说的一件事是,几乎在任何可能的情况下,我都喜欢将内置表与WordPress一起使用,而不是添加新表。添加表比添加SQL代码来访问现有表有更大的影响。考虑到这一点,我可能会学习将元表用于投票插件,但老实说,除非我真正尝试实现这样的功能,否则我无法明确地说明这一点。

更新我刚读到the code by c.bavota 在某些方面它是好的,在其他方面它困扰着我。我喜欢他使用post-meta,但我不喜欢他将逗号分隔的user\\u id列表放在post-meta字段中。当一个职位获得25000张选票时会发生什么?很明显,他的代码不适用于高流量站点。他的代码会使获得一个给定用户为任何有大量帖子的站点投票的所有帖子的列表变得非常缓慢。

如果他打算将所有用于投票的用户ID填充到元字段中,他应该以一种更具可扩展性的方式进行操作,例如将帖子ID存储在用户元中,因为一个用户投票25000次,甚至2500次的机会非常小。或者他可以通过将用户ID嵌入post元密钥来存储投票,即。"user_vote_{$user_id}" (尽管25000条元记录可能会导致自身问题。)

OTOH,如果您真的需要跟踪用户的投票,那么我可能会在这里主张使用表和直接SQL。

此外,他还推出了自己的web服务,而不是使用build-in AJAX functionality 对于web服务。虽然我不喜欢内置功能不是RESTful的,但我认为,除非您做得对,否则重新创建web服务基础架构不是一个好主意。正确的操作将包括内置的安全性,而c.bavota的代码并不担心安全性;无法逃脱$_POST 值,不使用nonce,不使用。

而且,如果两个或两个以上的人同时投票,他的代码很容易低估投票数。有点可怕的是,这家伙在销售高级主题,而他的指导性文章中的代码违反了几个已知的最佳实践。但我认为,作为一个主题供应商,他并不是唯一一个有安全性或可伸缩性问题的代码的供应商<;叹气(>;);。

我就这些问题发表了评论,并建议他立即警告他的用户,并使用更好的技术进行更新,但目前情况尚不明朗。希望他能出版。

更新2为什么要使用以下函数update_post_meta() 而不是直接更新数据库?有几个原因,但对于您计划分发的插件或主题来说,比您为自己的站点编写的代码更重要(尽管理想情况下,这对后者也有帮助):

WordPress很有可能会利用meta的数据库结构。他们以前做过,可能还会再做一次。如果您使用内置函数而不是SQL,那么您的代码将继续工作,但很明显,直接SQL代码将在WordPress升级时中断。

如果您使用update_post_meta() 它将适用于单个站点and 多站点。直接SQL代码适用于其中一种,但不适用于另一种。

如果您使用update_post_meta() 有人想使用一个插件,将频繁访问的值存储在MemCached 您的代码将支持它,但如果您编写直接SQL,则不支持它。

如果插件或主题挂钩update_post_meta() 如果你使用update_post_meta() 但如果使用直接SQL,则不会。

我确信还有其他原因我现在想不起来。

可以说,使用内置函数提供了direct SQL无法比拟的健壮性和灵活性;因此,只有在无法使用内置函数时才使用直接SQL。JMTCW。

SO网友:marvinhagemeister

对于大多数插件来说,使用WordPress就足够了Options-API. 虽然这对于按钮、字符串和其他简单的东西很好,但更复杂的插件有时需要自己的数据库表。如果您遇到这种情况,您应该遵循页面上的官方指南Creating Tables with Plugins.

只要正确验证输入并确保代码绝对安全,直接进入数据库没有什么错。WordPress有许多功能,使这一过程变得更加简单(再次,请参阅:Creating Tables with Plugins), 这就是我个人推荐这种方式的原因。

结束

相关推荐

How do you debug plugins?

我对插件创作还很陌生,调试也很困难。我用了很多echo,它又脏又丑。我确信有更好的方法可以做到这一点,也许是一个带有调试器的IDE,我可以在其中运行整个站点,包括插件?