Php и mysql удаление файла в pdo. Php прописать: Как правильно настроить соединение PDO. Подготовленные против прямых запросов

  • 03.11.2019

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

Соединение с MySQL:

$dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass);

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

Обработка ошибок соединения:

try { $dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass); foreach($dbh->query(‘SELECT * from FOO’) as $row) { print_r($row); } $dbh = null; } catch (PDOException $e) { die("Ошибка! Всё. Приехали... ".$e->getMessage()); }

Внимание: Если Вы не поймаете исключение, брошенное конструктором PDO, действие по умолчанию, предпринятое движком zend, должно остановить скрипт и показать трассировку. Эта хрень выдаст все Ваши интимные подробности общения с базой данной. То есть покажет подробные детали соединения с базой данных, включая имя пользователя и пароль! На Вашей совести поймать это исключение, либо явно (через утверждение try catch ), либо неявно через set_exception_handler ().

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

Закрытие соединения:

$dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass); // Здесь что то делаем: ... // А теперь, внимание: конец связи! $dbh = null;

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

Установка постоянного соединения:

$dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

Имейте ввиду: Если Вы хотите использовать постоянное соединение, Вы должны установить PDO::ATTR_PERSISTENT в массиве опций драйвера, который передаётся конструктору класса PDO. Устанавливая этот атрибут через PDO::setAttribute() после создания экземпляра объекта, драйвер не будет использовать постоянные связи. А так же, в этом случае вам не удастся расширить класс PDOStatement для каких то своих нужд, т.е. нельзя будет установить: PDO::ATTR_STATEMENT_CLASS

Термин PDO является сокращением понятия PHP Data Objects . Как можно судить по названию, эта технология позволяет работать с содержимым базы данных через объекты.

Почему не myqli или mysql?

Чаще всего, в отношении новых технологий, встает вопрос их преимуществ перед старыми-добрыми и проверенными инструментами, а также, перевода на них текущих и старых проектов.

Объектная ориентированность PDO

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

Говоря о PHP , будем подразумевать современный объектно-ориентированный PHP , позволяющий писать универсальный код, удобный для тестирования и повторного использования.

Использование PDO позволяет вынести работу с базой данных на объектно-ориентированный уровень и улучшить переносимость кода. На самом деле, использование PDO не так сложно, как можно было бы подумать.

Абстракция

Представим, что мы уже продолжительное время разрабатываем приложение, с использованием MySQL . И вот, в один прекрасный момент, появляется необходимость заменить MySQL на PostgreSQL .

Как минимум, нам придется заменить все вызовы mysqli_connect() (mysql_connect()) на pg_connect() и, по аналогии, другие функции, используемые для запроса и обработки данных.

При использовании PDO , мы ограничимся изменением нескольких параметров в файлах конфигурации.

Связывание параметров

Использование связанных параметров предоставляет большую гибкость в составлении запросов и позволяет улучшить защиту от SQL инъекций.

Получение данных в виде объектов

Те, кто уже использует ORM (object-relational mapping — объектно-реляционное отображение данных), например, Doctrine , знают удобство представления данных из таблиц БД в виде объектов. PDO позволяет получать данные в виде объектов и без использования ORM .

Расширение mysql больше не поддерживается

Поддержка расширения mysql окончательно удалена из нового PHP 7 . Если вы планируете переносить проект на новую версию PHP , уже сейчас следует использовать в нем, как минимум, mysqli. Конечно же, лучше начинать использовать PDO , если вы еще не сделали этого.

Мне кажется, что этих причин достаточно для склонения весов в сторону использования PDO . Тем более, не нужно ничего дополнительно устанавливать.

Проверяем наличие PDO в системе

Версии PHP 5.5 и выше, чаще всего, уже содержать расширение для работы с PDO . Для проверки достаточно выполнить в консоли простую команду:

php -i | grep "pdo"

Теперь откроем его в любом браузере и найдем нужные данные поиском по строке PDO .

Знакомимся с PDO

Процесс работы с PDO не слишком отличается от традиционного. В общем случае, процесс использования PDO выглядит так:

  1. Подключение к базе данных;
  2. По необходимости, подготовка запроса и связывание параметров;
  3. Выполнение запроса.

Подключение к базе данных

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

В общем случае, DSN состоит из имени драйвера, отделенного двоеточием от строки подключения, специфичной для каждого драйвера PDO .

