Namespace va autoload
Muammodan boshlaylik
Loyihangiz o'sdi: 40 ta class, har biri alohida faylda. Har bir sahifa boshida:
<?php
require_once __DIR__ . '/src/Mahsulot.php';
require_once __DIR__ . '/src/Savat.php';
require_once __DIR__ . '/src/Buyurtma.php';
require_once __DIR__ . '/src/BuyurtmaHolati.php';
require_once __DIR__ . '/src/PaymeTolov.php';
// ... yana 15 ta
Yangi class qo'shsangiz — kerakli sahifalarga require qo'shishni unutasiz. Bundan tashqari, siz Logger classini yozdingiz, keyin o'rnatgan kutubxonada ham Logger bor:
Fatal error: Cannot declare class Logger, because the name is already in use
Ikki muammo, ikki yechim: namespace — nomlar to'qnashuvi uchun, autoload — require lar uchun.
Namespace — nomlar uchun "familiya"
Sinfda ikkita Aziz bor. O'qituvchi "Aziz Karimov" va "Aziz Toshev" deb ajratadi. Namespace — classlarning familiyasi:
<?php
// src/Dokon/Logger.php
namespace Dokon;
class Logger
{
public function yoz(string $xabar): void { /* ... */ }
}
Endi bu classning to'liq nomi — Dokon\Logger. Boshqa kutubxonadagi Monolog\Logger bilan to'qnashmaydi.
Namespace ichma-ich bo'lishi mumkin:
<?php
namespace Dokon\Tolov;
class PaymeTolov { } // to'liq nomi: Dokon\Tolov\PaymeTolov
[!INFO]
namespacefaylning birinchi buyrug'i bo'lishi kerak (declare(strict_types=1);dan tashqari). Namespace da\(teskari slash) ishlatiladi.
use — qisqa nom bilan ishlatish
<?php
namespace Dokon\Controller;
use Dokon\Tolov\PaymeTolov;
use Dokon\Tolov\TolovTizimi;
use Dokon\Logger;
use Monolog\Logger as MonologLogger; // nomini o'zgartirib olish
class BuyurtmaController
{
public function __construct(
private TolovTizimi $tolov,
private Logger $logger,
) {}
}
use — "bu faylda PaymeTolov deganimda, Dokon\Tolov\PaymeTolov ni nazarda tutaman". as — bir xil nomli ikki classni ajratish uchun.
PHP ning o'z classlari
Namespace ichida PHP ning o'rnatilgan classlari oldiga \ qo'yish yoki use qilish kerak:
<?php
namespace Dokon;
$sana = new DateTimeImmutable();
// Error: Class "Dokon\DateTimeImmutable" not found
$sana = new \DateTimeImmutable(); // ✅ global namespace dan
Yoki fayl boshida use DateTimeImmutable;.
Autoload — classlarni avtomatik yuklash
PHP kodda noma'lum class uchrasa (masalan, new Dokon\Savat()), u to'xtashdan oldin sizdan so'raydi: "bu classni qayerdan topay?". Bu savolga javob beruvchi funksiya — autoloader:
<?php
// public/index.php
spl_autoload_register(function (string $class): void {
// "Dokon\Tolov\PaymeTolov" → "src/Tolov/PaymeTolov.php"
$prefiks = 'Dokon\\';
$papka = __DIR__ . '/../src/';
if (!str_starts_with($class, $prefiks)) {
return; // boshqa namespace — bu autoloader ning ishi emas
}
$nisbiy = substr($class, strlen($prefiks));
$fayl = $papka . str_replace('\\', '/', $nisbiy) . '.php';
if (is_file($fayl)) {
require $fayl;
}
});
// Endi birorta ham require kerak emas:
$savat = new Dokon\Savat();
$tolov = new Dokon\Tolov\PaymeTolov();
Autoloader classni faqat birinchi marta kerak bo'lganda yuklaydi. Ishlatilmagan classlar umuman yuklanmaydi — bu tezlik uchun ham foydali.
PSR-4 — umumiy qoida
Autoloader ishlashi uchun namespace va papka tuzilmasi bir-biriga mos bo'lishi kerak. Bu qoida PSR-4 standarti deyiladi:
Namespace → Fayl
Dokon\Savat → src/Savat.php
Dokon\Tolov\PaymeTolov → src/Tolov/PaymeTolov.php
Dokon\Model\Foydalanuvchi → src/Model/Foydalanuvchi.php
Qoidalar:
- Bitta fayl — bitta class
- Fayl nomi = class nomi (katta-kichik harf ham!)
- Namespace qismlari = papkalar
Odatiy loyiha tuzilmasi:
dokon/
├── public/
│ └── index.php ← veb-server faqat shu papkani ko'radi
├── src/
│ ├── Savat.php ← namespace Dokon;
│ ├── Model/
│ │ └── Mahsulot.php ← namespace Dokon\Model;
│ └── Tolov/
│ ├── TolovTizimi.php
│ └── PaymeTolov.php ← namespace Dokon\Tolov;
└── config.php
public/ — yagona ochiq papka. src/, config.php brauzerdan umuman ko'rinmaydi. Bu xavfsizlik uchun juda muhim.
Composer bilan — amaliy usul
O'z autoloader ingizni yozish shart emas. Composer (39-dars) buni avtomatik qiladi. composer.json:
{
"autoload": {
"psr-4": {
"Dokon\\": "src/"
}
}
}
composer dump-autoload
public/index.php:
<?php
require __DIR__ . '/../vendor/autoload.php';
$savat = new Dokon\Savat(); // hammasi ishlaydi
Bitta qator — va barcha classlaringiz hamda o'rnatilgan kutubxonalar avtomatik yuklanadi. Zamonaviy PHP loyihalarning 100% i shunday ishlaydi.
Nima uchun shunday?
Nima uchun namespace ajratgichi \, boshqa tillardagidek . yoki :: emas?
PHP da . — string birlashtirish, :: — static murojaat uchun allaqachon band edi. 2008-yilda namespace qo'shilayotganda ko'p variantlar muhokama qilindi va to'qnashmaydigan yagona belgi sifatida \ tanlandi. Ko'pchilik uni yoqtirmaydi (string ichida 'Dokon\\Savat' deb ikki marta yozish kerak), lekin endi bu o'zgarmaydi.
Tez-tez uchraydigan xatolar
Class topilmadi:
Error: Class "Dokon\Model\Mahsulot" not found
Tekshiring: fayl to'g'ri papkadami? Fayl nomi class nomi bilan aynan mosmi (mahsulot.php ≠ Mahsulot.php — Windows da ishlaydi, Linux serverda yo'q)? Faylda namespace to'g'ri yozilganmi?
use ni unutish — PHP classni joriy namespace ichidan qidiradi.
Namespace dagi o'rnatilgan classlar — \DateTimeImmutable, \PDO, \Exception — \ yoki use kerak.
Xulosa
Eslab qoling:
namespace Dokon\Tolov;— classning "familiyasi", nomlar to'qnashmaydiuse Dokon\Tolov\PaymeTolov;— qisqa nom bilan ishlatish;as— nomini o'zgartirish- Namespace ichida PHP classlari uchun
\yokiuse spl_autoload_register— classlarni avtomatik yuklash- PSR-4: namespace = papka, class nomi = fayl nomi
- Amalda: Composer +
require 'vendor/autoload.php'
Keyingi dars
34-dars: MySQL ga kirish — jadval, CRUD so'rovlar