Ошибки и их обработка
PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего
стиля разработки приложений.
-
PDO::ERRMODE_SILENT
До PHP 8.0.0, это был режим по умолчанию. PDO просто предоставит вам код ошибки, который
можно получить методами PDO::errorCode() и
PDO::errorInfo(). Эти методы реализованы как в объектах
запросов, так и в объектах баз данных. Если ошибка вызвана во время выполнения
кода объекта запроса, нужно вызвать метод
PDOStatement::errorCode() или
PDOStatement::errorInfo() этого объекта. Если ошибка
вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта. -
PDO::ERRMODE_WARNING
Помимо установки кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может
быть полезно при отладке или тестировании, когда нужно видеть, что произошло,
но не нужно прерывать работу приложения. -
PDO::ERRMODE_EXCEPTION
Начиная с PHP 8.0.0 является режимом по умолчанию. Помимо задания кода ошибки PDO будет выбрасывать исключение
PDOException, свойства которого будут отражать
код ошибки и её описание. Этот режим также полезен при отладке, так как
сразу известно, где в программе произошла ошибка. Это позволяет быстро
локализовать и решить проблему. (Не забывайте, что если исключение
является причиной завершения работы скрипта, все активные транзакции
будут откачены.)Режим исключений также полезен, так как даёт возможность структурировать
обработку ошибок более тщательно, нежели с обычными предупреждениями PHP, а
также с меньшей вложенностью кода, чем в случае работы в тихом режиме с
явной проверкой возвращаемых значений при каждом обращении к базе данных.Подробнее об исключениях в PHP смотрите в разделе Исключения.
PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE.
Отдельные драйверы PDO могут задавать соответствия своих собственных кодов
кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный
код SQLSTATE. Если необходима специфичная информация об ошибке, PDO предлагает
метод PDO::errorInfo(), который возвращает массив, содержащий
код SQLSTATE, код ошибки драйвера, а также строку ошибки драйвера.
Пример #1 Создание PDO объекта и установка режима обработки ошибок
<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// PDO выбросит исключение PDOException (если таблица не существует)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>
Результат выполнения данного примера:
Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'testdb.wrongtable' doesn't exist in /tmp/pdo_test.php:10 Stack trace: #0 /tmp/pdo_test.php(10): PDO->query('SELECT wrongcol...') #1 {main} thrown in /tmp/pdo_test.php on line 10
Замечание:
Метод PDO::__construct() будет всегда бросать исключение PDOException,
если соединение оборвалось, независимо от установленного значенияPDO::ATTR_ERRMODE
.
Пример #2 Создание экземпляра класса PDO и установка режима обработки ошибок в конструкторе
<?php
$dsn = 'mysql:dbname=test;host=127.0.0.1';
$user = 'googleguy';
$password = 'googleguy';$dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>
Результат выполнения данного примера:
Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in /tmp/pdo_test.php on line 9
There are no user contributed notes for this page.
Содержание
- Connections and Connection management
- Ошибки и их обработка
- Ошибки и их обработка
- PDO::errorCode
- Описание
- Список параметров
- Возвращаемые значения
- Примеры
- Смотрите также
- PDO::errorInfo
- Description
- Parameters
- Return Values
- Examples
- See Also
- User Contributed Notes 3 notes
Connections and Connection management
Connections are established by creating instances of the PDO base class. It doesn’t matter which driver you want to use; you always use the PDO class name. The constructor accepts parameters for specifying the database source (known as the DSN) and optionally for the username and password (if any).
Example #1 Connecting to MySQL
If there are any connection errors, a PDOException object will be thrown. You may catch the exception if you want to handle the error condition, or you may opt to leave it for an application global exception handler that you set up via set_exception_handler() .
Example #2 Handling connection errors
If your application does not catch the exception thrown from the PDO constructor, the default action taken by the zend engine is to terminate the script and display a back trace. This back trace will likely reveal the full database connection details, including the username and password. It is your responsibility to catch this exception, either explicitly (via a catch statement) or implicitly via set_exception_handler() .
Upon successful connection to the database, an instance of the PDO class is returned to your script. The connection remains active for the lifetime of that PDO object. To close the connection, you need to destroy the object by ensuring that all remaining references to it are deleted—you do this by assigning null to the variable that holds the object. If you don’t do this explicitly, PHP will automatically close the connection when your script ends.
Note: If there are still other references to this PDO instance (such as from a PDOStatement instance, or from other variables referencing the same PDO instance), these have to be removed also (for instance, by assigning null to the variable that references the PDOStatement).
Example #3 Closing a connection
= new PDO ( ‘mysql:host=localhost;dbname=test’ , $user , $pass );
// use the connection here
$sth = $dbh -> query ( ‘SELECT * FROM foo’ );
// and now we’re done; close it
$sth = null ;
$dbh = null ;
?>
Many web applications will benefit from making persistent connections to database servers. Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials. The persistent connection cache allows you to avoid the overhead of establishing a new connection every time a script needs to talk to a database, resulting in a faster web application.
Example #4 Persistent connections
The value of the PDO::ATTR_PERSISTENT option is converted to bool (enable/disable persistent connections), unless it is a non-numeric string , in which case it allows to use multiple persistent connection pools. This is useful if different connections use incompatible settings, for instance, different values of PDO::MYSQL_ATTR_USE_BUFFERED_QUERY .
If you wish to use persistent connections, you must set PDO::ATTR_PERSISTENT in the array of driver options passed to the PDO constructor. If setting this attribute with PDO::setAttribute() after instantiation of the object, the driver will not use persistent connections.
If you’re using the PDO ODBC driver and your ODBC libraries support ODBC Connection Pooling (unixODBC and Windows are two that do; there may be more), then it’s recommended that you don’t use persistent PDO connections, and instead leave the connection caching to the ODBC Connection Pooling layer. The ODBC Connection Pool is shared with other modules in the process; if PDO is told to cache the connection, then that connection would never be returned to the ODBC connection pool, resulting in additional connections being created to service those other modules.
Источник
Ошибки и их обработка
PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего стиля разработки приложений.
PDO::ERRMODE_SILENT
Это режим по умолчанию. PDO просто предоставит вам код ошибки, который можно получить методами PDO::errorCode() и PDO::errorInfo() . Эти методы реализованы как в объектах запросов так и в объектах баз данных. Если ошибка вызвана во время выполнения кода объекта запроса, нужно вызвать метод PDOStatement::errorCode() или PDOStatement::errorInfo() этого объекта. Если ошибка вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта.
PDO::ERRMODE_WARNING
Помимо задания кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может быть полезно при отладке или тестировании, когда нужно видеть, что произошло, но не нужно прерывать работу приложения.
PDO::ERRMODE_EXCEPTION
Помимо задания кода ошибки PDO будет выбрасывать исключение PDOException, свойства которого будут отражать код ошибки и ее описание. Этот режим также полезен при отладке, так как сразу известно, где в программе произошла ошибка. Это позволяет быстро локализовать и решить проблему. (Не забывайте, что если исключение является причиной завершения работы скрипта, все активные транзакции будут откачены.)
Режим исключений также полезен, так как дает возможность структурировать обработку ошибок более тщательно, нежели с обычными PHP предупреждениями, а также с меньшей вложенностью кода, чем в случае работы в тихом режиме с явной проверкой возвращаемых значений при каждом обращении к базе данных.
Подробнее об исключениях в PHP см. в разделе Исключения.
PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE. Отдельные PDO драйверы могут задавать соответствия своих собственных кодов кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный SQLSTATE код. Если необходима специфичная информация об ошибке, PDO предлагает метод PDO::errorInfo() , который возвращает массив, содержащий SQLSTATE код, код ошибки драйвера, а также строку ошибки драйвера.
Пример #1 Создание PDO объекта и задание режима обработки ошибок
= ‘mysql:dbname=testdb;host=127.0.0.1’ ;
$user = ‘dbuser’ ;
$password = ‘dbpass’ ;
try <
$dbh = new PDO ( $dsn , $user , $password );
$dbh -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );
> catch ( PDOException $e ) <
echo ‘Подключение не удалось: ‘ . $e -> getMessage ();
>
Метод PDO::__construct() будет всегда бросать исключение PDOException, если соединение оборвалось, независимо от установленного значения PDO::ATTR_ERRMODE . Непойманные исключения фатальны.
Пример #2 Создание экземпляра класса PDO и задание режима обработки ошибок в конструкторе
= ‘mysql:dbname=test;host=127.0.0.1’ ;
$user = ‘googleguy’ ;
$password = ‘googleguy’ ;
/*
По прежнему оберните конструктор в блок try/catch, так как, даже при установке ERRMODE в WARNING,
PDO::__construct всегда будет бросать исключение PDOException, если соединение оборвалось.
*/
try <
$dbh = new PDO ( $dsn , $user , $password , array( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_WARNING ));
> catch ( PDOException $e ) <
echo ‘Соединение оборвалось: ‘ . $e -> getMessage ();
exit;
>
// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh -> query ( «SELECT wrongcolumn FROM wrongtable» );
?>
Источник
Ошибки и их обработка
PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего стиля разработки приложений.
PDO::ERRMODE_SILENT
До PHP 8.0.0, это был режим по умолчанию. PDO просто предоставит вам код ошибки, который можно получить методами PDO::errorCode() и PDO::errorInfo() . Эти методы реализованы как в объектах запросов, так и в объектах баз данных. Если ошибка вызвана во время выполнения кода объекта запроса, нужно вызвать метод PDOStatement::errorCode() или PDOStatement::errorInfo() этого объекта. Если ошибка вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта.
PDO::ERRMODE_WARNING
Помимо установки кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может быть полезно при отладке или тестировании, когда нужно видеть, что произошло, но не нужно прерывать работу приложения.
PDO::ERRMODE_EXCEPTION
Начиная с PHP 8.0.0 является режимом по умолчанию. Помимо задания кода ошибки PDO будет выбрасывать исключение PDOException , свойства которого будут отражать код ошибки и её описание. Этот режим также полезен при отладке, так как сразу известно, где в программе произошла ошибка. Это позволяет быстро локализовать и решить проблему. (Не забывайте, что если исключение является причиной завершения работы скрипта, все активные транзакции будут откачены.)
Режим исключений также полезен, так как даёт возможность структурировать обработку ошибок более тщательно, нежели с обычными предупреждениями PHP, а также с меньшей вложенностью кода, чем в случае работы в тихом режиме с явной проверкой возвращаемых значений при каждом обращении к базе данных.
Подробнее об исключениях в PHP смотрите в разделе Исключения.
PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE. Отдельные драйверы PDO могут задавать соответствия своих собственных кодов кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный код SQLSTATE. Если необходима специфичная информация об ошибке, PDO предлагает метод PDO::errorInfo() , который возвращает массив, содержащий код SQLSTATE, код ошибки драйвера, а также строку ошибки драйвера.
Пример #1 Создание PDO объекта и установка режима обработки ошибок
= ‘mysql:dbname=testdb;host=127.0.0.1’ ;
$user = ‘dbuser’ ;
$password = ‘dbpass’ ;
$dbh = new PDO ( $dsn , $user , $password );
$dbh -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );
// PDO выбросит исключение PDOException (если таблица не существует)
$dbh -> query ( «SELECT wrongcolumn FROM wrongtable» );
?>
Результат выполнения данного примера:
Метод PDO::__construct() будет всегда бросать исключение PDOException , если соединение оборвалось, независимо от установленного значения PDO::ATTR_ERRMODE .
Пример #2 Создание экземпляра класса PDO и установка режима обработки ошибок в конструкторе
= ‘mysql:dbname=test;host=127.0.0.1’ ;
$user = ‘googleguy’ ;
$password = ‘googleguy’ ;
$dbh = new PDO ( $dsn , $user , $password , array( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_WARNING ));
// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh -> query ( «SELECT wrongcolumn FROM wrongtable» );
?>
Источник
PDO::errorCode
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)
PDO::errorCode — Возвращает код SQLSTATE результата последней операции с базой данных
Описание
Список параметров
У этой функции нет параметров.
Возвращаемые значения
Возвращает SQLSTATE — пятисимвольный идентификатор, определённый в стандарте ANSI SQL-92. Первые два символа SQLSTATE отвечают за класс ошибки, а следующие три определяют её подкласс. Класс ошибок 01 означает предупреждение, которому сопутствует возвращаемый код SQL_SUCCESS_WITH_INFO. Классы отличные от 01, за исключением ‘IM’, означают ошибки выполнения запросов к базе данных. Класс ‘IM’ свидетельствует об ошибках и предупреждениях, которые вызваны самой реализацией PDO (или, возможно, ODBC, если используется драйвер ODBC). Значение подкласса ‘000’ в любом классе означает, что подкласс для этого SQLSTATE отсутствует.
PDO::errorCode() выдаёт код ошибки только для операций, совершаемых с базой данных напрямую из PDO. Если создать объект PDOStatement методами PDO::prepare() или PDO::query() , и вызвать ошибку его методами, PDO::errorCode() эту ошибку не отобразит. Вам нужно вызвать PDOStatement::errorCode() , чтобы получить код ошибки для операции, выполняемой на определённом объекте PDOStatement.
Возвращает null , если никаких операций над базой данных средствами PDO-объекта не производилось.
Примеры
Пример #1 Получение кода SQLSTATE
/* Спровоцируем ошибку — таблицы BONES не существует */
$dbh -> exec ( «INSERT INTO bones(skull) VALUES (‘lucy’)» );
echo «nPDO::errorCode(): » , $dbh -> errorCode ();
?>
Результат выполнения данного примера:
Смотрите также
- PDO::errorInfo() — Получает расширенную информацию об ошибке, произошедшей в ходе последнего обращения к базе данных
- PDOStatement::errorCode() — Получает код SQLSTATE, связанный с последней операцией в объекте PDOStatement
- PDOStatement::errorInfo() — Получение расширенной информации об ошибке, произошедшей в результате работы объекта PDOStatement
Источник
PDO::errorInfo
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)
PDO::errorInfo — Fetch extended error information associated with the last operation on the database handle
Description
Parameters
This function has no parameters.
Return Values
PDO::errorInfo() returns an array of error information about the last operation performed by this database handle. The array consists of at least the following fields:
Element | Information |
---|---|
SQLSTATE error code (a five characters alphanumeric identifier defined in the ANSI SQL standard). | |
1 | Driver-specific error code. |
2 | Driver-specific error message. |
If the SQLSTATE error code is not set or there is no driver-specific error, the elements following element 0 will be set to null .
PDO::errorInfo() only retrieves error information for operations performed directly on the database handle. If you create a PDOStatement object through PDO::prepare() or PDO::query() and invoke an error on the statement handle, PDO::errorInfo() will not reflect the error from the statement handle. You must call PDOStatement::errorInfo() to return the error information for an operation performed on a particular statement handle.
Examples
Example #1 Displaying errorInfo() fields for a PDO_ODBC connection to a DB2 database
The above example will output:
See Also
- PDO::errorCode() — Fetch the SQLSTATE associated with the last operation on the database handle
- PDOStatement::errorCode() — Fetch the SQLSTATE associated with the last operation on the statement handle
- PDOStatement::errorInfo() — Fetch extended error information associated with the last operation on the statement handle
User Contributed Notes 3 notes
Please note : that this example won’t work if PDO::ATTR_EMULATE_PREPARES is true.
You should set it to false
-> setAttribute ( PDO :: ATTR_EMULATE_PREPARES , false );
$stmt = $dbh -> prepare ( ‘bogus sql’ );
if (! $stmt ) <
echo «nPDO::errorInfo():n» ;
print_r ( $dbh -> errorInfo ());
>
?>
here are the error codes for sqlite, straight from their site:
The error codes for SQLite version 3 are unchanged from version 2. They are as follows:
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
Some PDO drivers return a larger array. For example, the SQL Server driver returns 5 values.
For example:
= $db -> exec ( «DELETE FROM [TableName] WHERE ID between 6 and 17» );
print_r ( $db -> errorInfo ());
?>
Result:
Array
(
[0] => 00000
[1] => 0
[2] => (null) [0] (severity 0) []
[3] => 0
[4] => 0
)
Источник
Home / Handling errors when connecting to a database using PHP PDO
PHP’s PDO database abstraction class offers a better way to connect to databases than the mysql_* etc style functions, or using a 3rd party database library. This post looks at handle errors when connecting and a follow up post later this week will look at how to check for errors when running individual queries after a connection has been successfully established.
How to connect to the database
Everything in this post is covered in the PHP manual but I’m adding a few extra notes here about what to look for when connecting and what the default behaviors are. The way to connect to a database with PDO is like so:
$pdo = new PDO($dsn, $username, $password);
$dsn takes the form along the lines of this: «mysql:host=[HOSTNAME];dbname=[DATABASE NAME]» by subsituting the correct host and database. The dsn options aren’t that well explained or covered in the PHP manual (at least I haven’t been able to find concise documentation) so I may do a follow up post looking at the dsn options as well.
Wrap the attempt to connect within a try..catch block
If the database connection could not be established then it will silently fail and no error message will be displayed. The PHP script will also continue to run. This is not at all desirable so it is important to always wrap a PDO connection within a try..catch block like so:
try { $pdo = new PDO($dsn, $username, $password); } catch(PDOException $e) { // do some error handling here e.g.: // - display message to the user // - send an email to the webmaster // - log the error // and finally: exit; }
Getting the error message
The PDO class has a couple of error code functions: errorCode() and errorInfo() but these are not accessible if the connection could not be established. Instead, using the PDOException object’s getCode(), getMessage() etc methods. Read my earlier «PHP Exceptions – available information» post for more details about the types of information available.
From my own testing, $e->getCode() always appears to return 0 so it’s $e->getMessage that you will need to use for reporting or emailing to the webmaster. For example:
try { $pdo = new PDO($dsn, $username, $password); } catch(PDOException $e) { mail('webmaster@example.com', 'Database error message', $e->getMessage()); // now output some message to the user // and finally... exit; }
Example error messages include:
- SQLSTATE[HY000] [2005] Unknown MySQL server host ‘fakehost’ (1)
- SQLSTATE[42000] [1049] Unknown database ‘fakedb’
- SQLSTATE[28000] [1045] Access denied for user ‘fakeuser’@’localhost’ (using password: YES)
Conclusion and future posts
This should be everything you need to deal with catching errors when attempting to connect to the database using PDO. In future posts I’ll look at more of the options available for the DSN and looking for errors when running SQL queries.
Summary: in this tutorial, you’ll learn step by step how to connect to a MySQL database from PHP using PDO.
Prerequisites
Before connecting to a MySQL database server, you need to have:
- A MySQL database server, a database, and an account that has access to the database.
- PDO MySQL driver enabled in the php.ini file
1) Setting MySQL database parameters
Suppose you have a local MySQL database server that has the following information:
- The host is
localhost
. - The
bookdb
database on the local database server. - The account with the user
root
and password'S@cr@t1!'
that can access thebookdb
database.
In PHP, you can create a config.php
file and place the database parameters:
Code language: HTML, XML (xml)
<?php $host = 'localhost'; $db = 'bookdb'; $user = 'root'; $password = 'S@cr@t1!';
To use the database parameters, you can include the config.php
file using the require
construct:
Code language: HTML, XML (xml)
<?php require 'config.php';
2) Enable PDO_MySQL Driver
PDO_MYSQL is a driver that implements the PDO interface. PDO uses the PDO_MYSQL driver to connect to a MySQL database.
To check if the PDO_MYSQL driver is enabled, you open the php.ini
file. The php.ini
file is often located under the php
directory. For example, you can find the php.ini
file under the C:xamppphp
directory if you use XAMPP
on Windows.
The following shows the extension line in the php.ini
file:
;extension=php_pdo_mysql.dll
To enable the extension, you need to uncomment it by removing the semicolon (;
) from the beginning of the line like this:
extension=php_pdo_mysql.dll
After that, you need to restart the web server for the change to take effect.
MySQL data source name
PDO uses a data source name (DSN) that contains the following information:
- The database server host
- The database name
- The user
- The password
- and other parameters such as character sets, etc.
PDO uses this information to make a connection to the database server. To connect to the MySQL database server, you use the following data source name format:
Code language: JSON / JSON with Comments (json)
"mysql:host=host_name;dbname=db_name;charset=UTF8"
For example:
Code language: PHP (php)
$dsn = "mysql:host=localhost;dbname=bookdb;charset=UTF8";
Note that the charset UTF-8 sets the character set of the database connection to UTF-8.
The following index.php
script illustrates how to connect to the bookdb
database on the MySQL database server with the root
account:
Code language: HTML, XML (xml)
<?php require 'config.php'; $dsn = "mysql:host=$host;dbname=$db;charset=UTF8"; try { $pdo = new PDO($dsn, $user, $password); if ($pdo) { echo "Connected to the $db database successfully!"; } } catch (PDOException $e) { echo $e->getMessage(); }
How it works.
- First, create a new PDO object with the data source name, user, and password. The PDO object is an instance of the
PDO
class. - Second, show the success message if the connection is established successfully or an error message if an error occurs.
If you have everything set up correctly, you will see the following message:
Code language: plaintext (plaintext)
Connected to the bookdb database successfully!
Error handling strategies
PDO supports three different error handling strategies:
PDO::ERROR_SILENT
– PDO sets an error code for inspecting using thePDO::errorCode()
andPDO::errorInfo()
methods. ThePDO::ERROR_SILENT
is the default mode.PDO::ERRMODE_WARNING
– Besides setting the error code, PDO will issue anE_WARNING
message.PDO::ERRMODE_EXCEPTION
– Besides setting the error code, PDO will raise aPDOException
.
To set the error handling strategy, you can pass an associative array to the PDO constructor like this:
Code language: PHP (php)
$pdo = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
Or you can use the setAttribute()
method of the PDO instance:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Code language: PHP (php)
Troubleshooting
There are some common issues when you connect to a MySQL database:
If the MySQL driver is not enabled in the php.ini
file, you will get the error message:
Code language: plaintext (plaintext)
could not find driver
If you provide an incorrect password, you get the following error message:
Code language: plaintext (plaintext)
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)
If you provide an invalid database name or the database does not exist, you get the following error message:
Code language: plaintext (plaintext)
SQLSTATE[HY000] [1049] Unknown database 'bookdb'
If you provide an invalid database hostname, the following error message will display:
Code language: plaintext (plaintext)
SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: No such host is known.
Summary
- Enable the
PDO_MYSQL
driver in thephp.ini
file for connecting to a MySQL database from PHP PDO. - Create an instance of the PDO class to make a connection to a MySQL database.
- Use the PDO constructor or the
setAttribute()
method to set an error handling strategy.
Did you find this tutorial useful?
This is a tutorial on how to connect to a MySQL database using PHP.
Here, we hope to provide a simple explanation about the functions that are used and the connection details that are required.
There are three main parameters that you need to understand.
- Server / Host: This is the location of the database server. In most cases, this is referred to as the host. Basically, it is like a URL to your database. On your local machine, it will probably be “localhost”. On your web host, it might be something such as “mysql38.example.com”.
- User: The username of the MySQL user that you want to connect as.
- Password: The password of the MySQL user that you want to connect as.
When connecting to a MySQL server, you will need to provide these three details.
mysql_connect
Although the mysql_* functions are deprecated, I felt as though I couldn’t exclude them from this tutorial. Using the function mysql_connect, we can connect to MySQL like so.
//Our server/host parameter. $server = 'localhost'; //Our MySQL username. $user = 'root'; //Our MySQL password. $password = '123456'; //Attempt to connect. $connection = mysql_connect($server, $user, $password); //Check if we are connected. if($connection === false){ echo 'Failed to connect!'; } else{ echo 'We are connected!'; }
Note that you will obviously need to use the connection details that are relevant to your database server. In many cases, a local MySQL installation will have the following default details.
- Server: localhost
- User: root
- Password: *blank* Most default MySQL installations have a blank password by default. In these cases, we have to supply an empty string. If we attempt to supply a password when there is no password, then we will receive the following error: “Access denied for user ‘root’@’localhost’ (using password: YES)”.
If you are using a default account on a local installation, then your connection code will probably look like this.
$connection = mysql_connect('localhost', 'root', '');
Note that if a connection fails, the mysql_connect function will return a boolean FALSE value. However, if the connection is successful, then it will return a MySQL connection resource that can be used to query the database.
Selecting the database.
Before you can run any SQL queries on your tables, you will need to do two things.
- Connect to MySQL (already covered above).
- Select a database.
Remember that you can have multiple databases on the same MySQL server. Hence the reason that we must select a database before attempting to run any SQL queries on our tables.
An example of connecting to MySQL and selecting a database with PHP.
//Connect to the MySQL server. $connection = mysql_connect('localhost', 'root', ''); //Select our database. mysql_select_db('our_database_name', $connection); //Run our SQL queries.
Using the function mysql_select_db, we were able to select our database AFTER connecting to MySQL. The process will always be the same:
- Connect to the server.
- Select your database.
- Query your tables.
A lot of beginners struggle to grasp this, simply because many tutorials toss them straight into the deep end without explaining the basic steps that need to be taken.
PDO.
As we mentioned above, the mysql_* functions are deprecated. This means that you should not use them to build new web applications. Instead, you should use something like the PDO object.
$user = 'root'; $password = 'super_secret_password'; $pdo = new PDO('mysql:host=localhost;dbname=our_db', $user, $password);
If you look closely, you’ll see that we are using the same parameters.
We have our server (aka, the host), which is ‘localhost’. We have our username, which is ‘root’. And then we have our password, which is ‘super_secret_password’.
Note how you can also supply a parameter called dbname. This means that we can connect to our MySQL server and select our database in one line of code.
Let’s connect using the default MySQL details.
//Our MySQL user account. $user = 'root'; //Our MySQL password. $password = ''; //The server / hostname of MySQL. $server = 'localhost'; //The name of our database. $database = 'my_database'; //Connect using PDO. $pdo = new PDO("mysql:host=$server;dbname=$database", $user, $password); //Run SQL queries on our tables.
Hopefully, separating the details onto different lines has made it a bit clearer! Feel free to use the code above; inserting your own details where needed.
PHP won’t connect to MySQL.
This can be a frustrating issue. Thankfully, there are ways to debug our connection issues. The first order of business is to check for connection errors. How you catch these errors depends on which library you are using.
PDO connection error.
Detecting connection errors w/ PDO is pretty straight-forward, as the library allows you to throw exceptions.
//Our connection details. $host = 'localhost'; $user = 'root'; $password = ''; $database = 'test'; //An options array. //Set the error mode to "exceptions" $pdoOptions = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false ); //Connect $pdo = new PDO("mysql:host=$host;dbname=$database", $user, $password, $pdoOptions);
If you fail to connect for whatever reason, the code snippet above will throw an exception error. Some common examples:
Uncaught exception ‘PDOException’ with message ‘SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: No such host is known. ‘
This occurs when you have entered an incorrect host name / server name.
Uncaught exception ‘PDOException’ with message ‘SQLSTATE[HY000] [1045] Access denied for user ‘root’@’localhost’ (using password: YES)’
This occurs when you use the wrong password (or you enter a password, even though the account in question doesn’t have one).
Uncaught exception ‘PDOException’ with message ‘SQLSTATE[HY000] [1049] Unknown database ‘blah”
This one is pretty straightforward. Basically, the database “blah” does not exist.
mysql_connect connection error.
Here’s an example of error-checking with the mysql_* functions.
//Our connection details. $host = 'localhost'; $user = 'root'; $password = ''; $database = 'test'; //Connect to MySQL. $conn = mysql_connect($host, $user, $password); if($conn === false){ throw new Exception(mysql_error()); } //Select our database. $selectDb = mysql_select_db($database, $conn); if($selectDb === false){ throw new Exception(mysql_error($conn)); }
If you purposely use incorrect details (for testing purposes), you’ll see that the errors are relatively the same as the ones that are thrown while using the PDO object.
Querying MySQL.
Follow-on tutorials on how to query MySQL with PHP:
- Inserting rows into MySQL with the PDO object.
- Selecting rows from a MySQL database.
- Multi-inserts with the PDO object.
- Updating MySQL with prepared statements.
- Deleting database rows with the PDO object.
Практическая часть использования PDO API для работы с базой данных.
Что?
Для соединения с базой данных MySQL имеется три разных API:
mysql
mysqli
– MySQL Improved (улучшенная)pdo
– PHP Data Objects (объекты данных PHP)
Традиционный API mysql
хорошо выполняет свою работу и получил широкое распространение благодаря тому, что делает процесс получения записей из базы данных очень простым. Например:
/* * Демонстрация старого способа работы с базой данных MySQL */ # Соединение mysql_connect('localhost', 'username', 'password') or die('Could not connect: ' . mysql_error()); # Выбор базы данных mysql_select_db('someDatabase') or die('Не могу выбрать базу данных'); # Выполнение запроса $query = "SELECT * from someTable"; $result = mysql_query($query) or die('Query failed: ' . mysql_error()); # Фильтрация строк и вывод нужной информации while ($row = mysql_fetch_object($result)) { echo $row->name; }
Да, приведенный пример очень прост. Но у него есть существенные недостатки:
- Устарел: хотя официально его не признают устаревшим, но для новых приложений и обучения лучше использовать другие API.
- Очистка: процесс очистки ввода пользователя от ненужного кода ложится на плечи разработчика.
- Гибкость: данный API не гибкий и работает только с базой данных MySQL. А если нужно перейти на другую?
PDO (PHP Data Objects) предоставляет более мощный инструмент для использования. Не нужно думать о драйвере базы данных, можно использовать подготовленные выражения, исключаются инъекции кода SQL.
Как?
На первый взгляд PDO API выглядит устрашающе. Не потому что он чрезмерно сложен, а потому что mysql
является очень простым! Нужно просто сделать несколько несложных действий.
Соединение
Вы уже знаете устаревший способ соединения с базой данной MySQL:
# Соединение mysql_connect('localhost', 'username', 'password') or die('Could not connect: ' . mysql_error());
При работе с PDO нужно создать новый экземпляр класса, указать драйвер, имя базы данных, имя пользователя и пароль:
$conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
Ничего сложного.
Преимуществом данного подхода является простота изменения базы данных. Достаточно поменять имя источника данных. Нет зависимости от MySQL как при использовании функции mysql_connect
.
Ошибки
Но что если произойдет ошибка при соединении с базой данных? Обернем все в блок try/catch
:
try { $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { echo 'ERROR: ' . $e->getMessage(); }
Обратите внимание на то, что по умолчанию для PDO установлен режим работы с ошибками PDO::ERRMODE_SILENT
. Если все оставить без изменении, то придется вручную обрабатывать ошибки после выполнения запроса.
echo $conn->errorCode(); echo $conn->errorInfo();
При разработке лучше устанавливать режим PDO::ERRMODE_EXCEPTION
, в котором необработанные ошибки будут вызывать исключения и остановку скрипта.
Доступны следующие режимы работы с ошибками:
PDO::ERRMODE_SILENT
PDO::ERRMODE_WARNING
PDO::ERRMODE_EXCEPTION
Получаем данные
Итак, у нас есть соединение с базой данных и теперь нужно получить данные. Есть два способа решить поставленную задачу: query
и execute
. Рассмотрим оба.
Query
/* * Метод query */ $name = 'Joe'; # user-supplied data try { $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $data = $conn->query('SELECT * FROM myTable WHERE name = ' . $conn->quote($name)); foreach($data as $row) { print_r($row); } } catch(PDOException $e) { echo 'ERROR: ' . $e->getMessage(); }
Хотя выше приведенный пример будет работать, нам нужно вручную очищать данные пользователя с помощью метода PDO::quote
. Данный метод эквивалентен функции mysql_real_escape_string
(в обоих случаях строка очищается и заключается в кавычки). В случаях, когда нужно построить запрос SQL с использованием пользовательских данных, лучше применять подготовленные выражения. То есть, если запрос SQL не зависит от ввода пользователя, метод query
будет отличным выбором, а результат можно обработать выражением foreach
.
Execute
/* * Метод execute */ $id = 5; try { $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id'); $stmt->execute(array('id' => $id)); while($row = $stmt->fetch()) { print_r($row); } } catch(PDOException $e) { echo 'ERROR: ' . $e->getMessage(); }
В данном примере используется также метод prepare
для подготовки запроса, перед тем, как присоединить данные пользователя. В таком случае инъекция SQL теоретически невозможна, так как сами данные не вставляются в текст запроса SQL. Используется именованный параметр (:id
) для обозначения места.
Затем выполняется запрос с передачей массива, который содержит данные, которые следует использовать на месте именованного параметра.
$stmt->execute(array('id' => $id));
В качестве альтернативы можно использовать метод bindParam
:
$stmt->bindParam(':id', $id, PDO::PARAM_INT); $stmt->execute();
Обрабатываем данные
После вызова метода execute
есть несколько способов получить данные: массив (по умолчанию), объект и так далее. В выше приведенном примере используется режим по умолчанию: PDO::FETCH_ASSOC
. Его легко поменять, если нужно:
while($row = $stmt->fetch(PDO::FETCH_OBJ)) { print_r($row); }
Теперь результат будет в виде объекта. Доступны следующие опции:
- PDO::FETCH_ASSOC: Возвращает массив.
- PDO::FETCH_BOTH: Возвращает массив, проиндексированный по колонке с именем.
- PDO::FETCH_BOUND: Возвращает TRUE и назначает значение столбцов в наборе результата связанным переменным PHP.
- PDO::FETCH_CLASS: Возвращает новый экземпляр указанного класса.
- PDO::FETCH_OBJ: Возвращает анонимный объект, с именами свойств, соответствующих столбцам.
Выше приведенный код не имеет обратной связи на случай отсутствия результата. Исправим ситуацию:
$stmt->execute(array('id' => $id)); # Получаем массив, который содержит все строки результата $result = $stmt->fetchAll(); # Если получена одна или более строк... if ( count($result) ) { foreach($result as $row) { print_r($row); } } else { echo "Ничего не найдено."; }
Полный код будет выглядеть следующим образом:
$id = 5; try { $conn = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id'); $stmt->execute(array('id' => $id)); $result = $stmt->fetchAll(); if ( count($result) ) { foreach($result as $row) { print_r($row); } } else { echo "Ничего не найдено."; } } catch(PDOException $e) { echo 'ERROR: ' . $e->getMessage(); }
Многократное выполнение
PDO проявляет свою силу в случаях, когда надо выполнить один и тот же запрос SQL несколько раз, но с разными параметрами.
try { $conn = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); # Подготавливаем запрос один раз $stmt = $conn->prepare('INSERT INTO someTable VALUES(:name)'); $stmt->bindParam(':name', $name); # Первое выполнение $name = 'Keith'; $stmt->execute(); # Второе выполнение $name = 'Steven'; $stmt->execute(); } catch(PDOException $e) { echo $e->getMessage(); }
Как только запрос подготовлен, его можно выполнить несколько раз с разными параметрами. Выше приведенный код вставляет две строки в базу данных: одна с именем “Kevin,” а другая — “Steven.”
Типовые операции с базой данных (CRUD)
Рассмотрим выполнение типовых операций с данными (CRUD — Create, Read, Update, Delete создание, чтение, обновление, удаление). Обратите внимание, что код для них будет очень похожим.
Создание (Вставка)
try { $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare('INSERT INTO someTable VALUES(:name)'); $stmt->execute(array( ':name' => 'Justin Bieber' )); # Изменено строк? echo $stmt->rowCount(); // 1 } catch(PDOException $e) { echo 'Error: ' . $e->getMessage();
Обновление
$id = 5; $name = "Joe the Plumber"; try { $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare('UPDATE someTable SET name = :name WHERE id = :id'); $stmt->execute(array( ':id' => $id, ':name' => $name )); echo $stmt->rowCount(); // 1 } catch(PDOException $e) { echo 'Error: ' . $e->getMessage(); }
Удаление
$id = 5; try { $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare('DELETE FROM someTable WHERE id = :id'); $stmt->bindParam(':id', $id); // Воспользуемся методом bindParam $stmt->execute(); echo $stmt->rowCount(); // 1 } catch(PDOException $e) { echo 'Error: ' . $e->getMessage(); }
Результат в виде объекта
Одним из замечательных свойств PDO (а также и mysqli) является возможность представления результата запроса в виде экземпляра класса или объекта. Например:
class User { public $first_name; public $last_name; public function full_name() { return $this->first_name . ' ' . $this->last_name; } } try { $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $result = $pdo->query('SELECT * FROM someTable'); # Выводим результат как объект $result->setFetchMode(PDO::FETCH_CLASS, 'User'); while($user = $result->fetch()) { # Вызываем наш метод full_name echo $user->full_name(); } } catch(PDOException $e) { echo 'Error: ' . $e->getMessage(); }
Заключение
Если вы все еще используете старый API mysql
для работы с базой данных, то следует остановиться. Несмотря на то, что он еще не считается устаревшим, код будет иметь более высокий уровень безопасности и поддержки, если перевести его на PDO.
HomeCodingPHP application cannot connect to MySQL over SSL
This article describes how to solve PDOException: SQLSTATE[HY000] [2002] Connection refused
when connecting from any PHP application with PDO::MySQL to a SSL enabled MySQL database with mismatching CN.
Symptoms
Connecting to the database without SSL works, but when it is enabled, then you cannot connect although all certificates and keys are provided.
Database connection properties (in Drupal8) looks like:
array ( 'database' => 'database', 'username' => 'username', 'password' => 'password', 'prefix' => '', 'host' => 'hostname', 'port' => '3306', 'driver' => 'mysql', 'pdo' => [ PDO::MYSQL_ATTR_SSL_KEY =>'/var/www/site/keys/client-key.pem', PDO::MYSQL_ATTR_SSL_CERT =>'/var/www/site/keys/client-cert.pem', PDO::MYSQL_ATTR_SSL_CA =>'/var/www/site/keys/server-ca.pem' ] )
When trying to connect older versions of PHP does not report the real error but just PDOException: SQLSTATE[HY000] [2002] Connection refused
while newer ones report an additional
PHP Fatal error: Uncaught PDOException: PDO::__construct(): Peer certificate CN=`*********:stage-database' did not match expected CN=`***.***.***.***'
and is reproducible with SSL enabled Google Cloud SQL instance because the issued certificates CN is not a resolvable FQDN which can be used to be connect to from outside.
Cause
The root cause is PHP by default verifies if the canonical name of the certificate matches the hostname you are trying to connect to. If that fails then connection is denied but this is not reported as an error or warning.
Solution
After a few bug reports and complaints a new PDO::MySQL attribute was added in php-7.0.18, php-7.1.4 with commit 247ce052cd0fc7d0d8ea1a0e7ea2075e9601766a but not documented in the official documentation. That parameter disables hostname verification and applications connect without any issue. I’ve commented on php.net about that here.
So add to your pdo properties array the following key – PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT
'pdo' => [ PDO::MYSQL_ATTR_SSL_KEY =>'/var/www/site/keys/client-key.pem', PDO::MYSQL_ATTR_SSL_CERT =>'/var/www/site/keys/client-cert.pem', PDO::MYSQL_ATTR_SSL_CA =>'/var/www/site/keys/server-ca.pem', PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false ]
If after adding this parameter you get an error message
PHP message: Error: Undefined class constant 'MYSQL_ATTR_SSL_VERIFY_SERVER_CERT'
then your PHP version does not support that parameter and you need to upgrade.
The solutions is applicable to any PHP application that uses PDO::MySQL. So far verified on Symfony, Laravel, Drupal