🏗️ OOP – Klases un objekti PHP
Objektorientēta programmēšana (OOP) organizē kodu ap "objektiem" – datu un metožu kolekcijām. PHP piedāvā pilnvērtīgu OOP atbalstu.
Klases un objekti
Klase ir "zīmējums" (blueprint), no kura tiek radīti objekti.
Teksts
<?php
// Klases definēšana
class Automašīna {
// Īpašības (properties)
public string $marka;
public string $modelis;
public int $gads;
protected int $ātrums = 0; // protected - pieejama tikai šajā klasē un apakšklasēs
private float $degvielasTanks; // private - pieejama tikai šajā klasē
// Konstruktors - izsaucas, veidojot objektu
public function __construct(string $marka, string $modelis, int $gads) {
$this->marka = $marka;
$this->modelis = $modelis;
$this->gads = $gads;
$this->degvielasTanks = 50.0;
}
// Metodes
public function apraksts(): string {
return "{$this->gads}. gada {$this->marka} {$this->modelis}";
}
public function paātrināt(int $par): void {
$this->ātrums += $par;
echo "Paātrināts! Pašreizējais ātrums: {$this->ātrums} km/h<br>";
}
public function bremzēt(): void {
$this->ātrums = max(0, $this->ātrums - 20);
echo "Bremzēts. Ātrums: {$this->ātrums} km/h<br>";
}
public function iegūtĀtrumu(): int {
return $this->ātrums;
}
}
// Objekta izveide (instantiation)
$auto = new Automašīna("Toyota", "Corolla", 2022);
$auto2 = new Automašīna("BMW", "3-Series", 2021);
echo $auto->apraksts() . "<br>"; // 2022. gada Toyota Corolla
echo $auto2->apraksts() . "<br>; // 2021. gada BMW 3-Series
$auto->paātrināt(40);
$auto->paātrināt(20);
$auto->bremzēt();
echo "Ātrums: " . $auto->iegūtĀtrumu() . "<br>";
?>
Konstruktors un destruktors
Teksts
<?php
class DatubāzesSavienojums {
private static int $savienojumuSkaits = 0;
private string $host;
// PHP 8+ - Constructor Property Promotion
// Automātiski izveido un piešķir īpašības
public function __construct(
private string $nosaukums,
private int $ports = 3306,
bool $autoConnect = true
) {
$this->host = "localhost";
self::$savienojumuSkaits++;
echo "Izveidots savienojums #{" . self::$savienojumuSkaits . "} ar " . $this->nosaukums . "<br>";
if ($autoConnect) {
$this->savienot();
}
}
private function savienot(): void {
echo "Savienots ar {$this->nosaukums}:{$this->ports}<br>";
}
// Destruktors - izsaucas, iznīcinot objektu (garbage collection)
public function __destruct() {
echo "Savienojums ar {$this->nosaukums} slēgts.<br>";
self::$savienojumuSkaits--;
}
public static function iegūtSkaitu(): int {
return self::$savienojumuSkaits;
}
}
$db1 = new DatubāzesSavienojums("mana_db");
$db2 = new DatubāzesSavienojums("cita_db", 5432);
echo "Aktīvo savienojumu skaits: " . DatubāzesSavienojums::iegūtSkaitu() . "<br>";
// Kad skripts beidzas, __destruct automātiski tiek izsaukts katram objektam
?>
Piekļuves modificētāji un Getter/Setter
Teksts
<?php
class BankasKonts {
private float $bilance;
private array $transakcijas = [];
public function __construct(private string $numurs, float $sākotnējā = 0) {
if ($sākotnējā < 0) {
throw new InvalidArgumentException("Sākotnējā bilance nevar būt negatīva!");
}
$this->bilance = $sākotnējā;
}
// Getter - lasīt privātu īpašību
public function iegūtBilanci(): float {
return $this->bilance;
}
public function iegūtNumuru(): string {
return $this->numurs;
}
// Setter ar validāciju
public function iemaksāt(float $summa): void {
if ($summa <= 0) {
throw new InvalidArgumentException("Iemaksas summai jābūt pozitīvai!");
}
$this->bilance += $summa;
$this->transakcijas[] = [
"veids" => "iemaksa",
"summa" => $summa,
"laiks" => date("H:i:s")
];
}
public function izmaksāt(float $summa): void {
if ($summa > $this->bilance) {
throw new RuntimeException("Nepietiek naudas! Bilance: {$this->bilance}");
}
$this->bilance -= $summa;
$this->transakcijas[] = [
"veids" => "izmaksa",
"summa" => $summa,
"laiks" => date("H:i:s")
];
}
public function transakcijuVēsture(): array {
return $this->transakcijas;
}
// Magic method: __toString
public function __toString(): string {
return "Konts {$this->numurs}: " . number_format($this->bilance, 2) . " EUR";
}
}
$konts = new BankasKonts("LV12345678", 1000.00);
$konts->iemaksāt(500.00);
$konts->izmaksāt(200.00);
echo $konts . "<br>"; // Konts LV12345678: 1300.00 EUR
foreach ($konts->transakcijuVēsture() as $t) {
echo "{$t["laiks"]}: {$t["veids"]} {$t["summa"]} EUR<br>";
}
?>
Mantošana (Inheritance)
Teksts
<?php
// Vecāku klase (parent)
class Dzīvnieks {
public function __construct(
protected string $vārds,
protected int $vecums
) {}
public function apraksts(): string {
return "{$this->vārds} ({$this->vecums} gadi)";
}
public function skaņa(): string {
return "...";
}
public function __toString(): string {
return $this->apraksts() . " saka: " . $this->skaņa();
}
}
// Apakšklase (child) - mantojo no Dzīvnieks
class Suns extends Dzīvnieks {
public function __construct(string $vārds, int $vecums, private string $šķirne) {
parent::__construct($vārds, $vecums); // Izsauc vecāku konstruktoru
}
// Pārrakstīt (override) vecāku metodi
public function skaņa(): string {
return "Hau hau!";
}
// Jauna metode tikai Suns klasei
public function ienest(): string {
return "{$this->vārds} atnes bumbu!";
}
public function apraksts(): string {
return parent::apraksts() . " [{$this->šķirne}]"; // Izsauc vecāku metodi
}
}
class Kaķis extends Dzīvnieks {
public function skaņa(): string { return "Mjau!"; }
public function spēlēties(): string { return "{$this->vārds} spēlējas ar dziju!"; }
}
$suns = new Suns("Rex", 3, "Labradors");
$kaķis = new Kaķis("Muris", 5);
echo $suns . "<br>"; // Rex (3 gadi) [Labradors] saka: Hau hau!
echo $kaķis . "<br>"; // Muris (5 gadi) saka: Mjau!
echo $suns->ienest() . "<br>"; // Rex atnes bumbu!
// Polimorfisms - dažādi objekti, vienāda saskarne
$dzīvnieki = [$suns, $kaķis, new Suns("Laila", 2, "Pudels")];
foreach ($dzīvnieki as $d) {
echo $d->apraksts() . " saka: " . $d->skaņa() . "<br>";
}
// instanceof pārbaude
echo ($suns instanceof Suns) ? "Ir suns<br>" : "";
echo ($suns instanceof Dzīvnieks) ? "Arī ir dzīvnieks<br>" : "";
echo ($suns instanceof Kaķis) ? "" : "Nav kaķis<br>";
?>
Abstract klases un Interfaces
Teksts
<?php
// Abstract klase - var definēt kopīgo loģiku un abstraktās metodes
abstract class Forma {
abstract public function laukums(): float; // Jāiplementē apakšklasēs
abstract public function perimetrs(): float; // Jāiplementē apakšklasēs
// Kopīga metode visām formām
public function apraksts(): string {
return sprintf(
"%s: laukums=%.2f, perimetrs=%.2f",
get_class($this),
$this->laukums(),
$this->perimetrs()
);
}
}
class Taisnstūris extends Forma {
public function __construct(private float $platums, private float $augstums) {}
public function laukums(): float { return $this->platums * $this->augstums; }
public function perimetrs(): float { return 2 * ($this->platums + $this->augstums); }
}
class Aplis extends Forma {
public function __construct(private float $rādiuss) {}
public function laukums(): float { return M_PI * $this->rādiuss ** 2; }
public function perimetrs(): float { return 2 * M_PI * $this->rādiuss; }
}
// Interface - tīrs "kontrāts" (tikai metožu paraksti, bez implementācijas)
interface Eksportējams {
public function uzJSON(): string;
public function uzCSV(): string;
}
interface Salīdzināms {
public function salīdzināt(self $cits): int; // -1, 0, vai 1
}
// Klase var implementēt vairākus interfaces
class Produkts implements Eksportējams, Salīdzināms {
public function __construct(
public readonly string $nosaukums, // readonly - PHP 8.1+
public readonly float $cena
) {}
public function uzJSON(): string {
return json_encode(["nosaukums" => $this->nosaukums, "cena" => $this->cena]);
}
public function uzCSV(): string {
return "{$this->nosaukums},{$this->cena}";
}
public function salīdzināt(self $cits): int {
return $this->cena <=> $cits->cena;
}
}
$forms = [new Taisnstūris(5, 3), new Aplis(4)];
foreach ($forms as $f) echo $f->apraksts() . "<br>";
$p1 = new Produkts("Ābols", 0.5);
$p2 = new Produkts("Mango", 2.1);
echo $p1->uzJSON() . "<br>";
echo $p1->salīdzināt($p2) . "<br>"; // -1 (p1 < p2 pēc cenas)
?>
Traits
Traits ļauj koplietot metodes starp klasēm bez mantošanas.
🎓 Ko mācīties tālāk?
Nākamajā sadaļā iepazīsieties ar MySQL datubāzēm PHP – kā savienoties, veikt vaicājumus un CRUD operācijas.
Teksts
<?php
trait Žurnālēšana {
public function ierakstītŽurnālā(string $ziņa, string $līmenis = "INFO"): void {
echo "[{$līmenis}] " . date("H:i:s") . " | " . static::class . ": $ziņa<br>";
}
}
trait Validācija {
public function pārbaudītNeTukšu(string $vērtība, string $lauks): void {
if (empty(trim($vērtība))) {
throw new InvalidArgumentException("Lauks '$lauks' nevar būt tukšs!");
}
}
public function pārbaudītEpastu(string $epasts): bool {
return (bool) filter_var($epasts, FILTER_VALIDATE_EMAIL);
}
}
class LietotājuServiss {
use Žurnālēšana, Validācija; // Izmantot abus traits
public function reģistrēt(string $vārds, string $epasts): array {
$this->pārbaudītNeTukšu($vārds, "vārds");
if (!$this->pārbaudītEpastu($epasts)) {
throw new InvalidArgumentException("Nepareizs e-pasts: $epasts");
}
$this->ierakstītŽurnālā("Reģistrēts lietotājs: $vārds");
return ["id" => rand(1, 1000), "vārds" => $vārds, "epasts" => $epasts];
}
}
class PasūtījumuServiss {
use Žurnālēšana; // Arī šī klase var izmantot Žurnālēšana trait
public function izveidotPasūtījumu(int $lietotāja_id, float $summa): void {
$this->ierakstītŽurnālā("Pasūtījums: lietotājs $lietotāja_id, summa $summa EUR");
}
}
$serv = new LietotājuServiss();
$l = $serv->reģistrēt("Anna", "anna@example.lv");
echo "Reģistrēts: {$l["vārds"]}, ID: {$l["id"]}<br>";
$pas = new PasūtījumuServiss();
$pas->izveidotPasūtījumu(42, 149.99);
?>