1. Главная страница » Компьютеры » Php pdo mysql connect

Php pdo mysql connect

Автор: | 16.12.2019

In this example we will learn how to properly connect to Mysql database using PDO. It is based on the information provided in the main article on PDO but with additional explanations.

Surprisingly, there is no single state-of-the-art connection example in the PHP manual. Instead, different connection options are discussed in different chapters, which makes it hard for the learner to get a single robust example that is ready to use. Below you will find such an example, as well as the explanation of all the options used.

Example

Credentials exlained

First of all we are defining variables that contain connection credentials. This set is familiar to anyone who were using the old mysql_connect() function, save for $charset may be, which was rarely used (although it should have been).

  • $host stands for the database host. In case of the local development, it is most likely be 127.0.0.1 or localhost . In case of the live site, the actual hostname should be provided by the site admin / hosting provider. Note that connecting through IP address could save you a headache or two, so if you have a trouble with "localhost", try to use 127.0.0.1 instead.
  • $db is the name of the database in MySQL (the value that you were passing into mysql_select_db() ). On your local server it could be anything, while on a live site again it should be given to you by the admin / provider.
  • $user — a database user
  • $pass — a database password
  • $charset is a very important option. It is telling the database in which encoding you are sending the data in and would like to get the data back. Note that due to initially limited support of unicode in the utf8 MySQL charset, it is now recommended to use utf8mb4 instead.

Connection options explained

Next we are creating an array with PDO options that are either critically important or just make your experience with PDO much better.

  • PDO::ATTR_ERRMODE — this is a cornerstone option that should be always set to PDO::ERRMODE_EXCEPTION . It tells PDO to throw an exception every time a query failed, so you won’t have to get the error manually after every query call as it was used to be with mysql_query()
  • PDO::ATTR_EMULATE_PREPARES — this option tell PDO whether to use an emulation mode or not. It is agreed upon that in general it’s better to turn it off, however in some cases it is convenient to have it turned on. Luckily, this setting could be changed in runtime using PDO::setAttribute() method, so let’s make it turned off by default as a connection option, with the possibility to fall back later.
  • PDO::ATTR_DEFAULT_FETCH_MODE — this option is used simply for convenience. Although the fetch method can be always set right in the fetch function call (like $row = $stmt->fetch(PDO::FETCH_ASSOC); ), it is convenient to set it once for all and then just omit it in particular fetches. Besides, when iterating over a statement using foreach there is no place where we can set the fetch mode, so again it is convenient to set it beforehand. The two most popular fetch modes are PDO::FETCH_ASSOC and PDO::FETCH_OBJ which make PDO to fetch the resulting row as an associative array or as an object.

Handling errors

An uncaught exception is converted to a PHP fatal error. It is not a problem by itself, errors are for the good, and we desperately need this one to get the idea what’s wrong with our database. But such a converted error contains a stack trace added to the error message, which in case of PDO connection error would include the constructor parameters which happen to be the database credentials. Again, it shouldn’t be a problem, as on a live site displaying errors should be always turned off anyway, but we are humans and we make mistakes. So, to avoid even a chance to reveal the credentials, we are catching the Exception and immediately re-throwing them. So, now the stack trace begins on the throw line and doesn’t contain the database credentials.

Creating the connection

Having all the options and credentials set, we can finally proceed to creating a connection. To do so we need to create an instance of PDO class for which we need to supply 4 parameters of which the first one, called "DSN" being most important.

DSN is a semicolon-delimited string, consists of param=value pairs, that begins from the driver name and a colon:

Note that it’s important to follow the proper format — no spaces or quotes or other decorations have to be used in DSN, but only parameters, values and delimiters, as shown in the manual.

Beside DSN, we are using $user, $pass and $options variables defined above.

We are wrapping the creation of the PDO instance into a try..catch statement in order to be aware of the possible error, but without the risk of revealing the database credentials.

Don’ts

