PHP / Namespace

Namespace

Том төсөл дээр ажиллахад нэг нэртэй хоёр класс гарч ирэх нь нийтлэг асуудал юм — жишээлбэл, чиний бичсэн User класс болон ашиглаж буй гуравдагч сангийн User класс нэрээрээ мөргөлдөнө. Namespace нь яг энэ асуудлыг шийддэг: классуудыг нэрийн орон зай (namespace) дотор бүлэглэж, нэрийн мөргөлдөөнөөс хамгаалдаг. PHP-н Composer package manager болон бүх орчин үеийн фреймворкууд namespace-д бүрэн тулгуурладаг тул энэ ойлголтыг сайн эзэмших нь чухал.

Namespace тодорхойлох

Файлын хамгийн эхэнд namespace гэж тодорхойлно. Замыг \ тэмдгээр тусгаарладаг — компьютерийн хавтасны бүтэцтэй адил:

php
<?php
// файл: src/App/Models/User.php
namespace App\Models;

class User {
    public function __construct(
        public string $нэр,
        public string $имэйл
    ) {}

    public function тайлбар(): string {
        return "{$this->нэр} <{$this->имэйл}>";
    }
}
php
<?php
// файл: src/Payment/Models/User.php
namespace Payment\Models;

class User {
    public function __construct(
        public string $нэр,
        public float  $данс
    ) {}

    public function тайлбар(): string {
        return "{$this->нэр} — " . number_format($this->данс) . "₮";
    }
}

Хоёр файл хоёулаа User нэртэй класс агуулж байгаа ч namespace ялгаатай тул мөргөлдөхгүй.

use — namespace оруулах

Өөр namespace-ийн классыг use гэж оруулаад ашиглана. Энэ нь тухайн файлд богино нэрээр хэрэглэх боломж олгодог:

php
<?php
namespace App\Controllers;

// Бүтэн замаар оруулна
use App\Models\User;
use Payment\Models\User as PaymentUser; // нэр давхцвал alias өгнө

// Олон классыг нэг namespace-ээс оруулах
use App\Services\{AuthService, MailService, LogService};

class UserController {
    public function бүртгэх(): void {
        // use-тай тул богино нэрээр дуудна
        $хэрэглэгч = new User("Болд", "bold@example.mn");

        // Alias ашиглан ялгана
        $төлбөрийн = new PaymentUser("Болд", 500_000);

        echo $хэрэглэгч->тайлбар();  // Болд <bold@example.mn>
        echo $төлбөрийн->тайлбар();  // Болд — 500,000₮
    }
}
?>

as түлхүүр үгээр дурын богино нэр (alias) өгч болно — нэр мөргөлдөхөд маш хэрэгтэй.

Автоматаар ачаалах — autoloading

Жинхэнэ төсөлд require/include гэж гараар файл оруулахгүй — Composer-н autoloader автоматаар хайж олдог. PSR-4 стандартаар namespace нь хавтасны бүтэцтэй тохирно:

json
{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}
php
<?php
// composer.json тохируулсны дараа
require_once 'vendor/autoload.php';

use App\Models\User;
use App\Services\AuthService;

// Autoloader src/Models/User.php файлыг автоматаар олно
$хэрэглэгч = new User("Болд", "bold@example.mn");
?>

App\Models\Usersrc/Models/User.php гэж автоматаар орчуулагдана. Ингэснээр хавтасны нэр болон namespace үргэлж тохирч байх ёстой.

Функц ба константыг namespace-т зарлах

Класс төдийгүй функц болон константуудыг мөн namespace-д байрлуулж болно:

php
<?php
namespace App\Helpers;

const ХУВИЛБАР = '1.0.0';
const ХЭЛ      = 'mn';

function мөрийг_товчлох(string $мөр, int $урт = 50): string {
    if (strlen($мөр) <= $урт) {
        return $мөр;
    }
    return substr($мөр, 0, $урт) . '...';
}

function огноо_форматлах(string $огноо): string {
    return date('Y оны n-р сарын j', strtotime($огноо));
}
php
<?php
namespace App\Controllers;

use function App\Helpers\мөрийг_товчлох;
use function App\Helpers\огноо_форматлах;
use const App\Helpers\ХУВИЛБАР;

class НүүрХуудас {
    public function харуулах(): void {
        $гарчиг = мөрийг_товчлох("Энэ бол маш урт гарчиг бичвэр тул товчлогдоно", 20);
        echo $гарчиг;       // Энэ бол маш урт г...
        echo ХУВИЛБАР;      // 1.0.0
    }
}
?>

Бодит төслийн бүтэц

код
src/
├── App/
│   ├── Controllers/
│   │   ├── UserController.php     → namespace App\Controllers;
│   │   └── ProductController.php  → namespace App\Controllers;
│   ├── Models/
│   │   ├── User.php               → namespace App\Models;
│   │   └── Product.php            → namespace App\Models;
│   └── Services/
│       └── AuthService.php        → namespace App\Services;
└── Payment/
    └── Gateway.php                → namespace Payment;
php
<?php
// src/App/Services/AuthService.php
namespace App\Services;

use App\Models\User;

class AuthService {
    public function нэвтрэх(string $имэйл, string $нууц_үг): ?User {
        // Нэвтрэлт шалгах логик...
        return new User("Болд", $имэйл);
    }
}
?>

Namespace нь зөвхөн нэрийн мөргөлдөөнөөс хамгаалахаас гадна кодын бүтцийг тодорхой болгож, хамтран ажиллахад хялбарчилдаг.

Дараагийн хичээлд:

Exception зохицуулалтыг судална. try/catch/finally блокуудыг хэрхэн бичдэг, өөрийн Exception класс хэрхэн үүсгэдэг, алдааг тэнцвэртэй зохицуулах шилдэг дадлуудыг жишээгээр тайлбарлана.