【问题标题】:PDO with table prefix带表前缀的 PDO
【发布时间】:2012-04-19 18:41:21
【问题描述】:

我有以下模型类,我的所有模型都扩展了它。

class Model {
    [...]
    protected static $_query; // Query preparated

    public function prepare($query = null) {
        [...] // Connect to PDO, bla bla bla

        self::$_query = self::$link->prepare($query);
    }

    [...]

}

class Login extends Model {
    public function getUser($username = null) {
        self::prepare('SELECT * FROM usuarios WHERE usuario = :username LIMIT 1');
        self::bindValue('username', $username);

        return self::fetch();
    }
}

问题是,我需要在我的mysql中插入前缀,以避免表冲突,但不想编辑我所有的查询。

clientone_tablename
clienttwo_tablename
clientthree_tablename

如何在准备查询时解析和插入表前缀?

我什么都没试过,因为我知道的是,将我的自定义 PDO 扩展到 PHP PDO 类,现在这并不多..

我见过这个:PDO - Working with table prefixes。但不要正常工作..

谢谢!

【问题讨论】:

  • 您真的需要为每张表设置一个客户端名称吗?您不能生成一组随机数字并将其附加到“tbl_client”,这样它就会变成“tbl_client4455”,然后将该表名存储在您的clients 表中,以便您知道哪个表适用于哪个客户端?
  • @Ozzy 这么丑……
  • 我想知道你对解析 SQL 有什么看法??但是,您可以只添加它们的名称(即SELECT name FROM clients WHERE id=?)而不是数字,然后将其附加到表名中。除了当没有人应该能够看到它时它的丑陋之处(关于您的客户的私人信息?)。它只能通过您的程序访问,因此无论如何该名称都是隐藏的。
  • @Ozzy 我有像usersnewspagesfiles 这样的表格。我想为每个客户提供每个(和其他)表中的一个。因为是一个具有多个客户端项目的 mysql。所以,这不是最好的方法。
  • 我会给你一个答案(例子)来告诉你我的意思......

标签: php mysql pdo


【解决方案1】:

所以我假设您只有 1 个 MySQL 数据库(您的网络主机上的最小软件包)并且需要为您的每个客户端存储一个系统副本。

我的建议是,您创建一组单独的表(针对每个客户),但名称无关紧要,因为您可以在客户表中查找表名。

这是我给你的例子:客户表应该存储他们自己的表的表名
(例如 users_tbl = clientone_users for client id:1)以便稍后您可以查询 clients 表并获取他/她的表名,然后使用该结果查询他/她的 user、news、pages 和 files 表。

# SQL: new table structure
-- store the names of the clients tables here
CREATE TABLE clients(
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    name VARCHAR(50),
    address VARCHAR(250),
    email VARCHAR(50),
    pass BLOB,
    /* table names*/
    users_tbl VARCHAR(70),
    news_tbl VARCHAR(70),
    pages_tbl VARCHAR(70),
    files_tbl VARCHAR(70)
) ENGINE = InnoDB;

# PHP: Some definitions for the table structure
$tbl_names = array("_users","_news","_pages","_files");
$tbl_fields = array();
$tbl_fields[0] = array("id INT","users_col1 VARCHAR(10)","users_col2 VARCHAR(20)");
$tbl_fields[1] = array("id INT","news_col1 DATE",...);
$tbl_fields[2] = array(...);
$tbl_fields[3] = array(...);
// refers to YOUR clients table field names (see above)
$clients_fields = array("users_tbl", "news_tbl", "pages_tbl", "files_tbl");