Beside things that you should do, there are always things that you should do not. Some of them we will discuss below.

  • PDO::ATTR_PERSISTENT . Although this option is rather popular in the copy-pasted cargo cult PDO examples, a learner should always avoid it. There are too many drawbacks (that are outside of the scope of this article) whereas no advantages for a small site at all. This option should be used after a strong consideration only, and by no means as a blindly copy-pasted option just in case.
  • using die() , echo or any other output operator for the caught exception. As it is explained in the relevant article, PHP error reporting, an error message should never be printed unconditionally, but only according to the site-wide settings. And this should be done in the site-wide handler only.
Читайте также:  Deepcool gammaxx 400 установка 1151

Accessing the newly created connection

There is one thing that makes PDO more complex than old mysql_connect related stuff. Although one was able to use mysql_query anywhere in the code, without taking care of the connection which was magically supplied by PHP, with PDO one should always make sure that once created PDO instance is available in each part of their script.

There are many different strategies to have this done, but mostly used are:

  • global. Although this method is unanimously frowned upon, in case your code is the usual procedural spaghetti so familiar to every PHP user, using global to access a PDO instance would be your least problem. So for the simplest method possible just create a PHP file with the code above, and then include in the every PHP script that needs a database connection. Then use $pdo variable everywhere you need. To make it accessible in functions, add global $pdo; inside.
  • singleton approach is better but still frowned upon. But at least it can save you a hassle with global variables. An example can be found in the corresponding chapter about a simple PDO wrapper
  • constructor parameter is the most robust method in case your code is OOP. For the every class that needs a database connection, make PDO a constructor parameter

Related articles:

Got a question?

I am the only person to hold a gold badge in , and on Stack Overflow and I am eager to show the right way for PHP developers.

Besides, your questions let me make my articles even better, so you are more than welcome to ask any question you got.

SEE ALSO:

Latest comments:

  • 21.11.19 13:34
    GioMBG for SELECT query with PDO:
    I Staff, it is possible something like : SELECT >
    read more
  • 20.11.19 04:33
    Carl for How to connect properly using mysqli:
    Forget about the previous silly question. BTW, you’ve done a brilliant job.
    read more
  • 20.11.19 03:57
    Carl for How to connect properly using mysqli:
    In the include file, is it fair to assume that the three dots preceding the ". $params);" are.
    read more
  • 16.11.19 11:33
    Riya Basak for SELECT query with PDO:
    I’m trying to display a message when the query get no result from database. But it displaying.
    read more
  • 14.11.19 20:37
    Arnold D?zsa for PDO Fetch Modes:
    Dear! I read your article about FETCH_INTO. I would like to help so you wrote that it seems.
    read more

Add a comment

Please refrain from sending spam or advertising of any sort.
Messages with hyperlinks will be pending for moderator’s review.

Markdown is now supported:

  • > before and an empty line after for a quote
  • four spaces to mark a block of code

Comments:

typo on the second header , missing p from example

Hello and thank you for your dedication to help others. I am new to PHP and a stickler for best practices. Your work here is excellent. I am building a large database site and want to know what is the ideal PDO connection script that is ultra safe and can be used repeatedly throughout the site.

Reply:

Thank you for the kind words and a good question.

For the connection itself, the provided code is enough. Just put it in a php.file and include it (or rather require_once) in any script that needs a connection. Make sure that display_errors on a live server is set to 0, otherwise this code will print the database credentials out in case of a connection error.

As of the repeated use, it depends on how much functions and classes you are going to use and what is your coding style in general. For the old-style procedural scripts that don’t use functions or classes this code is enough. If you are going to use functions, make sure that you are passing the PDO connection as a parameter for a function that needs it. If you are going to use OOP, make sure that you are passing the PDO connection as a constructor parameter for a class that needs it.

I am sure you could have other questions, don’t hesitate to ask if so.

Hello, I am curious how you would test your connection? Is this an appropriate time for try/catch?

Reply:

That’s a very good question! The answer depends on what you are planning to do in case of connection error, or, to put it closer to your question, what code you want to put inside that catch block. If nothing particular, then it’s no use for the try catch at all, because basic error reporting should be already good with connection errors as well.

There is an article on the error reporting, https://phpdelusions.net/articles/error_reporting I hope you will find it useful

Feel free to ask if you have other questions!

I include my database connection file and this works:

return ($result == 1); >

