Joywork/engine/classes/MysqlPdo.php
2026-05-22 21:21:54 +03:00

204 lines
6.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Класс для работы с базой mysql по средствам PDO
*/
Class MysqlPdo{
private static $instance;
private $pdo;
private $opt = [
PDO::ATTR_ERRMODE => 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();
}
}