Для MySQL , подключение выполняется так:

$connection = new PDO("mysql:host=localhost;dbname=mydb;charset=utf8", "root", "root");

$connection = new PDO ("mysql:host=localhost;dbname=mydb;charset=utf8" , "root" , "root" ) ;

В данном случае, DSN содержит имя драйвера mysql , указание хоста (возможен формат host=ИМЯ_ХОСТА:ПОРТ ), имя базы данных, кодировка, имя пользователя MySQL и его пароль.

Запросы

В отличие от mysqli_query() , в PDO есть два типа запросов:

  • Возвращающие результат (select, show );
  • Не возвращающие результат (insert , detele и другие).

Первым делом, рассмотрим второй вариант.

Выполнение запросов

Рассмотрим пример выполнения запроса на примере insert .

$connection->exec("INSERT INTO users VALUES (1, "somevalue"");

$connection -> exec () ;

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

$affectedRows = $connection->exec("INSERT INTO users VALUES (1, "somevalue""); echo $affectedRows;

$affectedRows = $connection -> exec ("INSERT INTO users VALUES (1, "somevalue"" ) ;

echo $affectedRows ;

Получение результатов запроса

В случае использования mysqli_query () , код мог бы быть следующим.

$result = mysql_query("SELECT * FROM users"); while($row = mysql_fetch_assoc($result)) { echo $row["id"] . " " . $row["name"]; }

$result = mysql_query ("SELECT * FROM users" ) ;

while ($row = mysql_fetch_assoc ($result ) ) {

Для PDO , код будет проще и лаконичнее.

foreach($connection->query("SELECT * FROM users") as $row) { echo $row["id"] . " " . $row["name"]; }

foreach ($connection -> query ("SELECT * FROM users" ) as $row ) {

echo $row [ "id" ] . " " . $row [ "name" ] ;

Режимы получения данных

Как и в mysqli , PDO позволяет получать данные в разных режимах. Для определения режима, класс PDO содержит соответствующие константы.

  • PDO:: FETCH_ASSOC — возвращает массив, индексированный по имени столбца в таблице базы данных;
  • PDO:: FETCH_NUM — возвращает массив, индексированный по номеру столбца;
  • PDO:: FETCH_OBJ — возвращает анонимный объект с именами свойств, соответствующими именам столбцов. Например, $row->id будет содержать значение из столбца id.
  • PDO:: FETCH_CLASS — возвращает новый экземпляр класса, со значениями свойств, соответствующими данным из строки таблицы. В случае, если указан параметр PDO:: FETCH_CLASSTYPE (например PDO:: FETCH_CLASS | PDO:: FETCH_CLASSTYPE ), имя класса будет определено из значения первого столбца.

Примечание : это не полный список, все возможные константы и варианты их комбинации доступны в документации .

Пример получения ассоциативного массива:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_ASSOC)) { echo $row["id"] . " " . $row["name"]; }

$statement = $connection ->

while ($row = $statement -> fetch (PDO:: FETCH_ASSOC ) ) {

echo $row [ "id" ] . " " . $row [ "name" ] ;

Примечание : Рекомендуется всегда указывать режим выборки, так как режим PDO:: FETCH_BOTH потребует вдвое больше памяти — фактически, будут созданы два массива, ассоциативный и обычный.

Рассмотрим использование режима выборки PDO:: FETCH_CLASS . Создадим класс User :

class User { protected $id; protected $name; public function getId() { return $this->id; } public function setId($id) { $this->id = $id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } }

class User

protected $id ;

protected $name ;

public function getId ()

return $this -> id ;

public function setId ($id )

$this -> id = $id ;

public function getName ()

return $this -> name ;

public function setName ($name )

$this -> name = $name ;

Теперь выберем данные и отобразим данные при помощи методов класса:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_CLASS, "User")) { echo $row->getId() . " " . $row->getName(); }

$statement = $connection -> query ("SELECT * FROM users" ) ;

