Scope, anonim funksiyalar va arrow function (fn)
Muammodan boshlaylik
O'tgan darslarda bu xatoni ko'rdik:
<?php
$valyuta = "so'm";
function narx($n)
{
return $n . " " . $valyuta;
}
echo narx(5000);
// Warning: Undefined variable $valyuta
$valyuta yuqorida aniq e'lon qilingan. Nega funksiya uni ko'rmaydi? Va usort, array_map larda yozgan fn($x) => ... aslida nima edi? Bu darsda ikkalasiga javob beramiz.
Scope — o'zgaruvchining ko'rinish doirasi
Scope — o'zgaruvchi qayerda "yashaydi" va qayerdan ko'rinadi.
PHP da qoida juda oddiy: har bir funksiya — alohida xona. Funksiya ichida yaratilgan o'zgaruvchi faqat shu funksiya ichida yashaydi. Tashqaridagi o'zgaruvchilar esa funksiya ichiga kirmaydi.
<?php
$x = 10; // global scope
function test()
{
$y = 20; // local scope — faqat test() ichida
echo $x; // Warning: Undefined variable $x
}
test();
echo $y; // Warning: Undefined variable $y
Hayotiy o'xshatma: mehmonxona xonasi. Har bir xonaning o'z narsalari bor. Xonaga kirganingizda faqat o'zingiz olib kirgan narsalar (parametrlar) bilan ishlaysiz. Chiqib ketganingizda xonadagi hamma narsa tozalanadi.
Nima uchun shunday?
JavaScript va Python da funksiya tashqi o'zgaruvchilarni ko'radi. PHP da nima uchun yo'q?
Bu ataylab qilingan himoya. Katta loyihada yuzlab fayl va minglab o'zgaruvchi bor. Agar har bir funksiya istalgan global o'zgaruvchini ko'rsa va o'zgartira olsa — biror funksiya tasodifan $user ni o'zgartirib qo'yishi va saytning butunlay boshqa qismida xato chiqishi mumkin. PHP da funksiya faqat o'ziga aniq berilgan narsalar bilan ishlaydi. Natijada funksiyani o'qish uchun faqat uning o'zini o'qish yetarli.
To'g'ri yechim — parametr
<?php
$valyuta = "so'm";
function narx(int $n, string $valyuta): string
{
return "$n $valyuta";
}
echo narx(5000, $valyuta); // 5000 so'm
Funksiyaga nima kerak bo'lsa — parametr orqali bering. Bu 99% holatlarda to'g'ri yo'l.
global kalit so'zi — nima uchun ishlatmaslik kerak
<?php
$valyuta = "so'm";
function narx($n)
{
global $valyuta; // tashqi o'zgaruvchini ichkariga "olib kirish"
return "$n $valyuta";
}
Bu ishlaydi, lekin funksiya endi yashirin bog'liqlikka ega: e'loniga qarab unga $valyuta kerakligini bilib bo'lmaydi. Eski WordPress kodida ko'p uchraydi (global $wpdb;). Yangi kodda — ishlatmang.
static — chaqiruvlar orasida qiymatni saqlash
Odatda funksiya tugaganda ichidagi o'zgaruvchilar o'chadi. static o'zgaruvchi esa saqlanib qoladi:
<?php
function hisoblagich(): int
{
static $son = 0; // faqat birinchi chaqiruvda 0 bo'ladi
$son++;
return $son;
}
echo hisoblagich(); // 1
echo hisoblagich(); // 2
echo hisoblagich(); // 3
Real ishlatish — og'ir hisobni bir marta bajarib, natijani eslab qolish (keshlash):
<?php
function sozlamalar(): array
{
static $kesh = null;
if ($kesh === null) {
$kesh = json_decode(file_get_contents('config.json'), true); // faqat bir marta o'qiladi
}
return $kesh;
}
Anonim funksiyalar (closure)
Nomsiz funksiya. Uni o'zgaruvchiga saqlash yoki boshqa funksiyaga argument qilib berish mumkin:
<?php
$salom = function (string $ism): string {
return "Salom, $ism!";
}; // ← oxirida ; bor, chunki bu qiymat berish
echo $salom("Kamola"); // Salom, Kamola!
Eng ko'p ishlatiladigan joy — array_map, array_filter, usort kabi funksiyalarga berish:
<?php
$sonlar = [1, 2, 3, 4, 5, 6];
$juftlar = array_filter($sonlar, function ($n) {
return $n % 2 === 0;
});
// [1 => 2, 3 => 4, 5 => 6]
use — tashqi o'zgaruvchini olib kirish
Anonim funksiya ham tashqi o'zgaruvchilarni ko'rmaydi. Ammo use bilan aniq olib kirish mumkin:
<?php
$minNarx = 100000;
$qimmatlar = array_filter($mahsulotlar, function ($m) use ($minNarx) {
return $m['narx'] >= $minNarx;
});
use ($minNarx) — "bu funksiyaga $minNarx ning nusxasini ber". Bu global dan farqli — bog'liqlik ochiq ko'rinib turibdi.
Arrow function: fn (PHP 7.4+)
Qisqa anonim funksiyalar uchun ixcham yozuv:
<?php
$minNarx = 100000;
// Odatiy anonim funksiya
$qimmatlar = array_filter($mahsulotlar, function ($m) use ($minNarx) {
return $m['narx'] >= $minNarx;
});
// Arrow function — aynan bir xil natija
$qimmatlar = array_filter($mahsulotlar, fn($m) => $m['narx'] >= $minNarx);
fn ning xususiyatlari:
fn(parametrlar) => ifoda—returnva{}yozilmaydi- Tashqi o'zgaruvchilarni avtomatik ko'radi —
usekerak emas - Faqat bitta ifoda — ko'p qatorli mantiq uchun oddiy
functionishlating
<?php
$qqs = 0.12;
$narxlar = [100000, 250000];
$qqsBilan = array_map(fn($n) => $n * (1 + $qqs), $narxlar);
// [112000, 280000]
usort($foydalanuvchilar, fn($a, $b) => $a['yosh'] <=> $b['yosh']);
Qaysi birini tanlash?
| Holat | Tanlov |
|---|---|
| Ko'p joyda ishlatiladigan mantiq | Oddiy nomli function |
array_map / filter / usort uchun qisqa shart |
fn() => |
| Bir necha qatorli mantiq, bir marta ishlatiladi | function () use (...) { } |
| Chaqiruvlar orasida xotira kerak | static o'zgaruvchi |
Tez-tez uchraydigan xatolar
Anonim funksiyadan keyin ; ni unutish:
<?php
$f = function () {
return 1;
} // ❌ Parse error
use bilan olingan qiymatni o'zgartirishni kutish:
<?php
$jami = 0;
$qosh = function ($n) use ($jami) {
$jami += $n; // faqat nusxa o'zgaradi
};
$qosh(5);
echo $jami; // 0
Asl o'zgaruvchini o'zgartirish kerak bo'lsa — use (&$jami). Lekin odatda yaxshiroq yo'l — natijani return qilish.
fn ichida ko'p qator yozishga urinish:
<?php
$f = fn($x) => {
$y = $x * 2;
return $y;
}; // ❌ Parse error — fn faqat bitta ifoda
Xulosa
Eslab qoling:
- Har bir funksiya — alohida scope; tashqi o'zgaruvchilar ko'rinmaydi
- Kerakli qiymatni parametr orqali bering;
globaldan qoching static— chaqiruvlar orasida saqlanadigan o'zgaruvchifunction () use ($x) { }— anonim funksiya, tashqi qiymatusebilanfn($x) => ...— qisqa, tashqi o'zgaruvchilarni avtomatik ko'radi, faqat bitta ifoda
Keyingi dars
17-dars: 1-4 bo'lim mashqlari