пятница, 14 марта 2014 г.

PHP, PDO. Примеры работы

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

Прежде всего создадим таблицу, пускай это будет таблица users, вот такая:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`email` varchar(50) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) Engine=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4;

INSERT INTO `users` (`id`, `name`, `email`, `age`) VALUES  
                    (1, 'Alex', 'alex@hisemail.com', 20),
(2, 'Maxim', 'maxim@hisemail.com', 24),
(3, 'Denis', 'denis@hisemail.com', 25);
Давайте разберемся как работать в PDO с MySQL. Для начала нужно подключиться к серверу MySQL:
try
{   // У меня таблица хранится в бд test.
    $db = new PDO('mysql:host=localhost;dbname=test','root','');
}
catch(PDOException $e)
{
    die("Error: ".$e->getMessage());
}
Для того чтобы сделать выборку всех данных из таблицы у класса PDO есть метод ->fetchAll():
if ($result = $db->query("SELECT * FROM `users`"))
{
    $result->execute();
    $data = $result->fetchAll();
    echo "<pre>";
    print_r($data);
    echo "</pre>";
}
В итоге вы должны получить такой результат:
Array
(
    [0] => Array
        (
            [id] => 1
            [0] => 1
            [name] => Alex
            [1] => Alex
            [email] => alex@hisemail.com
            [2] => alex@hisemail.com
            [age] => 20
            [3] => 20
        )

    [1] => Array
        (
            [id] => 2
            [0] => 2
            [name] => Maxim
            [1] => Maxim
            [email] => maxim@hisemail.com
            [2] => maxim@hisemail.com
            [age] => 24
            [3] => 24
        )

    [2] => Array
        (
            [id] => 3
            [0] => 3
            [name] => Denis
            [1] => Denis
            [email] => denis@hisemail.com
            [2] => denis@hisemail.com
            [age] => 25
            [3] => 25
        )
)
А теперь сделаем фетч данных в ассоциативный массив по ключу (id), заметье :id это плейсхолдер, своеобразная защита от mysql-инъекций:
if ($result = $db->prepare("SELECT * FROM `users` WHERE `id`=:id"))
{
    $id = 2;
    $result->bindValue(":id",$id,PDO::PARAM_INT);
    $result->execute();
    $assoc = $result->fetch(PDO::FETCH_ASSOC);
    echo "<pre>";
    var_dump($assoc);
    echo "</pre>";
}
Посмотрим на результат
array(4) {
  ["id"]=>
  string(1) "2"
  ["name"]=>
  string(5) "Maxim"
  ["email"]=>
  string(18) "maxim@hisemail.com"
  ["age"]=>
  string(2) "24"
}
Чтобы вернуть оба массива сразу и проиндексированный и с именнованными полями достаточно просто изменить константу FETCH_ASSOC на FETCH_BOTH
if ($result = $db->prepare("SELECT * FROM `users` WHERE `id`=:id"))
{
    $id = 3;
    $result->bindValue(":id",$id,PDO::PARAM_INT);
    $result->execute();
    $both = $result->fetch(PDO::FETCH_BOTH);
    echo "<pre>";
    var_dump($both);
    echo "</pre>";
}
Вот что из этого вышло
array(8) {
  ["id"]=>
  string(1) "3"
  [0]=>
  string(1) "3"
  ["name"]=>
  string(5) "Denis"
  [1]=>
  string(5) "Denis"
  ["email"]=>
  string(18) "denis@hisemail.com"
  [2]=>
  string(18) "denis@hisemail.com"
  ["age"]=>
  string(2) "25"
  [3]=>
  string(2) "25"
}
А теперь вернем результат запроса в виде объекта, с этим справляется константа класса PDO FETCH_OBJ
if ($result = $db->prepare("SELECT * FROM `users` WHERE `id`=:id"))
{ 
    $id = 1;
    $result->bindValue(":id",$id,PDO::PARAM_INT);
    $result->execute();
    $obj = $result->fetch(PDO::FETCH_OBJ);
    echo "<pre>";
    var_dump($obj->name);
    echo "</pre>";
    // результат string(4) "Alex"
}
Вставку в базу данных (метод INSERT) можно сделать таким способом, как видим создается массив, вернуть идентификатор добавленной записи можно с помощью метода lastinsertId()
if ($result = $db->prepare("INSERT INTO `users`(`name`,`email`,`age`) VALUES (?,?,?)"))
{
    $name = "Andrew";
    $email = "andrew@hisemail.com";
    $age = 22;
    $data = array ( $name, $email, $age );
    $result->execute($data);
    $Id = $db->lastinsertId();
    echo $Id; // 4 
}
Несколько ранее мы столкнулись с bindValue, но есть еще и bindParam, главное отличие одного от другого в том что bindValue() – присваивает псевдопеременной значение, а bindParam() – связывает псевдопеременную с настоящей переменной, и при изменении настоящей переменной, не нужно больше вызывать никаких дополнительных функций, можно сразу execute()