# PHP: Create a user and create the users database
function createUser($name, $address, $email, $pass, $salt) {
    global $db, $tbl_names, $tbl_fields;
    $success = false;
    if ($db->beginTransaction()) {
        $sql = "INSERT INTO clients(name, address, email, pass)
                     VALUES (?, ?, ?, AES_ENCRYPT(?, ?));"
        $query = $db->prepare($sql);
        $query->execute(array($name, $address, $email, $pass, $salt));
        if ($query->rowCount() == 1) { # if rowCount() doesn't work
            # get the client ID        # there are alternative ways
            $client_id = $db->lastInsertId();
            for ($i=0; $i<sizeof($tbl_names); $i++) {
                $client_tbl_name = $name . $tbl_names[$i];
                $sql = "CREATE TABLE " . $client_tbl_name . "("
                           . implode(',', $tbl_fields[$i]) . ");";
                if (!$db->query($sql)) {
                    $db->rollBack();
                    return false;
                } else {
                    $sql = "UPDATE clients SET ".clients_fields[$i]."=? "
                                       ."WHERE id=?;";
                    $query = $db->prepare($sql);
                    if (!$query->execute(
                            array($client_tbl_name, (int)$client_id)
                                         )) {
                        $db->rollBack();
                        return false;
                    }
                }
            }
            $db->commit();
            $success = true;
        }
        if (!$success) $db->rollBack();
    }
    return $success;
}

# PHP: Get the Client's table names
function getClientsTableNames($client_id) {
    $sql = "SELECT (users_tbl, news_tbl, pages_tbl, files_tbl)
              FROM clients WHERE id=?;";
    $query = $db->prepare($sql);
    if ($query->execute(array((int)$client_id)))
        return $query->fetchAll();
    else
        return null;
}

# PHP: Use the table name to query it
function getClientsTable($client_id, $table_no) {
    $table_names = getClientsTableNames($client_id);
    if ($table_names != null && isset($table_names[$table_no])) {
        $sql = "SELECT * FROM ".$table_names[$table_no].";";
        $query = $db->prepare($sql);
        if ($query->execute(array((int)$client_id)))
            return $query->fetchAll();
    }
    return null;
}

【讨论】:

  • 我想我会失去一些性能,但基本上,它就像self::prepare('SELECT * FROM ' . self::getPrefix([$dbname if multiple DB, or null for current DB]) . 'usuarios WHERE usuario = :username LIMIT 1');..(静态成员可以是$this-&gt;getPrefix(),或$db-&gt;getPrefix()等)
  • 我只是使用了普通的 PDO,PDOStatement 代码,但是如果你明白我在说什么,你可以改变代码来使用你的数据库抽象层。
  • 是的,我在说:通过这种方式,我需要一个方法/函数来插入前缀。为此,我可以将前缀存储在 config.php 中并使用 $db-&gt;getPrefix() 获取例如,这是最简单的方法。使用这种方法,self::prepare('SELECT * FROM #__usuarios WHERE usuario = :username LIMIT 1'); 怎么样,在我的模型中 prepare()#__ 替换为config.php 定义表前缀。
  • 包含定义前缀require_once('table_settings.php');的文件会更容易,在函数中将前缀定义为全局,以便您可以访问它getUser { global $prefix; ... },然后这样做:@ 987654331@ 但我认为无论哪种方式都行得通。
  • 感谢您的帮助,让我有了这样的想法。 =)
【解决方案2】:

只需重写您的查询以使用在某处变量中找到的表前缀。解析所有表名查询比它的价值更麻烦。 (你真的要写一个 SQL 解析器吗?)

【讨论】:

  • 我认为更容易解析..我不喜欢self::prepare('SELECT * FROM ' . self::getPrefix() . 'usuarios WHERE usuario = :username LIMIT 1');..如果我有一个复杂的查询,这就像一个不干净的方式来做到这一点..
  • 我不确定你怎么会认为编写 sql 解析器比字符串插值更容易。 (另外,停止使用静态成员!如果你想在同一个应用程序中使用两个不同的前缀怎么办?)
  • 由于没有静态成员,我需要从数据库中获取前缀。self::getPrefix('db1')self::getPrefix('db2')
猜你喜欢
  • 2014-01-30
  • 2010-12-08
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
相关资源
最近更新 更多