7-bo‘lim

Funksiyalar

Turlar bilan e'lon qilish, standart va nomli argumentlar, yopilmalar, o'q funksiyalari va qiymat qaytarish qoidalari.

🕑 13 daqiqa o‘qish 📄 691 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Turlarni e'lon qilish
  2. Standart va nomli argumentlar
  3. O'zgaruvchan sonli argumentlar
  4. Yopilmalar va use
  5. Massiv qaytarish va yoyish
  6. Rekursiya
  7. Xulosa

Funksiya - kodni qayta ishlatishdan ko'ra ko'proq narsa. Yaxshi yozilgan funksiya imzosining o'zi bilan nima qilishini aytadi.

Turlarni e'lon qilish #

PHP
// Har bir misol qat'iy turlar rejimida ishlaydi.
PHP
// 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)");
}
Natija
Soliq (standart 12%):  120000
Soliq (15%):           150000

  [jurnal] hisob-kitob tugadi

  id=1   Husanboy
  id=2   Malika
  id=99  (topilmadi)
Har doim turlarni yozing

Turlarsiz funksiya nima qilishini faqat o'qib bilish mumkin:

PHP
function hisobla($a, $b) { ... }      // nima kiradi? nima chiqadi?

Turlar bilan esa imzoning o'zi javob beradi:

PHP
function hisobla(int $summa, float $foiz): int { ... }

Bu uch foyda beradi:

FoydaIzoh
Xato erta topiladiNoto'g'ri tur - darhol TypeError
Muharrir yordam beradiAvtoto'ldirish ishlaydi
Hujjat kerak emasImzo o'zi hujjat

Foydali tur belgilari:

YozuvMa'nosi
?stringSatr yoki null
int|stringIkkisidan biri (PHP 8)
voidHech narsa qaytarmaydi
neverUmuman qaytmaydi (exit yoki throw)
staticO'sha sinf namunasi
arrayMassiv (elementlar turi ko'rsatilmaydi)

array ning kamchiligi - u ichidagi turni aytmaydi. Buni izohda ko'rsatish an'anasi bor:

PHP
/** @param list<int> $sonlar */
function yigindi(array $sonlar): int { ... }

Muharrirlar va statik tahlilchilar bu izohni o'qiydi.

Standart va nomli argumentlar #

PHP
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";
Natija
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)
Nomli argumentlar (PHP 8) nimani hal qiladi

Eski PHP da oraliqdagi bitta argumentni o'zgartirish uchun hammasini yozish kerak edi:

PHP
xabarYubor("Husanboy", "matn", "xabar", true);
//                              ^^^^^^ faqat shu kerak edi,
//                              lekin oldingisini ham yozdik

Nomli argumentlar bilan:

PHP
xabarYubor(kimga: "Husanboy", matn: "matn", shoshilinch: true);

Ayniqsa bool argumentlar uchun foydali. Taqqoslang:

PHP
saqla($fayl, true, false, true);              // nimani anglatadi?
saqla($fayl, ustigaYoz: true, zaxira: false); // endi aniq

Uch qoida:

  1. Nomli argumentlar pozitsionlardan keyin keladi.
  2. Argument nomi - bu ommaviy interfeys: uni o'zgartirsangiz chaqiruvchi kod buziladi.
  3. 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 #

PHP
// ... - 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";
Natija
yigindi():          0
yigindi(1,2,3):     6
yigindi(10,20,30):  60

Massivdan yoyish:   349
Eng kattasi:        94

Nomli yoyish:       Kamola, 23 yosh, Namangan
Funksiya imzosining har bir qismi nima uchun function soliqHisobla(int $summa, float $foiz = 12.0): int Aniq nom Fe'l + ob'ekt: nima qiladi Argument turi Noto'g'ri tur - darhol xato Standart Ixtiyoriy argument Qaytish turi Nima qaytishi aniq Yomon imzo function hisobla($a, $b, $c = null) Kodni o'qimasdan hech narsa bilib bo'lmaydi Yaxshi imzo function soliqHisobla(int $s, float $f): int Hujjat o'qish shart emas Yaxshi funksiyaning uch belgisi 1. Bitta ish qiladi 2. Nomi shu ishni aytadi 3. Yashirin ta'siri yo'q Uchinchisi eng muhimi: funksiya global holatni jimgina o'zgartirmasin.
Imzo - funksiyaning eng qisqa va eng ishonchli hujjati

Yopilmalar va use #

PHP
$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";
Natija
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 tanlash
function () use (...)fn() =>
Tashqi o'zgaruvchiuse bilan oshkoraAvtomatik ko'radi
TanaKo'p qatorli blokBitta ifoda
Havola olishuse (&$x) mumkinMumkin emas
returnYozish kerakYozilmaydi

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:

VaziyatTanlov
Bitta ifoda, map/filter ichidafn
Bir necha qatorfunction
Tashqi o'zgaruvchini o'zgartirishfunction use (&$x)
Bog'liqlik aniq ko'rinishi kerakfunction use ($x)

Muhim: fn ham qiymatni nusxa qilib oladi, havola qilib emas. Ya'ni tashqi o'zgaruvchini o'zgartira olmaydi.

Massiv qaytarish va yoyish #

PHP
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";
Natija
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
Ko'p qiymat qaytarish - PHP da uch usul

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:

PHP
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:

PHP
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 #

PHP
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";
Natija
[+] 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
Amaliy topshiriq
  1. Turlarsiz funksiya yozing, keyin unga turlarni qo'shing.
  2. Noto'g'ri turdagi argument bering - qanday xato chiqadi?
  3. ?string qaytaruvchi funksiya yozing va null ni tekshiring.
  4. Beshta argumentli funksiyani nomli argumentlar bilan chaqiring.
  5. Argumentlar tartibini o'zgartirib chaqiring.
  6. ...$sonlar bilan istalgancha argument qabul qiling.
  7. Massivni ... bilan argumentlarga yoying.
  8. use ($x) va use (&$x) farqini tekshiring.
  9. Xuddi shu kodni fn bilan yozing - havola ishlaydimi?
  10. Rekursiv funksiya bilan ko'p o'lchovli massiv hajmini hisoblang.

Xulosa #

  • Funksiya imzosi - uning eng ishonchli hujjati; har doim turlarni yozing.
  • ?string - satr yoki null; 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.
  • ...$args istalgancha 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; fn esa havola ola olmaydi.
  • fn tashqi 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.

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.