Fayllar — file_get_contents, file_put_contents, fopen
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\nni olib tashlaydiFILE_SKIP_EMPTY_LINES— bo'sh qatorlarni tashlab ketadi
Faylga yozish
<?php
file_put_contents(__DIR__ . '/xabar.txt', "Salom, dunyo!");
[!WARNING]
file_put_contentsdefault 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 usulFILE_APPEND | LOCK_EX— log yozish uchunfopen+fgets+fclose— katta fayllarni qatorma-qatorfputcsv/fgetcsv— CSV ni qo'lda yasamang- Foydalanuvchi bergan nom bilan fayl ochmang — whitelist ishlating
Keyingi dars
25-dars: JSON — json_encode, json_decode