But I am not sure whether what you are saying amounts to the same thing. I mean it works, Im just trying to understand why when in my head it doesnt quite equal what you are saying!

Читайте также:  Fix it microsoft office 2016

Hi, I tried to do the nasty global approach but I found i dont need to add global $pdo to functions in a file where I include the database connection from another file. Just $pdo seems to be ok.

Reply:

If you need to access a variable inside a function,m you have to either pass it as a function parameter (i.e. $var = func($pdo); ) or declare it global inside.

Why is the charset specified? Isn’t the character set defined for the fields in the database definition? What if these two values conflict?

Reply:

That’s a very good question!

Actually, a database has the ability to recode your data on the fly. And for this very reason you have to specify the charset. For example, it could be utf8 in the database but Windows-1252 on your page (well, you seldom could find such a page nowadays but still). In such a case you have to set a connection charset as cp1252, and then a database will recode your data from 1252 to utf and back.

There is also one more reason connected to the string literals added to the query directly or via emulated placeholders. Escaping rules are different for the different encodings and therefore it is important to specify the charset to let an escaping function to escept the data properly.

I love your explanation about pdo, I am new to pdo and will love to work with it in a project. Do you have any tutorial video that explains pdo in crud using oop method. Thanks for your time.

Соединения устанавливаются автоматически при создании объекта PDO от его базового класса. Не имеет значения, какой драйвер вы хотите использовать; вы всегда используете имя базового класса. Конструктор класса принимает аргументы для задания источника данных (DSN), а также необязательные имя пользователя и пароль (если есть).

Пример #1 Подключение к MySQL

В случае ошибки при подключении будет выброшено исключение PDOException. Его можно перехватить и обработать, либо оставить на откуп глобальному обработчику ошибок, который вы задали функцией set_exception_handler() .

Пример #2 Обработка ошибок подключения

Если ваше приложение не перехватывает исключение PDO конструктора, движок zend выполнит стандартные операции для завершения работы скрипта и вывода обратной трассировки. В этой трассировке будет содержаться детальная информация о соединении с базой данных, включая имя пользователя и пароль. Ответственность за перехват исключений лежит на вас. Перехватить исключение можно явно (с помощью выражения catch), либо неявно, задав глобальный обработчик ошибок функцией set_exception_handler() .

При успешном подключении к базе данных в скрипт будет возвращен созданный объект PDO. Соединение остается активным на протяжении всего времени жизни объекта. Чтобы закрыть соединение, необходимо уничтожить объект путем удаления всех ссылок на него (этого можно добиться, присваивая NULL всем переменным, указывающим на объект). Если не сделать этого явно, PHP автоматически закроет соединение по окончании работы скрипта.

Замечание: Если существуют другие ссылки на данный экземпляр PDO (например, из объекта PDOStatement или другие переменные, ссылающиеся на него), они также должны быть удалены (например, присвоением NULL переменной, ссылающейся на PDOStatement).

Пример #3 Закрытие соединения

= new PDO ( ‘mysql:host=localhost;dbname=test’ , $user , $pass );
// здесь мы каким-то образом используем соединение
$sth = $dbh -> query ( ‘SELECT * FROM foo’ );

// соединение больше не нужно, закрываем
$sth = null ;
$dbh = null ;
?>

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

Пример #4 Постоянные соединения

Чтобы использовать постоянные соединения, необходимо добавить константу PDO::ATTR_PERSISTENT в массив параметров драйвера, который передается конструктору PDO. Если просто задать этот атрибут функцией PDO::setAttribute() уже после создания объекта, драйвер не будет использовать постоянные соединения.

Если вы используете PDO ODBC драйвер и ваши ODBC библиотеки поддерживают объединение подключений в пул (ODBC Connection Pooling) (unixODBC и Windows точно поддерживают, но могут быть и другие), то рекомендуется вместо постоянных соединений пользоваться этим пулом. Пул подключений ODBC доступен всем модулям текущего процесса; если PDO сам кеширует соединение, то это соединение будет недоступно другим модулям и не попадет в пул. В результате каждый модуль будет создавать дополнительные подключения для своих нужд.

User Contributed Notes 12 notes

