类中的MySQL导致挫败感


MySQL within classes causing frustration

我有这个代码:

<?php 
class guildData {
    public $email = NULL;
    public $hash_pw = NULL;
    public $user_id = NULL;
    public $clean_username = NULL;
    public $display_username = NULL;
    public function selectGuild($g_id)
    {
            global $db,$db_table_prefix;
            $this->g_id = $g_id;
            $sql = "SELECT
                            name
                            FROM
                            guild
                            WHERE
                            id = '".$g_id."'";
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            return ($row['name']);
    }
}
?>
<?php echo $guildData->selectGuild(1); ?>

我只是得到一个 500 错误,IDEone 也给了我这个:

致命错误:在第 32 行的/home/VT00Ds/prog.php 中的非对象上调用成员函数 selectGuild()

看不到错误,你能帮我吗?

你做错了。

  1. 摆脱全局变量。相反,如果类需要DB访问,那么你应该在构造函数中注入它:

    class GuildData
    {
        //  ... snip 
        protected $connection;
        public function __construct( PDO $connection )
        {
            $this->connection = $connection;
        }
        //  ... snip 
    }
    
  2. 您的代码具有 SQL 注入的潜力。不应连接查询,而应使用预准备语句:

    $statement = $this->connection->prepare(
                    'SELECT name FROM guild WHERE id = :id'
                 );
    $statement->bindParam( ':id', $this->g_id, PDO::PARAM_INT );
    if ( $statement->execute() )
    {
        $data = $statement->fetch( PDO::FETCH_ASSOC );
    }
    
  3. 您必须先实例化对象,然后才能使用它们:

    $pdo = new PDO('mysql:host=localhost;dbname=myMagicalDB;charset=UTF-8', 
                   'username', 'password');
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $guild = new GuildData( $pdo );
    $guild->selectGuild(42);
    
  4. 您可以考虑将带有 DB 处理的部分与域逻辑分开。本质上是让其他类处理数据的获取和存储,而Guild类管理逻辑。您可能会发现这个和这个答案相关。

  5. 不要使用public变量。通过直接公开内部数据来破坏对象的封装。相反,您应该将它们定义为 protectedprivate .

    你也可以仔细看看你实际上保留在那里的东西。为什么GuildData需要$hash_pw$clean_username

您尚未实例化$guildData 。 如果要在不实例化对象的情况下使用此方法,则应static该方法。

class guildData {
    public static function selectGuild($g_id) { ... }
}

然后你可以从

echo guildData::selectGuild(1);

否则,您需要实例化一个对象

$guildData = new GuildData();
echo $guildData->selectGuild(1);

此外,您应该在其中使用某种__construct()方法,以便设置成员变量。

更新我还注意到您的selectGuild()方法中存在错误:

$this->g_id = $g_id;

设置 g_id 的值,该值未定义为类中的成员变量。 必须在类定义中将g_id声明为成员变量:

class guildData {
    public $email = NULL;
    public $hash_pw = NULL;
    public $user_id = NULL;
    public $clean_username = NULL;
    public $display_username = NULL;
    public $g_id = NULL;
    .
    .
    .
}

最后,sql_query()不是我听说过的PHP方法。除非您使用的是定义这些方法的库,否则我认为您的意思是mysql_query().如果是这种情况,您应该停止使用mysql_*函数。它们正在被弃用。而是使用 PDO(从 PHP 5.1 开始支持)或 mysqli(从 PHP 4.1 开始支持)。如果您不确定要使用哪一个,请阅读这篇 SO 文章。