# PHP un datubāzes: PDO un mysqli

> PHP un datubāzes izskaidrotas: PDO un mysqli salīdzinājums, Prepared Statements, kļūdu apstrāde kopš PHP 8 un droši piekļuves dati darbībā.

Avots: https://phpsos.de/lv/php/php-und-datenbanken/  
Aktuāls uz: 25.10.2026  
Pakalpojuma sniedzējs: PHP SOS, PHP ārkārtas palīdzība un serveru drošība. Tūlītēja palīdzība pa WhatsApp: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20nepiecie%C5%A1ama%20pal%C4%ABdz%C4%ABba%20ar%20m%C5%ABsu%20PHP%20serveri.%20Uz%C5%86%C4%93mums%3A%20%E2%80%A6%20Vietne%3A%20%E2%80%A6

**Īsi:** PHP piekļūst datubāzēm caur divām izplatītām saskarnēm: PDO (PHP Data Objects) ar daudzām datubāzu sistēmām strādā caur vienotu saskarni, mysqli ir pielāgots MySQL un MariaDB. Ar abām droši pret SQL injekciju aizsargā Prepared Statements, tas ir, vaicājumi ar vietturiem. Kopš PHP 8.0 (PDO) un 8.1 (mysqli) abas kļūdas pēc noklusējuma ziņo kā Exception.

## Kā PHP sazinās ar datubāzēm

Gandrīz katra PHP lietojumprogramma saturu glabā datubāzē: lapas, pasūtījumus, lietotāju kontus, iestatījumus. PHP skripts šim nolūkam izveido savienojumu, nosūta vaicājumu SQL valodā un apstrādā rezultātu. Piekļuves dati parasti atrodas konfigurācijas failā tajā pašā serverī.

Vadībai tas ir svarīgi, jo datubāzē parasti atrodas uzņēmuma vērtīgākie dati. Kas serverī var izpildīt kodu, parasti var arī nolasīt konfigurācijas failu un ar šiem piekļuves datiem piekļūt datubāzei.

## PDO un mysqli salīdzinājums

| Pazīme | PDO | mysqli |
|---|---|---|
| Datubāzes | daudzas, ar draiveriem, piemēram, `PDO_MYSQL`, `PDO_PGSQL`, `PDO_SQLITE`, `PDO_SQLSRV`, `PDO_OCI` | MySQL un MariaDB |
| Vietturi | nosaukti (`:name`) un pozicionāli (`?`) | pozicionāli (`?`) |
| Stils | objektorientēts | objektorientēts un procedurāls |
| Kļūdas kā Exception | noklusējums kopš PHP 8.0.0 | noklusējums kopš PHP 8.1.0 |
| Īsā forma vaicājumiem ar parametriem | `prepare()` un `execute()` ar masīvu | `execute_query()` kopš PHP 8.2.0 |

Praksē bieži izšķir ietvars vai CMS. Daudzi nes līdzi savu datubāzes slāni, kas iekšēji izmanto PDO vai mysqli. Kas pārņem lietojumprogrammu, ar vienkāršu meklēšanu pirmkodā var noskaidrot, kura saskarne tiek lietota un kur rodas vaicājumi:

```bash
# Kur lietojumprogramma izveido savienojumus, kur rodas vaicājumi?
grep -rn --include='*.php' -E 'new PDO|new mysqli|mysqli_connect|->query\(' /var/www/app/src | head -50
```

Atradumi ar `->query(` nav automātiski nedroši. Tomēr tie pelna otru skatienu, jo tur vērtības var nonākt tieši SQL tekstā, nevis tikt nodotas caur vietturiem. Tieši vecāki projekti sajauc abus stilus, un pārbaude atmaksājas pirms katra lielāka atjauninājuma.

## Prepared Statements: svarīgākais paraugs

Prepared Statement gadījumā vaicājums ar vietturiem tiek nosūtīts datubāzei un vērtības tiek nodotas atsevišķi. Saskaņā ar PHP rokasgrāmatu tas aizsargā pret SQL injekciju, ja visa lietotāju ievade iet caur vietturiem.

