Доступ к базе данных в PHP

Практическая часть использования 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.

Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/NdlDVS4f4cg/lessons.php

Читать комменты и комментировать

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



Защитный код
Обновить

Доступ к базе данных в PHP | | 2012-06-19 11:57:37 | | Статьи Web-мастеру | | Практическая часть использования PDO API для работы с базой данных.Что?Для соединения с базой данных MySQL имеется три разных API:mysql mysqli – MySQL Improved (улучшенная) pdo – PHP Data Objects | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Поделиться с друзьями: