PHP、PDO 和遗留数据库 - 即时更改字符集?
PHP, PDO and legacy DB - change charset on the fly?
好久没用了PHP。需要将一个非常非常旧的站点从 mysql_*
升级到 PDO
。迁移工作正常,但数据库是混合 Latin1
和 utf8
表的可怕混乱。无法改变这一点。
看到了一个巧妙的解决方案 here,您只需为每种类型的字符集创建一个连接,但我的问题是该站点是作为 classes 的层次结构构建的,所有这些都来自单个 Db class,它在初始化时定义字符集。
在旧代码中,问题是 "solved" 通过使用 mysql_set_charset()
,但不幸的是我找不到 PDO 等价物。
如何在 PDO 连接上即时更改字符集?有可能吗?
或者谁能推荐一种模式?
这是 "fever rescue" 由 PHP 5.x 升级到 7.2 引起的,它不是重构整个代码库或数据库的选项。
大致是这样的:
class Db {
private $pdo;
public function __construct() {
$dsn = "mysql:host=".$this->hostname.";dbname=".$this->database.";charset=".$this->charset;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
$this->pdo = new PDO($dsn, $this->username, $this->password, $opt);
} catch(PDOException $e) {
echo "Error connecting to database: ". $e->getMessage();
}
}
}
class AnotherClass extends Db {
public function __construct() {
parent::__construct();
...
}
}
class YetAnotherClass extends AnotherClass [
...
}
想在Db
class上实现一个方法所以我在继承classes上可以执行例如$this->changeCharset('Latin1');
当使用PDO连接到MySQL时,明确设置字符集为utf8是明智的(当然,只有在使用utf8时才是字符集)。在 MySQL 或 MySQLi 扩展中,我通常会执行查询 SET NAMES utf8 来设置它。
在 PDO 中,可以在连接字符串中指定字符集:
$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);
字符集选项仅在 PHP 5.3.6 之后使用,因此在 运行使用旧版本的 PHP 时请考虑到这一点。在这种情况下,您应该 运行 在构建 PDO 对象后使用以下语句:
$conn->exec('SET NAMES utf8');
但是你不应该 运行宁这样一个旧版本的 PHP 无论如何。
已经有一个可接受的答案,但我 post 这只是为了将我在评论中的想法扩展到您的示例代码中。
class Db {
private $pdo;
public function __construct($charset) {
$dsn = "mysql:host=".$this->hostname.";dbname=".$this->database.";charset=".$charset;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
$this->pdo = new PDO($dsn, $this->username, $this->password, $opt);
} catch(PDOException $e) {
echo "Error connecting to database: ". $e->getMessage();
}
}
}
class AnotherClass extends Db {
public function __construct() {
parent::__construct('latin1');
}
}
好久没用了PHP。需要将一个非常非常旧的站点从 mysql_*
升级到 PDO
。迁移工作正常,但数据库是混合 Latin1
和 utf8
表的可怕混乱。无法改变这一点。
看到了一个巧妙的解决方案 here,您只需为每种类型的字符集创建一个连接,但我的问题是该站点是作为 classes 的层次结构构建的,所有这些都来自单个 Db class,它在初始化时定义字符集。
在旧代码中,问题是 "solved" 通过使用 mysql_set_charset()
,但不幸的是我找不到 PDO 等价物。
如何在 PDO 连接上即时更改字符集?有可能吗? 或者谁能推荐一种模式?
这是 "fever rescue" 由 PHP 5.x 升级到 7.2 引起的,它不是重构整个代码库或数据库的选项。
大致是这样的:
class Db {
private $pdo;
public function __construct() {
$dsn = "mysql:host=".$this->hostname.";dbname=".$this->database.";charset=".$this->charset;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
$this->pdo = new PDO($dsn, $this->username, $this->password, $opt);
} catch(PDOException $e) {
echo "Error connecting to database: ". $e->getMessage();
}
}
}
class AnotherClass extends Db {
public function __construct() {
parent::__construct();
...
}
}
class YetAnotherClass extends AnotherClass [
...
}
想在Db
class上实现一个方法所以我在继承classes上可以执行例如$this->changeCharset('Latin1');
当使用PDO连接到MySQL时,明确设置字符集为utf8是明智的(当然,只有在使用utf8时才是字符集)。在 MySQL 或 MySQLi 扩展中,我通常会执行查询 SET NAMES utf8 来设置它。
在 PDO 中,可以在连接字符串中指定字符集:
$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);
字符集选项仅在 PHP 5.3.6 之后使用,因此在 运行使用旧版本的 PHP 时请考虑到这一点。在这种情况下,您应该 运行 在构建 PDO 对象后使用以下语句:
$conn->exec('SET NAMES utf8');
但是你不应该 运行宁这样一个旧版本的 PHP 无论如何。
已经有一个可接受的答案,但我 post 这只是为了将我在评论中的想法扩展到您的示例代码中。
class Db {
private $pdo;
public function __construct($charset) {
$dsn = "mysql:host=".$this->hostname.";dbname=".$this->database.";charset=".$charset;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
$this->pdo = new PDO($dsn, $this->username, $this->password, $opt);
} catch(PDOException $e) {
echo "Error connecting to database: ". $e->getMessage();
}
}
}
class AnotherClass extends Db {
public function __construct() {
parent::__construct('latin1');
}
}