while ($row = $statement -> fetch (PDO:: FETCH_CLASS , "User" ) ) {

echo $row -> getId () . " " . $row -> getName () ;

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

Для понимания сути и всех преимуществ связывания параметров нужно более подробно рассмотреть механизмы PDO . При вызове $statement -> query () в коде выше, PDO подготовит запрос, выполнит его и вернет результат.

При вызове $connection -> prepare () создается подготовленный запрос. Подготовленные запросы — это способность системы управления базами данных получить шаблон запроса, скомпилировать его и выполнить после получения значений переменных, использованных в шаблоне. Похожим образом работают шаблонизаторы Smarty и Twig .

При вызове $statement -> execute () передаются значения для подстановки в шаблон запроса и СУБД выполняет запрос. Это действие аналогично вызову функции шаблонизатора render () .

Пример использования подготовленных запросов в PHP PDO :

В коде выше подготовлен запрос выборки записи с полем id равным значению, которое будет подставлено вместо : id . На данном этапе СУБД выполнит анализ и компиляцию запроса, возможно с использованием кеширования (зависит от настроек).

Теперь нужно передать недостающий параметр и выполнить запрос:

$id = 5; $statement->execute([ ":id" => $id ]);

Преимущества использования связанных параметров

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

PDO предоставляет удобную возможность экранирования пользовательских данных, например, такой код больше не нужен:

Вместо этого, теперь целесообразно делать так:

Можно, даже, еще укоротить код, используя нумерованные параметры вместо именованных:

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

$numberOfUsers = $connection->query("SELECT COUNT(*) FROM users")->fetchColumn(); $users = ; $statement = $connection->prepare("SELECT * FROM users WHERE id = ? LIMIT 1"); for ($i = 1; $i <= 5; $i++) { $id = rand(1, $numberOfUsers); $users = $statement->execute([$id])->fetch(PDO::FETCH_OBJ); }

$numberOfUsers = $connection -> query ("SELECT COUNT(*) FROM users" ) -> fetchColumn () ;

$users = ;

for ($i = 1 ; $i <= 5 ; $i ++ ) {

$id = rand (1 , $numberOfUsers ) ;

$users = $statement -> execute ([ $id ] ) -> fetch (PDO:: FETCH_OBJ ) ;

При вызове метода prepare () , СУБД проведет анализ и скомпилирует запрос, при необходимости использует кеширование. Позже, в цикле for , происходит только выборка данных с указанным параметром. Такой подход позволяет быстрее получить данные, уменьшив время работы приложения.

При получении общего количества пользователей в базе данных был использован метод fetchColumn () . Этот метод позволяет получить значение одного столбца и является полезным при получении скалярных значений, таких как количество, сумма, максимально или минимальное значения.

Связанные значения и оператор IN

Часто, при начале работы с PDO , возникают трудности с оператором IN . Например, представим, что пользователь вводит несколько имен, разделенных запятыми. Пользовательский ввод хранится в переменной $names .

мета теги (5)

Время от времени я вижу вопросы о подключении к базе данных.
Большинство ответов - это не то, как я это делаю, или я просто не могу правильно ответить. Так или иначе; Я никогда не думал об этом, потому что способ, которым я это делаю, работает для меня.

Но вот сумасшедшая мысль; Возможно, я делаю все это неправильно, и если это так; Мне бы очень хотелось знать, как правильно подключиться к базе данных MySQL с помощью PHP и PDO и сделать ее доступной.

Вот как я это делаю:

Во-первых, вот моя файловая структура (урезанная) :

Public_html/ * index.php * initialize/ -- load.initialize.php -- configure.php -- sessions.php

index.php
На самом верху я require("initialize/load.initialize.php"); ,

load.initialize.php

# site configurations require("configure.php"); # connect to database require("root/somewhere/connect.php"); // this file is placed outside of public_html for better security. # include classes foreach (glob("assets/classes/*.class.php") as $class_filename){ include($class_filename); } # include functions foreach (glob("assets/functions/*.func.php") as $func_filename){ include($func_filename); } # handle sessions require("sessions.php");

Я знаю, что есть лучший, или более правильный способ включения классов, но не помню, что это было. Не получили времени, чтобы изучить его еще, но я думаю, что это было что-то с autoload . что-то вроде того...

configure.php
Здесь я в основном просто переопределяю некоторые php.ini -properties и выполняю некоторые другие глобальные настройки для сайта

connect.php
Я установил соединение в класс, чтобы другие классы могли расширять этот...

Class connect_pdo { protected $dbh; public function __construct() { try { $db_host = " "; // hostname $db_name = " "; // databasename $db_user = " "; // username $user_pw = " "; // password $con = new PDO("mysql:host=".$db_host."; dbname=".$db_name, $db_user, $user_pw); $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $con->exec("SET CHARACTER SET utf8"); // return all sql requests as UTF-8 } catch (PDOException $err) { echo "harmless error message if the connection fails"; $err->getMessage() . "
"; file_put_contents("PDOErrors.txt",$err, FILE_APPEND); // write some details to an error-log outside public_html die(); // terminate connection } } public function dbh() { return $this->dbh; } } # put database handler into a var for easier access $con = new connect_pdo(); $con = $con->dbh(); //

Здесь я действительно верю, что есть место для массового улучшения, так как я недавно начал изучать ООП и использовал PDO вместо mysql.
Поэтому я только что последовал за несколькими учебниками для начинающих и опробовал разные вещи...

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

If (!isset($_SESSION["sqlQuery"])){ session_start(); $_SESSION["sqlQuery"] = new sqlQuery(); }

Таким образом, этот класс доступен повсеместно. Это может быть не очень хорошая практика (?) ...
Во всяком случае, это то, что этот подход позволяет мне делать везде:

Echo $_SESSION["sqlQuery"]->getAreaName("county",9); // outputs: Aust-Agder (the county name with that id in the database)

Внутри моего класса sqlQuery , который extends мой класс connect_pdo , у меня есть открытая функция getAreaName которая обрабатывает запрос в моей базе данных.
Думаю, довольно аккуратный.

Работает как шарм
Так вот в основном, как я это делаю.
Кроме того, всякий раз, когда мне нужно что-то извлекать из моего БД из класса, я просто делаю что-то похожее на это:

$id = 123; $sql = "SELECT whatever FROM MyTable WHERE id = :id"; $qry = $con->prepare($sql); $qry -> bindParam(":id", $id, PDO::PARAM_INT); $qry -> execute(); $get = $qry->fetch(PDO::FETCH_ASSOC);

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

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

Я очень хочу учиться...

Answers

$dsn = "mysql:host=your_host_name;dbname=your_db_name_here"; // define host name and database name $username = "you"; // define the username $pwd="your_password"; // password try { $db = new PDO($dsn, $username, $pwd); } catch (PDOException $e) { $error_message = $e->getMessage(); echo "this is displayed because an error was found"; exit(); }

Недавно я пришел к аналогичному ответу / вопросу самостоятельно. Это то, что я сделал, в случае, если кто-то заинтересован:

args = func_get_args(); } public function __call($method, $args) { if (empty($this->db)) { $Ref = new \ReflectionClass("\PDO"); $this->db = $Ref->newInstanceArgs($this->args); } return call_user_func_array(array($this->db, $method), $args); } }

Для его вызова вам нужно только изменить эту строку:

$DB = new \Library\PDO(/* normal arguments */);

И тип-намек, если вы используете его (\ Library \ PDO $ DB).

Это действительно похоже на принятый ответ и ваш; однако он имеет значительное преимущество. Рассмотрим этот код:

$DB = new \Library\PDO(/* args */); $STH = $DB->prepare("SELECT * FROM users WHERE user = ?"); $STH->execute(array(25)); $User = $STH->fetch();

Хотя он может выглядеть как обычный PDO (он изменяется только этим \Library\ only), он фактически не инициализирует объект, пока вы не вызовете первый метод, в зависимости от того, что это такое. Это делает его более оптимизированным, поскольку создание объекта PDO немного дорого. Это прозрачный класс, или то, что он называется Ghost , форма . Вы можете обрабатывать $ DB как обычный экземпляр PDO, передавать его, выполнять те же операции и т. Д.

Я бы предложил не использовать $_SESSION для доступа к вашему соединению с БД глобально.

Вы можете сделать одну из нескольких вещей (в порядке худших для лучших практик):

  • Доступ к $dbh с использованием global $dbh внутри ваших функций и классов
  • Используйте одноэлементный реестр и доступ к нему глобально, например:

    $registry = MyRegistry::getInstance(); $dbh = $registry->getDbh();

    Внесите обработчик базы данных в нужные ему классы:

    Class MyClass { public function __construct($dbh) { /* ... */ } }

Однако он немного более продвинутый и требует больше «проводки» без рамки. Таким образом, если инъекция зависимостей слишком сложна для вас, используйте реестр singleton вместо совокупности глобальных переменных.

Цель

Как я вижу, ваша цель в этом случае двоякая:

  • создавать и поддерживать одно / многоразовое соединение для каждой базы данных
  • убедитесь, что соединение настроено правильно

Решение

$provider = function() { $instance = new PDO("mysql:......;charset=utf8", "username", "password"); $instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); return $instance; }; $factory = new StructureFactory($provider);

Затем в другом файле или ниже в том же файле:

$something = $factory->create("Something"); $foobar = $factory->create("Foobar");

Сама фабрика должна выглядеть примерно так:

Class StructureFactory { protected $provider = null; protected $connection = null; public function __construct(callable $provider) { $this->provider = $provider; } public function create($name) { if ($this->connection === null) { $this->connection = call_user_func($this->provider); } return new $name($this->connection); } }

Таким образом, вы можете иметь централизованную структуру, которая гарантирует, что соединение создается только тогда, когда это необходимо. Это также облегчило бы процесс модульного тестирования и обслуживания.PHP , и этот код добавить обратные слэши следующие символы: \x00 , \n , \r , \ , " , " и \x1a . Передайте входные значения в качестве параметров, чтобы свести к минимуму вероятность внедрения SQL.

  • Самый продвинутый способ - использование PDO.
  • Я надеюсь, что это поможет вам.

    Рассмотрим следующий запрос:

    $iId = mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

    mysql_real_escape_string () не будет защищать здесь. Если вы используете одиночные кавычки ("") вокруг ваших переменных внутри вашего запроса, это то, что защищает вас от этого. Ниже приведено ниже решение:

    $iId = (int) mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

    На этот question есть хорошие ответы.

    Я предлагаю, что использование PDO - лучший вариант.

    Редактировать:

    mysql_real_escape_string() устарел от PHP 5.5.0. Используйте либо mysqli, либо PDO.

    Альтернативой mysql_real_escape_string () является

    String mysqli_real_escape_string (mysqli $link , string $escapestr)

    Пример:

    $iId = $mysqli->real_escape_string("1 OR 1=1"); $mysqli->query("SELECT * FROM table WHERE id = $iId");

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

    Наверняка, многие уже слышали аббревиатуру PDO , но мало кто знает, что же это. Вот давайте сегодня об этом и поговорим.

    Что такое PDO?

    PDO(PHP Data Objects) - это просто интерфейс , позволяющий нам абстрагироваться от конкретной базы данных. Лучше всего показать на примере.

    Mysql_connect($host, $user, $pass); // MySQL
    mysql_select_db($db);

    Sqlite_open($db); // sqlite

    Pg_connect("host=$host, dbname=$db, user=$user, password=$pass"); // PostgreSQL

    В коде выше представлены способы для подключения к трём разным базам данных: MySQL , sqlite и PostgreSQL . Как видите, функции у каждой БД отличаются.

    То же самое с другими действиями. Например, выборка данных из БД.

    $sql = "INSERT INTO(name, pass) VALUES($name, $pass)";

    Mysql_query($sql); // MySQL
    sqlite_query($sql); // sqlite
    pg_query($sql); // PostgreSQL

    Зачем нужен PDO?

    Представим, что у нас есть огромная база данных PostgreSQL , и мы решили сменить её на MySQL . Нам придётся переписывать очень много кода, и, скорее всего, без ошибок не обойдётся. Чтобы решить эту проблему и существует PDO , позволяющий нам не зависеть от конкретной базы.

    Давайте рассмотрим, как мы теперь можем подключиться.

    $db = new PDO("mysql:host=$host;dbname=$db", $user, $pass); // MySQL
    $db = new PDO("sqlite:host=$host;dbname=$db", $user, $pass); // sqlite
    $db = new PDO("pgsql:host=$host;dbname=$db", $user, $pass); // PostgreSQL

    Как видно из кода выше, в этих трёх подключениях меняется только строчка с названием БД, а остальное всё то же самое.

    Чтобы что-нибудь выбрать, мы можем написать так:

    $db->exec($sql);

    Всё! Запрос выполнится независимо от того, какая у нас база данных.

    Поддержка

    PDO доступен с PHP 5.1 . Чтобы мы могли "забыть", какую базу данных мы используем, за нас всё делают их драйверы . Чтобы их активировать, зайдите в файл php.ini и найдите там строчки, которые начинаются на extension=php_pdo_ , а затем идёт название базы данных, и раскоментируйте их.

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