Using PHP 5.4.26, pdo_pgsql with libpg 9.2.8 (self compiled). As usual PHP never explains some critical stuff in documentation. You shouldn’t expect that your connection is closed when you set $dbh = null unless all you do is just instantiating PDO class. Try following:

= new PDO ( ‘pgsql:host=192.168.137.1;port=5432;dbname=anydb’ , ‘anyuser’ , ‘pw’ );
sleep ( 5 );
$stmt = $pdo -> prepare ( ‘SELECT * FROM sometable’ );
$stmt -> execute ();
$pdo = null ;
sleep ( 60 );
?>

Now check your database. And what a surprise! Your connection hangs for another 60 seconds. Now that might be expectable because you haven’t cleared the resultset.

= new PDO ( ‘pgsql:host=192.168.137.160;port=5432;dbname=platin’ , ‘cappytoi’ , ‘1111’ );
sleep ( 5 );
$stmt = $pdo -> prepare ( ‘SELECT * FROM admin’ );
$stmt -> execute ();
$stmt -> closeCursor ();
$pdo = null ;
sleep ( 60 );
?>

What teh heck you say at this point? Still same? Here is what you need to do to close that connection:

= new PDO ( ‘pgsql:host=192.168.137.160;port=5432;dbname=platin’ , ‘cappytoi’ , ‘1111’ );
sleep ( 5 );
$stmt = $pdo -> prepare ( ‘SELECT * FROM admin’ );
$stmt -> execute ();
$stmt -> closeCursor (); // this is not even required
$stmt = null ; // doing this is mandatory for connection to get closed
$pdo = null ;
sleep ( 60 );
?>

PDO is just one of a kind because it saves you to depend on 3rd party abstraction layers. But it becomes annoying to see there is no implementation of a "disconnect" method even though there is a request for it for 2 years. Developers underestimate the requirement of such a method. First of all, doing $stmt = null everywhere is annoying and what is most annoying is you cannot forcibly disconnect even when you set $pdo = null. It might get cleared on script’s termination but this is not always possible because script termination may delayed due to slow client connection etc.

Читайте также:  Motorola droid turbo xt1254 характеристики

Anyway here is how to disconnect forcibly using postgresql:

= new PDO ( ‘pgsql:host=192.168.137.160;port=5432;dbname=platin’ , ‘cappytoi’ , ‘1111’ );
sleep ( 5 );
$stmt = $pdo -> prepare ( ‘SELECT * FROM admin’ );
$stmt -> execute ();
$pdo -> query ( ‘SELECT pg_terminate_backend(pg_backend_pid());’ );
$pdo = null ;
sleep ( 60 );
?>

Following may be used for MYSQL: (not guaranteed)
KILL CONNECTION_ID()

Содержание:

PDO (PHP Data Objects) — расширение PHP, которое реализует взаимодействие с базами данных при помощи объектов. Профит в том, что отсутствует привязка к конкретной системе управления базами данных. PDO поддерживает СУБД: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server и другие.

Официальный мануал по PHP PDO здесь . Там же можно найти и сам класс PDO .

Почему стоит использовать PDO

Функции mysql в PHP для работы с БД давно уже устарели, на сегодняшний день желательно использовать mysqli или PDO (PHP Data Objects). Кроме того, mysqli — эта библиотека, которая по большому счёту, не предназначена для использования напрямую в коде. Она может послужить хорошим строительным материалом для создания библиотеки более высокого уровня. При работе с mysqli следует также помнить об обеспечении безопасности вашего приложения, в частности о защите от SQL-инъекций. В случае использования PDO (с его подготовленными запросами), такая защита идёт уже "из коробки", главное правильно применить необходимые методы.

Тестовая база данных с таблицей

Установка PDO

Проверить доступные драйвера

Соединение с базой данных

Соединения устанавливаются автоматически при создании объекта PDO от его базового класса.

При ошибке подключения PHP выдаст ошибку:

В этом примере подключения мы используем конструкцию try. catch . Многие спорят о целесообразности её использования. Лично я использую try. catch , она мне не мешает.

Подготовленные и прямые запросы