Пример с bindParam(), обязательно указывайте тип заbind'енных переменных, PDO::PARAM_STR или PDO::PARAM_INT, давайте вытащим все записи из базы где имена пользователей начинаются на "A"
if ($result = $db->prepare("SELECT * FROM `users` WHERE `name` LIKE :symb"))
{
    $symb = "A%";
    $result->bindParam(":symb",$symb,PDO::PARAM_STR);
    $result->execute();
    $data = array();
    while ($fields = $result->fetch(PDO::FETCH_ASSOC))
    {
         $data[] = $fields;
    }
    echo "<pre>";
    var_dump($data);
    echo "</pre>";
}
Результат
array(2) {
  [0]=>
  array(4) {
    ["id"]=>
    string(1) "1"
    ["name"]=>
    string(4) "Alex"
    ["email"]=>
    string(17) "alex@hisemail.com"
    ["age"]=>
    string(2) "20"
  }
  [1]=>
  array(4) {
    ["id"]=>
    string(1) "4"
    ["name"]=>
    string(6) "Andrew"
    ["email"]=>
    string(19) "andrew@hisemail.com"
    ["age"]=>
    string(2) "22"
  }
}
Кроме PARAM_STR и PARAM_INT есть еще ряд констант:

PDO::PARAM_BOOL ( bool ) - логические данные
PDO::PARAM_NULL ( NULL ) - пусто ( NULL ) т.е. ничего
PDO::PARAM_LOB ( Larg Objects Data ) - это для больших объемов данных
PDO::PARAM_STMT (for a recordset type, currently not supported)
PDO::PARAM_INPUT_OUTPUT (for an INOUT parameter of a Stored Procedure)

Рассмотрим еще пару таких вещей как удаление и изменение нужных записей

Сперва давайте изменим возвраст нашему Alex'у, что-то он у нас слишком молодо выглядит

if ($result = $db->prepare("UPDATE `users` SET `age`=:age WHERE `name`=:name"))
{
    $age = 25;
    $name = "Alex";
    $result->bindParam(":age",$age,PDO::PARAM_INT);
    $result->bindParam(":name",$name,PDO::PARAM_STR);
    $result->execute();
}
Готово! Теперь Alex повзраслел аж на целых 5 лет. Осталось только удалить одного из участников моего туториола, не бойтесь, с ним ничего плохого не случилось, просто его перевели в другой отдел, пускай нашей жертвой будет Andrew, пошел на повышение можно сказать!
if ($result = $db->prepare("DELETE FROM `users` WHERE `name`=?"))
{
     $result->execute(array("Andrew"));
}
Очень часто требуется проверить на валидность почтовый адрес (ну или пароль), с паролем не хочу заморачиваться, тем более что у нас в БД нету такого поля, так что давайте рассмотрим ситуацию на примере email, т.е. если пользователь ввел свое имя как Maxim и email как maxim@hisemail.com, то такой пользователь есть, логинем его и как говорится "В Добрый путь!".

Для того чтобы сделать такую проверку достаточно будет метода fetchColumn(), так как все-равно запрос у нас возвращает только одно поле
if ($result = $db->prepare("SELECT `name`,`email` FROM `users` WHERE `name`=:name AND 
                           `email`=:email"))
{
     $params = array (
       "name" => "Maxim",
       "email" => "maxim@hisemail.com"
     );
    $result->execute($params);
     if ($valid = (bool) $result->fetchColumn())
    {
         echo "Пользователь (существует) залогинен";
    }
}
Еще один нюанс, извольте, плейсхолдеры нельзя использовать для названия таблиц и полей (это вам не данные!!!), т.е.
SELECT ? FROM ? WHERE `id`=:id LIMIT 1
так делать ни в коем случае нельзя!

Конечно это далеко ни все что есть в PDO, я лишь только хотел с'акцентировать свое и ваше внимание на самых базовых вещах.

IT-записки

comments powered by Disqus