7-bo‘lim
Funksiyalar
Turlar bilan e'lon qilish, standart va nomli argumentlar, yopilmalar, o'q funksiyalari va qiymat qaytarish qoidalari.
Ushbu bo‘lim mundarijasi
Funksiya - kodni qayta ishlatishdan ko'ra ko'proq narsa. Yaxshi yozilgan funksiya imzosining o'zi bilan nima qilishini aytadi.
Turlarni e'lon qilish #
// Har bir misol qat'iy turlar rejimida ishlaydi.
// Imzo hamma narsani aytadi: nima kiradi, nima chiqadi
function soliqHisobla(int $summa, float $foiz = 12.0): int
{
return (int) round($summa * $foiz / 100);
}
// Hech narsa qaytarmaydigan funksiya - void
function jurnalgaYoz(string $xabar): void
{
echo " [jurnal] {$xabar}\n";
}
// null ham qaytarishi mumkin - ? belgisi
function foydalanuvchiTop(int $id): ?string
{
$baza = [1 => "Husanboy", 2 => "Malika"];
return $baza[$id] ?? null;
}
echo "Soliq (standart 12%): " . soliqHisobla(1000000) . "\n";
echo "Soliq (15%): " . soliqHisobla(1000000, 15.0) . "\n";
echo "\n";
jurnalgaYoz("hisob-kitob tugadi");
echo "\n";
foreach ([1, 2, 99] as $id) {
$ism = foydalanuvchiTop($id);
printf(" id=%-3d %s\n", $id, $ism ?? "(topilmadi)");
}
Soliq (standart 12%): 120000
Soliq (15%): 150000
[jurnal] hisob-kitob tugadi
id=1 Husanboy
id=2 Malika
id=99 (topilmadi)
Turlarsiz funksiya nima qilishini faqat o'qib bilish mumkin:
function hisobla($a, $b) { ... } // nima kiradi? nima chiqadi?
Turlar bilan esa imzoning o'zi javob beradi:
function hisobla(int $summa, float $foiz): int { ... }
Bu uch foyda beradi:
| Foyda | Izoh |
|---|---|
| Xato erta topiladi | Noto'g'ri tur - darhol TypeError |
| Muharrir yordam beradi | Avtoto'ldirish ishlaydi |
| Hujjat kerak emas | Imzo o'zi hujjat |
Foydali tur belgilari:
| Yozuv | Ma'nosi |
|---|---|
?string | Satr yoki null |
int|string | Ikkisidan biri (PHP 8) |
void | Hech narsa qaytarmaydi |
never | Umuman qaytmaydi (exit yoki throw) |
static | O'sha sinf namunasi |
array | Massiv (elementlar turi ko'rsatilmaydi) |
array ning kamchiligi - u ichidagi turni aytmaydi.
Buni izohda ko'rsatish an'anasi bor:
/** @param list<int> $sonlar */
function yigindi(array $sonlar): int { ... }
Muharrirlar va statik tahlilchilar bu izohni o'qiydi.
Standart va nomli argumentlar #
function xabarYubor(
string $kimga,
string $matn,
string $turi = "xabar",
bool $shoshilinch = false,
bool $nusxaSaqla = true
): string {
$belgi = $shoshilinch ? "!" : " ";
$nusxa = $nusxaSaqla ? "saqlandi" : "saqlanmadi";
return sprintf("%s [%s] %s -> %s (%s)", $belgi, $turi, $matn, $kimga, $nusxa);
}
echo "Faqat majburiy argumentlar:\n";
echo xabarYubor("Malika", "Yig'ilish 10:00 da") . "\n";
echo "\nHamma argument tartib bilan:\n";
echo xabarYubor("Nodira", "Server ishlamayapti", "ogohlantirish", true, false) . "\n";
echo "\nNomli argumentlar - faqat kerakligini beramiz:\n";
echo xabarYubor(
kimga: "Husanboy",
matn: "Zaxira nusxa tayyor",
shoshilinch: true
) . "\n";
echo "\nTartibni ham o'zgartirish mumkin:\n";
echo xabarYubor(
matn: "Hisobot yuborildi",
kimga: "Aziza",
nusxaSaqla: false
) . "\n";
Faqat majburiy argumentlar:
[xabar] Yig'ilish 10:00 da -> Malika (saqlandi)
Hamma argument tartib bilan:
! [ogohlantirish] Server ishlamayapti -> Nodira (saqlanmadi)
Nomli argumentlar - faqat kerakligini beramiz:
! [xabar] Zaxira nusxa tayyor -> Husanboy (saqlandi)
Tartibni ham o'zgartirish mumkin:
[xabar] Hisobot yuborildi -> Aziza (saqlanmadi)
Eski PHP da oraliqdagi bitta argumentni o'zgartirish uchun hammasini yozish kerak edi:
xabarYubor("Husanboy", "matn", "xabar", true);
// ^^^^^^ faqat shu kerak edi,
// lekin oldingisini ham yozdik
Nomli argumentlar bilan:
xabarYubor(kimga: "Husanboy", matn: "matn", shoshilinch: true);
Ayniqsa bool argumentlar uchun foydali. Taqqoslang:
saqla($fayl, true, false, true); // nimani anglatadi?
saqla($fayl, ustigaYoz: true, zaxira: false); // endi aniq
Uch qoida:
- Nomli argumentlar pozitsionlardan keyin keladi.
- Argument nomi - bu ommaviy interfeys: uni o'zgartirsangiz chaqiruvchi kod buziladi.
- Ichki PHP funksiyalarida ham ishlaydi:
str_contains(haystack: $a, needle: $b).
Ikkinchi qoidani unutmang - parametr nomini o'zgartirish endi buzuvchi o'zgarish hisoblanadi.
O'zgaruvchan sonli argumentlar #
// ... - istalgancha argument qabul qiladi
function yigindi(int ...$sonlar): int
{
return array_sum($sonlar);
}
function engKattasi(int $birinchi, int ...$qolganlari): int
{
return max($birinchi, ...$qolganlari);
}
echo "yigindi(): " . yigindi() . "\n";
echo "yigindi(1,2,3): " . yigindi(1, 2, 3) . "\n";
echo "yigindi(10,20,30): " . yigindi(10, 20, 30) . "\n";
echo "\n";
// Massivni argumentlarga yoyish - yana ... belgisi
$ballar = [88, 94, 76, 91];
echo "Massivdan yoyish: " . yigindi(...$ballar) . "\n";
echo "Eng kattasi: " . engKattasi(...$ballar) . "\n";
echo "\n";
// Assotsiativ massivni nomli argumentlarga yoyish
function kartaYasa(string $ism, string $shahar, int $yosh): string
{
return "{$ism}, {$yosh} yosh, {$shahar}";
}
$malumot = ["ism" => "Kamola", "yosh" => 23, "shahar" => "Namangan"];
echo "Nomli yoyish: " . kartaYasa(...$malumot) . "\n";
yigindi(): 0
yigindi(1,2,3): 6
yigindi(10,20,30): 60
Massivdan yoyish: 349
Eng kattasi: 94
Nomli yoyish: Kamola, 23 yosh, Namangan
Yopilmalar va use #
$soliqFoizi = 12;
// Oddiy anonim funksiya - tashqi o'zgaruvchini KO'RMAYDI
$oddiy = function (int $summa): int {
// $soliqFoizi bu yerda mavjud emas
return $summa;
};
// use bilan - qiymat NUSXASI olinadi
$nusxaBilan = function (int $summa) use ($soliqFoizi): int {
return (int) round($summa * $soliqFoizi / 100);
};
echo "use bilan (12%): " . $nusxaBilan(1000000) . "\n";
// Foizni o'zgartiramiz
$soliqFoizi = 20;
echo "Foiz 20 ga o'zgardi, lekin funksiya hali ham: "
. $nusxaBilan(1000000) . "\n";
echo "Sabab: use qiymatni YARATILISH paytida nusxalaydi.\n";
echo "\n";
// Havola bilan - o'zgarishni ko'radi
$hisoblagich = 0;
$oshir = function () use (&$hisoblagich): void {
$hisoblagich++;
};
$oshir();
$oshir();
$oshir();
echo "Havola bilan hisoblagich: {$hisoblagich}\n";
echo "\n";
// O'q funksiyasi - use SHART EMAS, o'zi ko'radi
$chegirma = 15;
$hisobla = fn(int $narx): int => (int) round($narx * (100 - $chegirma) / 100);
echo "O'q funksiyasi (15% chegirma): " . $hisobla(200000) . "\n";
use bilan (12%): 120000
Foiz 20 ga o'zgardi, lekin funksiya hali ham: 120000
Sabab: use qiymatni YARATILISH paytida nusxalaydi.
Havola bilan hisoblagich: 3
O'q funksiyasi (15% chegirma): 170000
function va fn - qaysi birini tanlashfunction () use (...) | fn() => | |
|---|---|---|
| Tashqi o'zgaruvchi | use bilan oshkora | Avtomatik ko'radi |
| Tana | Ko'p qatorli blok | Bitta ifoda |
| Havola olish | use (&$x) mumkin | Mumkin emas |
return | Yozish kerak | Yozilmaydi |
fn qisqa, lekin uning avtomatik ushlashi ham
afzallik, ham xavf.
Afzallik: array_map(fn($x) => $x * $koeff, $m) -
juda qisqa.
Xavf: funksiya qaysi tashqi o'zgaruvchilarga bog'liqligi ko'rinmaydi. Uzun kodda bu chalkashlik tug'diradi.
Amaliy qoida:
| Vaziyat | Tanlov |
|---|---|
Bitta ifoda, map/filter ichida | fn |
| Bir necha qator | function |
| Tashqi o'zgaruvchini o'zgartirish | function use (&$x) |
| Bog'liqlik aniq ko'rinishi kerak | function use ($x) |
Muhim: fn ham qiymatni nusxa qilib oladi, havola
qilib emas. Ya'ni tashqi o'zgaruvchini o'zgartira
olmaydi.
Massiv qaytarish va yoyish #
function statistikaHisobla(array $sonlar): array
{
if ($sonlar === []) {
return ["soni" => 0, "jami" => 0, "ortacha" => 0.0, "eng" => 0];
}
return [
"soni" => count($sonlar),
"jami" => array_sum($sonlar),
"ortacha" => round(array_sum($sonlar) / count($sonlar), 2),
"eng" => max($sonlar),
];
}
$natija = statistikaHisobla([88, 94, 76, 91, 83]);
echo "Massiv sifatida:\n";
foreach ($natija as $kalit => $qiymat) {
printf(" %-10s %s\n", $kalit, $qiymat);
}
echo "\n";
// Massivni o'zgaruvchilarga yoyish
["soni" => $soni, "ortacha" => $ortacha] = $natija;
echo "Yoyilgan: {$soni} ta talaba, o'rtacha {$ortacha}\n";
echo "\n";
// Indeksli massivni yoyish
function minMax(array $sonlar): array
{
return [min($sonlar), max($sonlar)];
}
[$eng_kam, $eng_kop] = minMax([88, 94, 76, 91, 83]);
echo "Eng kam: {$eng_kam}, eng ko'p: {$eng_kop}\n";
Massiv sifatida:
soni 5
jami 432
ortacha 86.4
eng 94
Yoyilgan: 5 ta talaba, o'rtacha 86.4
Eng kam: 76, eng ko'p: 94
PHP funksiyasi faqat bitta qiymat qaytaradi. Lekin uchta muqobil bor:
1. Assotsiativ massiv (yuqorida ko'rdik) - eng keng tarqalgan. Kalitlar natijani hujjatlashtiradi.
2. Obyekt - eng aniq usul:
final class Statistika {
public function __construct(
public readonly int $soni,
public readonly float $ortacha,
) {}
}
Bu 12-bo'limda ko'riladi. Uning afzalligi: muharrir xossalarni biladi va xato yozsangiz darhol aytadi.
3. Havola orqali chiqish parametri:
function ajrat(string $s, ?string &$xato = null): ?array
Bu usuldan qoching. U funksiyaning yashirin ta'siri bor degani va kodni o'qishni qiyinlashtiradi. 15-bo'limda uning o'rniga istisnolardan foydalanamiz.
Rekursiya #
function katalogniChiz(array $tuzilma, int $daraja = 0): void
{
foreach ($tuzilma as $nom => $ichi) {
echo str_repeat(" ", $daraja);
if (is_array($ichi)) {
echo "[+] {$nom}\n";
katalogniChiz($ichi, $daraja + 1);
} else {
echo " - {$nom} ({$ichi} KB)\n";
}
}
}
$loyiha = [
"app" => [
"Models" => ["Foydalanuvchi.php" => 4, "Buyurtma.php" => 7],
"Views" => ["bosh.php" => 12],
],
"public" => [
"index.php" => 2,
"assets" => ["style.css" => 24],
],
"README.md" => 3,
];
katalogniChiz($loyiha);
echo "\n";
// Rekursiv hajm hisoblash
function jamiHajm(array $tuzilma): int
{
$jami = 0;
foreach ($tuzilma as $ichi) {
$jami += is_array($ichi) ? jamiHajm($ichi) : $ichi;
}
return $jami;
}
echo "Jami hajm: " . jamiHajm($loyiha) . " KB\n";
[+] app
[+] Models
- Foydalanuvchi.php (4 KB)
- Buyurtma.php (7 KB)
[+] Views
- bosh.php (12 KB)
[+] public
- index.php (2 KB)
[+] assets
- style.css (24 KB)
- README.md (3 KB)
Jami hajm: 52 KB
- Turlarsiz funksiya yozing, keyin unga turlarni qo'shing.
- Noto'g'ri turdagi argument bering - qanday xato chiqadi?
?stringqaytaruvchi funksiya yozing vanullni tekshiring.- Beshta argumentli funksiyani nomli argumentlar bilan chaqiring.
- Argumentlar tartibini o'zgartirib chaqiring.
...$sonlarbilan istalgancha argument qabul qiling.- Massivni
...bilan argumentlarga yoying. use ($x)vause (&$x)farqini tekshiring.- Xuddi shu kodni
fnbilan yozing - havola ishlaydimi? - Rekursiv funksiya bilan ko'p o'lchovli massiv hajmini hisoblang.
Xulosa #
- Funksiya imzosi - uning eng ishonchli hujjati; har doim turlarni yozing.
?string- satr yokinull;void- qaytarmaydi;never- umuman qaytmaydi.- Nomli argumentlar (PHP 8) oraliqdagi argumentlarni o'tkazib yuborish imkonini beradi.
- Argument nomi ommaviy interfeys - uni o'zgartirish buzuvchi o'zgarish.
...$argsistalgancha argument qabul qiladi;f(...$massiv)esa uni yoyadi.- Assotsiativ massivni
...bilan nomli argumentlarga yoyish mumkin. use ($x)qiymat nusxasini oladi - keyingi o'zgarishni ko'rmaydi.use (&$x)havola oladi;fnesa havola ola olmaydi.fntashqi o'zgaruvchilarni avtomatik ko'radi - qisqa, lekin bog'liqlik yashirin.- Ko'p qiymat qaytarish uchun massiv yoki obyekt ishlating, chiqish parametridan qoching.
- Massivni
[$a, $b] = f()shaklida o'zgaruvchilarga yoyish mumkin.
Keyingi bo'limda formalar va HTTP so'rov ma'lumotlarini qabul qilishni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.