В PDO два способа выполнения запросов:

  • Прямой — состоит из одного шага;
  • Подготовленный — состоит из двух шагов.

Прямые запросы

  • query() используется для операторов, которые не вносят изменения, например SELECT . Возвращает объект PDOStatemnt , из которого с помощью методов fetch() или fetchAll извлекаются результаты запроса. Можно его сравнить с mysql resource , который возвращала mysql_query() .
  • exec() используется для операторов INSERT, DELETE, UPDATE . Возвращает число обработанных запросом строк.

Прямые запросы используются только в том случае, если в запросе отсутствуют переменные и есть уверенность, что запрос безопасен и правильно экранирован.

Подготовленные запросы

Если же в запрос передаётся хотя бы одна переменная, то этот запрос в обязательном порядке должен выполняться только через подготовленные выражения . Что это значит? Это обычный SQL запрос, в котором вместо переменной ставится специальный маркер — плейсхолдер. PDO поддерживает позиционные плейсхолдеры ( ? ), для которых важен порядок передаваемых переменных, и именованные ( :name ), для которых порядок не важен. Примеры:

Чтобы выполнить такой запрос, сначала его надо подготовить с помощью метода prepare() . Она также возвращает PDO statement , но ещё без данных. Чтобы их получить, надо исполнить этот запрос, предварительно передав в него наши переменные. Передать можно двумя способами: Чаще всего можно просто выполнить метод execute() , передав ему массив с переменными:

Как видно, в случае именованных плейсхолдеров в execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров. После этого можно извлечь результаты запроса:

ВАЖНО! Подготовленные запросы — основная причина использовать PDO, поскольку это единственный безопасный способ выполнения SQL запросов, в которых участвуют переменные.

Получение данных. Метод fetch()

Мы уже выше познакомились с методом fetch() , который служит для последовательного получения строк из БД. Этот метод является аналогом функции mysq_fetch_array() и ей подобных, но действует по-другому: вместо множества функций здесь используется одна, но ее поведение задается переданным параметром. В подробностях об этих параметрах будет написано в другой заметке , а в качестве краткой рекомендации посоветую применять fetch() в режиме FETCH_LAZY

В этом режиме не тратится лишняя память, и к тому же к колонкам можно обращаться любым из трех способов — через индекс, имя, или свойство (через -> ). Недостатком же данного режима является то, что он не работает с fetchAll()

Получение данных. Метод fetchColumn()

Также у PDO statement есть метод для получения значения единственной колонки. Очень удобно, если мы запрашиваем только одно поле — в этом случае значительно сокращается количество кода:

Получение данных. Метод fetchAll()

PDO и оператор LIKE

Работая с подготовленными запросами, следует понимать, что плейсхолдер может заменять только строку или число. Ни ключевое слово, ни идентификатор, ни часть строки или набор строк через плейсхолдер подставить нельзя. Поэтому для LIKE необходимо сначала подготовить строку поиска целиком, а потом ее подставлять в запрос:

Здесь может вознинуть проблема! Поиск может не работать, потому как из базы у вас приходят данные в неправильной кодировке. Необходимо добавить кодировку в подключение, если она там не указана!

PDO и оператор LIMIT

Важно! Когда PDO работает в режиме эмуляции, все данные, которые были переданы напрямую в execute() , форматируются как строки. То есть, эскейпятся и обрамляются кавычками. Поэтому LIMIT . превращается в LIMIT ’10’, ’10’ и очевидным образом вызывает ошибку синтаксиса и, соответственно, пустой массив данных.

Решение #1 : Отключить режим эмуляции:

Решение #2 : Биндить эти цифры через bindValue() , принудительно выставляя им тип PDO::PARAM_INT :

PDO и оператор IN

При выборке из таблицы необходимо доставать записи, соответствующие всем значениям массива.

Добавление записей

Изменение записей

Удаление записей

Использование транзакций

Важно! Транзакции в PDO работают только с таблицами InnoDB

В данной заметке мы познакомились с основными понятиями PDO, его установкой, подключением к БД и самые простые возможности выборки, изменения и удаления данных. В следующих заметках мы рассмотрим ещё несколько тем, касающихся PDO.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *