Деректер өңдеушілер

Өз PHP кодыңыз өте көп рет деректер базасын пайдаланады. Сіздің деректер базасымен байланыс жасау және өздігінен интерактивті болдыру үшін бірнеше мүмкіндіктеріңіз бар. PHP 5.1.0-ге дейін ұсынулған опция — мысалы, mysqli, pgsql, mssql — боларды пайдалану.

Егер сіздің өкінішке болары, сіздің бағдарламаңызда тек бір деректер базасын пайдалансаңыз, міне, натив драйверлер маңызды болады. Бірақ мысалы, сіз MySQL және бір көмекші MSSQL пайдаланасыз, немесе Oracle деректер базасына қосылу көрсеткіштері көмекші болса, онда сіз оларды теңдеу мүмкін емесіз. Сізге өзге деректер базасы үшін толығымен жаңа API үйрену қажет болады — және бұл ауыр ауыр болатын мәселе болуы мүмкін.

MySQL Көмекшісі

PHP үшін mysql көмекшісі тым өте ескі және үшінші екі көмекшімен ауыстырылды:

Не тек mysql дамытуы өте оқшау кездесіпті, бірақ ол PHP 7.0-да қолдану үшін ресми түсірілді.

Сіздің php.ini параметрлеріңізге кіріспеу үшін кез келген редакторыңызда mysql_* іздеу кезінде, қолданылатын модульді тексеру үшін бір опция — бұл mysql_connect() және mysql_query() сияқты функциялар болса, онда mysql пайдаланылады.

Сіз PHP 7.x неше көп жатқызбасында болмаса да, бұл жаңартуды жаңа ізденген кезде өздігінізді жеткізбеді. Ең жақсы опция — mysqli неоғу PDO көмекшілерімен mysql пайдалануын өз бағдарламаларыңызда жасау, сондай-ақ кейіндіктен тездетілмейміз.

Егер сіз mysql көмекшісінен mysqli көмекшісіне жаңарту жасасаңыз, тек mysql_* орналастыруы келетіндей сілтеме ұсынатпайтын салмақты жаңарту ұсыныстарына салынғанына ескеріп көйлеу көрсетілетін тамаша жақсы емес. Бұл тек өте қысқарту жаттығу, бірақ PDO де ұсынылады техникалық артықшылықтардан тарату мүмкіндігін ұмытпайды.

PDO Көмекшісі

PDO PHP 5.1.0-дан бастап бар бағдарлама байланыс абстракция библиотекасы — бірнеше өте көп деректер базаларымен сөйлесу үшін қолданылатын. Мысалы, сіз MySQL не SQLite-пен байланысу үшін өзіндік кодты пайдалана аласыз:

<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

PDO сіздің SQL сұрауларыңын немесе өткізіп тұрмайтын қажеттіліктерін түсіндірмейді; бұл тек өзге деректер базаларымен байланысу үшін ортақ интерфейс береді.

Онда біреу, PDO сізге SQL инъекция атакаларынан тым аурулармен сақтау мүмкіндігін береді. Мысалы, иностанны input (мысалы, ID) өз SQL сұрауларыңызға сәтті жасау үшін PDO клаузалары мен байланыстарды пайдалануға мүмкіндік береді.

PHP скрипті санаймыз, сізге саны ID дайындалмалы параметр ретінде келеді. Бұл ID-ны деректер базасынан пайдаланушы еңгізу үшін пайдалану қажет. Бұл кедей жол:

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- ЖАРАМСЫЗ ЕМЕС!

Бұл жаман код. Сіз SQL сұрау параметрін жоқтау SQL сұрауына енгізіп отырап жатарды, аймақ жасау үшін SQL Инъекция деп аталатын іске қосу практикасын пайдалану арқылы. Мысалы, қауіпсіздік куршаушы көмекші параметрімен http://domain.com/?id=1%3BDELETE+FROM+users деп URL-ді шақыру кезінде $_GET['id'] переменді 1;DELETE FROM users деп орнататын болса, бұл өзгеріске кететін барлық пайдаланушыларды жоюды алдайды! Себебі, сіз PDO клаузаларын пайдалана отырып, ID енгізініштерін өтініштерімен тазарту керек.

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT); // <-- деректеріңізді біріншіден тазартыңыз (көмекші: [Деректерді Тазалау](#data_filtering)), мағаны INSERT, UPDATE жатсаулары үшін аса маңызды.
$stmt->bindParam(':id', $id, PDO::PARAM_INT); // <-- PDO арқылы SQL үшін автоматты тазаланады
$stmt->execute();

Бұл дұрыс код. Бұл PDO клаузасында байланысталған параметрді қолданады. Бұл иностанны input (мысалы, ID) деректер базасына енгізілгеннен бұрын тазалайды, потенциалды SQL инъекция атакаларын алтынан шақырады.