```php
<?php
declare(strict_types=1);

$pdo = new PDO(
    'mysql:host=localhost;dbname=shop;charset=utf8mb4',
    $dbUser,
    $dbPass,
    [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);

$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE plz = :plz AND aktiv = :aktiv');
$stmt->execute(['plz' => $plz, 'aktiv' => 1]);

foreach ($stmt as $zeile) {
    echo htmlspecialchars($zeile['name'], ENT_QUOTES, 'UTF-8'), "\n";
}
```

Tas pats ar mysqli īsajā formā, kas pastāv kopš PHP 8.2:

```php
<?php
$db = new mysqli('localhost', $dbUser, $dbPass, 'shop');
$ergebnis = $db->execute_query('SELECT id, name FROM kunden WHERE plz = ?', [$plz]);

foreach ($ergebnis as $zeile) {
    echo htmlspecialchars($zeile['name'], ENT_QUOTES, 'UTF-8'), "\n";
}
```

Izstrādātājiem jāzina divas robežas. Vietturi nedrīkst atrasties pēdiņās; `LIKE` meklējumos aizstājējzīmes `%` pieder nodotajā vērtībā. Un vietturi aizstāj tikai vērtības, nevis tabulu vai kolonnu nosaukumus. Kā šādus īpašos gadījumus atrisināt droši, parāda ceļvedis [SQL injekcijas novēršana PHP](https://phpsos.de/lv/ratgeber/sql-injection-php/).

## Kļūdu apstrāde: Exceptions kluso kļūdu vietā

Agrāk abas saskarnes pēc noklusējuma strādāja klusi: neveiksmīgs vaicājums atgrieza `false`, un kas to nepārbaudīja, turpināja darbu ar tukšiem datiem. Tas ir mainījies:

- **PDO:** Kopš PHP 8.0.0 `PDO::ERRMODE_EXCEPTION` ir noklusējums. Kļūdas met `PDOException`.
- **mysqli:** Kopš PHP 8.1.0 kļūdu ziņošana ir iestatīta uz `MYSQLI_REPORT_ERROR` un `MYSQLI_REPORT_STRICT`. Kļūdas met `mysqli_sql_exception`; iepriekš ziņošana bija izslēgta.

Drošībai tas nozīmē: Exceptions jāuztver un jāreģistrē žurnālā, bet nekad nedrīkst nonākt pārlūkprogrammā ar SQL tekstu, tabulu nosaukumiem vai piekļuves datiem. Kā to tīri nošķirt, apraksta lapa [Kļūdas un Exceptions PHP](https://phpsos.de/lv/php/fehler-und-exceptions/).

## Piekļuves datu un tiesību pareiza piešķiršana

Datubāze ir aizsargāta tikai tik labi, cik tās piekļuves dati. Pierādījušies šie noteikumi:

1. **Savs lietotājs katrai lietojumprogrammai:** Vietnei nekad neizmantot datubāzes administratoru.
2. **Tikai nepieciešamās tiesības:** Vietnei parasti vajag lasīšanu, rakstīšanu, mainīšanu un dzēšanu savā datubāzē, bet ne tiesības uz citām datubāzēm vai servera funkcijām.
3. **Nekādu attālinātu savienojumu bez iemesla:** Datubāzei jābūt sasniedzamai tikai no tīmekļa servera, nevis no interneta.
4. **Piekļuves dati ārpus webroot:** Konfigurācijas un `.env` faili nedrīkst būt izsaucami ar URL. Vairāk rakstā [Piekļuves datu un .env failu aizsardzība](https://phpsos.de/lv/blog/env-dateien-schuetzen/).
5. **Šifrēts savienojums nošķirtiem serveriem:** Ja datubāze atrodas citā datorā, savienojumam jābūt šifrētam, lai piekļuves dati un saturs pa tīklu neiet atklātā tekstā.
6. **Savas piekļuves apkopei:** Datu dublēšanai, izvērtējumiem un administratoriem ir savi lietotāji. Tā žurnālā var izsekot, kurš ko darījis, un piekļuvi var bloķēt, netraucējot vietni.

## Datubāzes, PHP2Shell un ārkārtas gadījums

PHP2Shell skar nevis pašu datubāzi, bet PHP interpretatoru: CVE-2026-109618 un CVE-2026-109619 ļauj izpildīt ļaunprātīgu kodu bez pieteikšanās. Ja tas izdodas, kods darbojas ar PHP procesa tiesībām un tādējādi parasti var nolasīt konfigurācijas failu ar datubāzes piekļuves datiem. Prepared Statements pret to nepalīdz, jo uzbrukums vispār nenotiek caur SQL vaicājumu.

Obligāts ir atjauninājums uz PHP 8.5.12, 8.4.27, 8.3.36 vai 8.2.35 un visu PHP procesu pārstartēšana. Ja ir norādes uz sekmīgu uzbrukumu, klāt nāk jauni datubāzes piekļuves dati, datubāzes pārbaude uz ievadītu saturu un ziņošanas pienākuma novērtējums pēc VDAR (GDPR). Šeit lietderīga ir strukturēta [Incident Response](https://phpsos.de/lv/leistungen/incident-response/).

> **Padoms:**
> Datubāzes paroles mainiet tikai pēc servera attīrīšanas. Kamēr darbojas ļaunprātīgs kods, tas var atkal nolasīt arī jaunos piekļuves datus.

## Kā PHP SOS palīdz konkrēti?

- Mēs pārbaudām, kā jūsu lietojumprogramma piekļūst datubāzei, un vai lietotāji, tiesības un tīkla piekļuve atbilst minimumam.
- Mēs kontrolējam, vai konfigurācijas un piekļuves faili atrodas ārpus webroot un nav publiski sasniedzami.
- Pēc incidenta mēs atjaunojam piekļuves datus pareizā secībā un pārbaudām datubāzi uz ievadītu kodu.
- Mēs rezultātus dokumentējam tā, lai datu aizsardzības speciālisti un apdrošinātāji tos varētu izsekot.


## Biežāk uzdotie jautājumi

**Vai man izmantot PDO vai mysqli?**  
Jauniem projektiem PDO parasti ir elastīgāka izvēle, jo tas ar daudzām datubāzēm strādā caur vienu saskarni. mysqli ir lietderīgs, ja izmantojat tikai MySQL vai MariaDB un jums vajadzīgas to īpašās funkcijas. Abi ir droši, ja konsekventi tiek izmantoti Prepared Statements.

**Vai PDO kļūdu gadījumā automātiski met Exceptions?**  
Jā, kopš PHP 8.0.0 PDO::ERRMODE_EXCEPTION ir noklusējums. Iepriekš bija kluso režīms, kurā kļūdas bija izsaucamas tikai ar errorCode() un errorInfo(). Vecākas lietojumprogrammas režīmu bieži vēl iestata skaidri.

**Vai vietturi var aizstāt arī tabulu vai kolonnu nosaukumus?**  
Nē. Vietturi apzīmē tikai vērtības. Tabulu un kolonnu nosaukumi, piemēram, kārtošanai, pirms ievietošanas vaicājumā jāpārbauda pret fiksētu atļauto nosaukumu sarakstu.

**Vai pēc PHP2Shell man jānomaina datubāzes parole?**  
Pats atjauninājums vien to neprasa. Taču, ja ir norādes, ka serveris bija kompromitēts, visi konfigurācijas failos esošie piekļuves dati uzskatāmi par zināmiem. Tad tie pēc attīrīšanas jāatjauno.

## Avoti

- [PHP rokasgrāmata: PDO Prepared Statements](https://www.php.net/manual/en/pdo.prepared-statements.php)
- [PHP rokasgrāmata: PDO kļūdu apstrāde](https://www.php.net/manual/en/pdo.error-handling.php)
- [PHP rokasgrāmata: mysqli::execute_query](https://www.php.net/manual/en/mysqli.execute-query.php)
- [PHP rokasgrāmata: mysqli_driver::$report_mode](https://www.php.net/manual/en/mysqli-driver.report-mode.php)
