У любого современного сайта есть база данных и, если не использовать CMS или фраймверк, то понадобится универсальный интерфейс для доступа к этой базе. Желательно без привязки к конкретной СУБД и с возможностью ее смены с минимальными изменениями кода. Один из достойных вариантов - это PHP Data Objects (PDO).

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

Подключить PDO очень просто, правда есть небольшое различие для разных СУБД. Например:

// MуSQL
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 

// PostgreSQL
$pdo = new PDO("pgsql:host=$host;dbname=$dbname", $user, $pass);

// SQLite
$pdo = new PDO("sqlite:/path/database.db");

При неккоректных входных данных PDO отдаст исключение. При необходимости его можно перехватить с помощью конструкции try...catch. Также, при желании, можно настроить режим обработки ошибок. Делается это через метод $pdo->setAttribute():

// PDO::ERRMODE_SILENT: Возвращать код ошибки по принципу, 
// как в расширениях mysql или mysqli (по умолчанию).
// PDO::ERRMODE_WARNING: Вызывать E_WARNING.
// PDO::ERRMODE_EXCEPTION: Выбрасывать исключения.
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

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

Например, для запросов, которые не возвращают никаких данных можно использовать функцию $pdo->exec(). При удачном выполнении вернет количество затронутых записей, при неудачном FALSE:

$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass);

$countRow = $pdo->exec('DELETE FROM products');

А вот если нужна выборка из базы, подойдет метод $pdo->query(). При удачном выполнении вернет PDOStatement, при неудачном FALSE:

$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass); 

$sql = 'SELECT * FROM categories';
foreach ($pdo->query($sql) as $row)
{
    echo $row['name'] . PHP_EOL;
}

Конечно можно и более индивидуально настроить запрос. Например:

$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass); 

// Полученные записи будут в виде массива с объектами
if (false !== $query = $pdo->query('SELECT * FROM categories'))
{
    $categories = $query->fetchAll(PDO::FETCH_OBJ);

    foreach ($categories as $category)
    {
        echo $category->name . PHP_EOL;
    }
}

// А здесь вернет строку из базы в виде объекта Product
class Product {
    public $name;
}
if (false !== $query = $pdo->query('SELECT * FROM products WHERE id = 1'))
{
    $product = $query->fetchObject(get_class(new Product));

    if ($product instanceof Product)
        echo $product->name . PHP_EOL;
}

И наконец, третий способ - подготовленный (или параметризованный) запрос. Вполне обоснованно может возникнуть вопрос: "Зачем же его подготавливать?". Ответ очень прост - для того, что бы его можно было выполнять многократно (например, поиск на сайте). Подготовка выполняется методом $pdo->prepare(), а выполнение - методом $pdo->execute().

При подготовке запроса сервер проверяет шаблон запроса, строит его план и выделяет для него ресурсы. При выполнении в шаблон подставляются реальные значения и выполняется отправка на сервер, который запускает уже готовый запрос (а не формирует его заново как с методом $pdo->query()). Пример:

$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass); 

$stmt = $pdo->prepare('SELECT name FROM posts WHERE text LIKE :text');
$stmt->execute(array('text' => '%php%'));
foreach ($stmt->fetchAll() as $row)
{
    echo $row['name'] . PHP_EOL;
}

В завершение опишу несколько полезных методов класса PDO.

Так как запросы в базу будем посылать не только мы, но и пользователи сайта (все тот же поиск по сайту), то мы просто обязаны защитить себя от sql инъекций. Для этого у PDO есть функция $pdo->quote(), которая экранирует специальные символы.

Если мы делаем запрос не методом $pdo->exec(), но при этом хотим узнать количество затронутых записей (например, после обновления характеристики товара, хотим узнать сколько товаров затронуло это обновление), то функция $pdo->rowCount() как раз то, что нам надо.

Если же нужно получить id последней добавленной записи, то нам поможет функция $pdo->lastInsertId().