Fayllar — file_get_contents, file_put_contents, fopen

~15 daq · PHP · Fayllar, Sana va Xatolar

Muammodan boshlaylik

Har doim ham ma'lumotlar bazasi kerak emas. Ba'zan oddiy fayl yetarli:

  • Saytga kirishlar yoki xatolar jurnali (log)
  • Sozlamalar fayli
  • Excel uchun CSV hisobot
  • Kichik loyihada mehmonlar kitobi

PHP da fayl bilan ishlashning ikki darajasi bor: oddiy (bir qatorda butun faylni o'qish/yozish) va past darajali (fopen — qatorma-qator, katta fayllar uchun).


Butun faylni o'qish

<?php

$matn = file_get_contents(__DIR__ . '/xabar.txt');
echo $matn;

Fayl topilmasa — false qaytaradi va Warning chiqaradi:

<?php

$yol = __DIR__ . '/xabar.txt';

if (!is_file($yol)) {
    exit("Fayl topilmadi");
}

$matn = file_get_contents($yol);

Qatorlar massivi sifatida:

<?php

$qatorlar = file(__DIR__ . '/ismlar.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// ['Ali', 'Vali', 'Sami']
  • FILE_IGNORE_NEW_LINES — har bir qator oxiridagi \n ni olib tashlaydi
  • FILE_SKIP_EMPTY_LINES — bo'sh qatorlarni tashlab ketadi

Faylga yozish

<?php

file_put_contents(__DIR__ . '/xabar.txt', "Salom, dunyo!");

[!WARNING] file_put_contents default holatda faylni to'liq qayta yozadi — eski mazmun yo'qoladi. Fayl bo'lmasa — yaratadi.

Oxiriga qo'shish uchun — FILE_APPEND:

<?php

function logYoz(string $xabar): void
{
    $qator = date('Y-m-d H:i:s') . " | $xabar" . PHP_EOL;
    file_put_contents(__DIR__ . '/app.log', $qator, FILE_APPEND | LOCK_EX);
}

logYoz("Foydalanuvchi #42 tizimga kirdi");
logYoz("Buyurtma #1043 yaratildi");

LOCK_EX — yozish paytida faylni qulflaydi. Ikki foydalanuvchi bir vaqtda yozsa, qatorlar aralashib ketmaydi.


fopen — katta fayllar uchun

file_get_contents butun faylni xotiraga yuklaydi. 2 GB lik log fayli bo'lsa — PHP xotirasi tugaydi:

Fatal error: Allowed memory size of 134217728 bytes exhausted

Katta fayllarni qatorma-qator o'qish kerak:

<?php

$f = fopen(__DIR__ . '/katta.log', 'r');

if ($f === false) {
    exit("Faylni ochib bo'lmadi");
}

$xatolar = 0;
while (($qator = fgets($f)) !== false) {
    if (str_contains($qator, 'ERROR')) {
        $xatolar++;
    }
}

fclose($f);
echo "Xatolar soni: $xatolar";

Xotirada bir vaqtda faqat bitta qator turadi — fayl hajmi qanchalik katta bo'lmasin.

Ochish rejimlari

Rejim Ma'nosi Fayl bo'lmasa Mavjud mazmun
r Faqat o'qish Xato Saqlanadi
w Faqat yozish Yaratadi O'chiriladi
a Oxiriga yozish Yaratadi Saqlanadi
x Yangi fayl yaratish Yaratadi Fayl bo'lsa — xato
r+ O'qish + yozish Xato Saqlanadi
<?php

$f = fopen(__DIR__ . '/eslatma.txt', 'a');
fwrite($f, "Yangi qator" . PHP_EOL);
fclose($f);

CSV fayllar

CSV — vergul bilan ajratilgan jadval. Excel va Google Sheets ochadi.

Yozish:

<?php

$buyurtmalar = [
    ['id' => 1, 'mijoz' => 'Ali Valiyev', 'summa' => 250000],
    ['id' => 2, 'mijoz' => 'Malika, Toshkent', 'summa' => 1200000],
];

$f = fopen(__DIR__ . '/hisobot.csv', 'w');
fputcsv($f, ['ID', 'Mijoz', 'Summa']);           // sarlavha
foreach ($buyurtmalar as $b) {
    fputcsv($f, [$b['id'], $b['mijoz'], $b['summa']]);
}
fclose($f);

fputcsv vergul yoki qo'shtirnoq bor qiymatlarni ("Malika, Toshkent") avtomatik to'g'ri o'raydi. Qo'lda implode(',', ...) qilsangiz — CSV buziladi.

O'qish:

<?php

$f = fopen(__DIR__ . '/hisobot.csv', 'r');
$sarlavha = fgetcsv($f);

while (($qator = fgetcsv($f)) !== false) {
    $yozuv = array_combine($sarlavha, $qator);
    echo "{$yozuv['Mijoz']}: {$yozuv['Summa']}" . PHP_EOL;
}
fclose($f);

array_combine sarlavhalarni kalit qilib, har bir qatorni assotsiativ massivga aylantiradi.


Fayl va papkalar bilan amallar

<?php

$yol = __DIR__ . '/data/hisobot.csv';

is_file($yol);        // fayl mavjudmi
is_dir(__DIR__ . '/data');   // papka mavjudmi
filesize($yol);       // hajmi baytlarda
filemtime($yol);      // oxirgi o'zgartirilgan vaqt (timestamp)

copy($yol, __DIR__ . '/data/zaxira.csv');
rename($yol, __DIR__ . '/data/eski.csv');   // nomini o'zgartirish yoki ko'chirish
unlink(__DIR__ . '/data/eski.csv');         // o'chirish

if (!is_dir(__DIR__ . '/data/2026')) {
    mkdir(__DIR__ . '/data/2026', 0755, true);   // true — ichma-ich papkalarni ham yaratadi
}

$fayllar = glob(__DIR__ . '/data/*.csv');   // barcha .csv fayllar ro'yxati

echo basename('/var/www/data/hisobot.csv');   // hisobot.csv
echo pathinfo('hisobot.csv', PATHINFO_EXTENSION);   // csv

Xavfsizlik: Path Traversal

<?php

// ❌ XAVFLI
$fayl = $_GET['fayl'];
echo file_get_contents(__DIR__ . '/docs/' . $fayl);

Hujumchi ?fayl=../../config.php yoki ?fayl=../../../../etc/passwd yuboradi. ../ — "bir papka yuqoriga". U docs/ dan chiqib, istalgan faylni o'qiydi — baza paroli bilan birga.

Himoya — ruxsat berilgan ro'yxat:

<?php

$ruxsat = ['qollanma', 'shartlar', 'maxfiylik'];
$fayl = $_GET['fayl'] ?? '';

if (!in_array($fayl, $ruxsat, true)) {
    http_response_code(404);
    exit("Topilmadi");
}

echo file_get_contents(__DIR__ . "/docs/$fayl.txt");

Yoki basename() bilan papka qismini olib tashlash. Lekin ruxsat ro'yxati (whitelist) — eng ishonchli.


Nima uchun shunday?

Nima uchun fopen/fclose kerak, agar file_get_contents ancha qulay bo'lsa?

file_get_contents ichida aynan fopen → o'qish → fclose bajariladi. Bu qulay "o'ram". Lekin u bitta qoidaga asoslangan: "butun fayl xotiraga sig'adi". Kichik fayllar uchun bu to'g'ri. Gigabaytlik log, millionlab qatorli CSV import — u yerda faqat oqim (stream) bilan ishlash mumkin. PHP ikki darajani ham beradi: oddiy holatlarga qulay, murakkablariga to'liq nazorat.


Tez-tez uchraydigan xatolar

Nisbiy yo'l — file_get_contents('data.txt') skript qayerdan ishga tushirilganiga bog'liq. Doim __DIR__.

Ruxsat yo'q:

Warning: file_put_contents(/var/www/data/log.txt): Failed to open stream: Permission denied

Linux serverda veb-server (www-data) foydalanuvchisi papkaga yoza olishi kerak.

w rejimi bilan muhim faylni ochish — mazmuni darhol o'chadi, hatto hech narsa yozmasangiz ham.


Xulosa

Eslab qoling:

  • file_get_contents / file_put_contents — kichik fayllar uchun oddiy usul
  • FILE_APPEND | LOCK_EX — log yozish uchun
  • fopen + fgets + fclose — katta fayllarni qatorma-qator
  • fputcsv / fgetcsv — CSV ni qo'lda yasamang
  • Foydalanuvchi bergan nom bilan fayl ochmang — whitelist ishlating

Keyingi dars

25-dars: JSON — json_encode, json_decode