PHP, PDO и устаревшая БД - меняйте кодировку на лету? - PullRequest
0 голосов
/ 30 ноября 2018

Давно, с тех пор как я использовал PHP.Необходимо обновить очень, очень старый сайт с mysql_* до PDO.Миграция работает хорошо, но БД - ужасный беспорядок из смешанных таблиц Latin1 и utf8.Не могу изменить это.

Вы видели изящное решение здесь , где вы просто создаете соединение для каждого типа кодировки, но моя проблема в том, что сайт построен как иерархия классов, все производные от одногоКласс Db, который определяет кодировку при инициализации.

В старом коде проблема была «решена» с помощью mysql_set_charset(), но, к сожалению, я не могу найти эквивалент PDO.

Как изменить кодировку на лету при подключении к PDO?Это вообще возможно?Или кто-нибудь может предложить какой-то шаблон?

Это «спасение от лихорадки», вызванное обновлением с 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, чтобы я в унаследованных классах мог выполнить, например, $this->changeCharset('Latin1');

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Уже есть принятый ответ, но я опубликую его только для того, чтобы расширить мою идею в комментариях к вашему примеру кода.

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');
  }
}
0 голосов
/ 30 ноября 2018

При использовании PDO для подключения к MySQL целесообразно явно установить набор символов в utf8 (конечно, только при использовании utf8 - кодировка).В расширении MySQL или MySQLi я обычно выполняю запрос SET NAMES utf8, чтобы установить его.

В PDO кодировка может быть указана в строке подключения:

$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);

Опция charsetиспользуется только с PHP 5.3.6, поэтому учитывайте это при запуске более старой версии PHP.В этом случае вы должны выполнить следующую инструкцию после создания объекта PDO:

$conn->exec('SET NAMES utf8');

Но вы все равно не должны запускать такую ​​старую версию PHP.

...