INSERT немесе UPDATE сияқты жазулар үшін деректерді тазалау ( деректерді тазалау туралы мақала ) тым маңызды, және басқалар үшін оны тазалау (HTML тегтерін аластату, JavaScript жою үшін тазалау) түсіндірілген. PDO тек оны SQL үшін тазалар, сіздің қолданушы интерфейсі үшін емес.

Сіздің білетініз келсе, деректер базасы байланыстары ресурстарды қолданады, және агымдағы кезде соңы болмаса, өзге тілдерде тегін жабылар болуы туралы еш өзіге сыйлықсыз болмақты білу керек. PDO пайдалану арқылы сіз объектіні жоя отырып барлық әлеуеттерін жойғанда байланысты алып тастай аласыз, міне, оны NULL-ге орнату арқылы. Бұны белгісіз болмасаңыз, PHP скрипті бітетінде байланысты автоматты түрде жабады - басқа даусыз жасау келсе, мәселен, сіз қолдану үшін жаттығу байланыстарды пайдалануды сақтайсыз боларсыз.

Деректер базасымен Іштірек Құру

Дайында PHP үйренуге бастайтын уақытта, дамытуды жасаушылар көбінесе, олардың деректер базасымен іштірек құрауын, кодты көрсеткін болады:

<ul>
<?php
foreach ($db->query('SELECT * FROM table') as $row) {
    echo "<li>".$row['field1']." - ".$row['field2']."</li>";
}
?>
</ul>

Бұл көмекші көптеген себептерге байланысты жаман практика, основалы олар - бұл өте қиын болар, тестілеу үшін қиын, оқуы үшін қиын, деректерді өзгерту үшін үстіне шектеу көрсету мүмкіндігі жоқ жатамдықтарды жасау себептерінен болмауы мүмкін. Басқа ешқандай шектеу көрсетпесеңіз, көптеген кескіндіктерді көрсетуіне қатысты көп өріс әкесіз кетеді.

Бұл істеулерді орындау үшін басқа шешімдер де бар - ООП немесе функционалды жасау мүмкін болатын болатын болады, бірақ белгілі бөлік көрсетілуі керек.

Ең нысанды қарап тұрыпыңыз:

<?php
function getAllFoos($db) {
    return $db->query('SELECT * FROM table');
}

$results = getAllFoos($db);
foreach ($results as $row) {
    echo "<li>".$row['field1']." - ".$row['field2']."</li>"; // ЖАРАМСЫЗ!!
}

Бұл жақсы бастау. Осы екі элементті орнына келісімізді орналастырып, сіздің байланыс ортаңызды тазартып аласыз.

foo.php

<?php
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8mb4', 'username', 'password');

// Модельді қолданып алу үшін
include 'models/FooModel.php';

// Нысаны құру
$fooModel = new FooModel($db);
// Foo-лардың тізімін алу
$fooList = $fooModel->getAllFoos();

// Көрсету
include 'views/foo-list.php';

models/FooModel.php

<?php
class FooModel
{
    public function __construct(protected PDO $db)
    {
    }

    public function getAllFoos() {
        return $this->db->query('SELECT * FROM table');
    }
}

views/foo-list.php

<?php foreach ($fooList as $row): ?>
    <li><?= $row['field1'] ?> - <?= $row['field2'] ?></li>
<?php endforeach ?>

Бұл аса тұрау жасаушылардың көбі өзгергеніне сияқты, тек біраз көмекшілігі көбейгі. Сіз өмірінде барлық жаттамаларды орналау қажет емес, бірақ көбінеуліктік дайындық жасау және деректер базасымен іштірек құрау алдамашы болмаса, өз өлшемізге емес болады. Егер әр турлы бастамаларды біріктіріп жаттамаларды жасау қажет болса, бұл мүмкіндік көбінесеу қатесі болуы мүмкін. Егер сіз өмірінде араларды таратуды қайта тексергіңіз келсе, сіздің бірлесетін тесттеу көмекшісі болады.

Абстракция Қабаттары

Көптеген фреймворктар PDO үстіне орнатылған немесе орнатылмауы мүмкін болатын өзінің абстракция қабатын ұсынайды. Олар өзінде PDO туралы терімдігі айырым абстракция беру жаттықтыруын ұсынату үшін PHP әдістерінде сұрауларыңызды биіктейді, бірақ егер сіз MySQL, PostgreSQL және SQLite мен тесікке жұмыс жасау кезінде, бұл аз көбірек келуі мүмкін болар.

Кейбір абстракция қабаттары PSR-0 немесе PSR-4 пространство аты стандарттарын қолданарлықтағы орындалатылады, сондай-ақ сізге қажет болатын барлық бағдарламаға орнатуға болады: