PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; private $host; private $port = '3306'; private $db; private $user; private $pass; private $charset = 'utf8'; private $sphinx = false; private $PostgreSQL = false; public function __construct($host, $db, $user, $pass, $sphinx = false, $port = null, $PostgreSQL=false, $opt = array(), $charset = null){ $this->host = $host; $this->db = $db; $this->user = $user; $this->pass = $pass; if(!empty($opt)) { $this->opt = $opt; } if($charset){ $this->charset = $charset; } if($sphinx){ $this->sphinx = $sphinx; } if($PostgreSQL){ $this->PostgreSQL = $PostgreSQL; } if($port){ $this->port = $port; } $this->pdo = $this->connect(); self::$instance = $this; } // Кэш недоступности PG-хостов в рамках одного PHP-запроса. // Чтобы не делать fsockopen-чек повторно для одного и того же хоста (экономит 2 сек на каждом повторе). private static $pg_unreachable_cache = array(); //Подключение private function connect(){ $dsn = "mysql:host=".$this->host.";port=".$this->port.";dbname=".$this->db; if($this->sphinx){ $dsn = "mysql:host=".$this->host.";port=".$this->port; } else if ($this->PostgreSQL){ $dsn = "pgsql:host=".$this->host.";port=".$this->port; // Быстрая проверка доступности PG-хоста (2 сек таймаут). // Без этой проверки PDO-connect может висеть 30-60 секунд при недоступном хосте, // что валит весь кабинет на окружениях без PG (например, dev). // На проде PG доступен — проверка мгновенна. На dev — 2 сек на первый раз, потом 0 сек. $cacheKey = $this->host . ':' . $this->port; if (isset(self::$pg_unreachable_cache[$cacheKey])) { // Не логируем — про этот хост в текущем запросе уже отписались. throw new RuntimeException(self::$pg_unreachable_cache[$cacheKey]); } $sock = @fsockopen($this->host, (int)$this->port, $errno, $errstr, 2); if (!$sock) { $msg = "PostgreSQL unreachable at {$this->host}:{$this->port} ({$errno}: {$errstr})"; self::$pg_unreachable_cache[$cacheKey] = $msg; // Пишем ОДИН раз в php error_log при первом обнаружении недоступности в текущем запросе. // На проде это видно в стандартном error_log сервера и поможет быстро поймать момент отказа PG. $reqUri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'cli'; @error_log("[MysqlPdo] {$msg} | request: {$reqUri}"); throw new RuntimeException($msg); } fclose($sock); } try { $pdo = null; if($this->sphinx){ $pdo = new PDO($dsn); } else { $pdo = new PDO($dsn, $this->user, $this->pass, $this->opt); } return $pdo; } catch (PDOException $e) { // Для MySQL/Sphinx без БД приложение работать не может — die как и было. // Для PG нас сюда не должны пускать (fsockopen-check выше уже отсёк), // но на всякий случай — бросаем исключение, не die. if ($this->PostgreSQL) { throw new RuntimeException('PostgreSQL connection failed: ' . $e->getMessage()); } die('Ooooops что-то пошло не так. Мы уже работаем над проблемой.'); } } //mysql_query public function query($query, $error = false){ $stmt = null; try{ $stmt = $this->pdo->query($query); } catch (Exception $e){ print_r($query); print_r($e->getMessage()); } if(!$stmt && $error){ print_r($query); print_r($this->pdo->errorInfo()); } return $stmt; } //mysql_query with named params public function queryNamed($query, $params){ $statement = $this->pdo->prepare($query); $statement->execute($params); return $statement; } //mysql_fetch_assoc public function fetch_assoc($stmt){ if (!$stmt || !($stmt instanceof PDOStatement)) { return null; } $row = $stmt->fetch(PDO::FETCH_ASSOC); return $row; } //mysql_num_rows public function num_rows($stmt){ if (!$stmt || !($stmt instanceof PDOStatement)) { return 0; } $rows = $stmt->rowCount(); return $rows; } //mysql_result public function result_pdo($stmt){ if (!$stmt || !($stmt instanceof PDOStatement)) { return []; } $res = $stmt->fetchAll(PDO::FETCH_ASSOC); return $res; } public function result($stmt, $column = 0){ if (!$stmt || !($stmt instanceof PDOStatement)) { return null; } $res = $stmt->fetchColumn($column); return $res; } //mysql_fetch_row function fetch_row($stmt){ if (!$stmt || !($stmt instanceof PDOStatement)) { return null; } $row = $stmt->fetch(PDO::FETCH_NUM); return $row; } //mysql_insert_id function insert_id(){ $id = $this->pdo->lastInsertId(); return $id; } //mysql_error function error(){ return $this->pdo->errorInfo(); } //mysql_error function quote($str){ return $this->pdo->quote($str); } static function get() { return self::$instance; } public function errorInfo() { return $this->pdo->errorInfo(); } }