معالجة الملفات
تُخزّن قواعد البيانات البيانات المنظمة؛ بينما تُخزّن الملفات البيانات غير المنظمة — مثل السجلات وملفات التكوين وتقارير CSV والصور التي يرفعها المستخدمون. يمنحك هذا الدرس تحكماً كاملاً في الملفات والمجلدات في لغة PHP.
1. قراءة الملفات
PHP
<?php
// Method 1: file_get_contents() — read an entire file in one line
$content = file_get_contents('hello.txt');
echo $content;
// Method 2: fopen + fread — streamed reading (for large files)
$handle = fopen('hello.txt', 'r');
$content = fread($handle, filesize('hello.txt'));
fclose($handle);
// Method 3: Read line by line (most memory-efficient)
$handle = fopen('data.txt', 'r');
while (($line = fgets($handle)) !== false) {
echo trim($line) . "<br>";
}
fclose($handle);
// Method 4: file() — read all lines into an array at once
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
print_r($lines);
?>
| الطريقة | الأنسب لـ | الذاكرة |
|---|---|---|
file_get_contents() |
الملفات الصغيرة (ملفات التكوين، JSON) | كلها دفعة واحدة |
fopen + fread |
ملفات متوسطة الحجم | خاضعة للرقابة |
fopen + fgets |
الملفات الكبيرة (السجلات، ملفات CSV) | منخفض |
file() |
معالجة الملفات الصغيرة سطراً سطراً | معالجتها دفعة واحدة |
2. كتابة الملفات
PHP
<?php
// file_put_contents() — write a file in one line
file_put_contents('notes.txt', "Today I learned PHP file handling\n");
// Append mode (third parameter: FILE_APPEND)
file_put_contents('notes.txt', "Now I can append content\n", FILE_APPEND);
// Exclusive lock for writing (prevents concurrent conflicts)
file_put_contents('counter.txt', $count, LOCK_EX);
// fwrite — fine-grained control
$handle = fopen('log.txt', 'a'); // 'a' = append mode
fwrite($handle, date("Y-m-d H:i:s") . " — User logged in\n");
fclose($handle);
?>
▶ مثال: نظام تسجيل بسيط
PHP
<?php
class Logger {
public function __construct(
private string $logFile
) {}
public function info(string $message): void {
$this->write('INFO', $message);
}
public function error(string $message): void {
$this->write('ERROR', $message);
}
public function warning(string $message): void {
$this->write('WARNING', $message);
}
private function write(string $level, string $message): void {
$time = date("Y-m-d H:i:s");
$line = "[{$time}] [{$level}] {$message}\n";
file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
}
public function getRecent(int $lines = 20): array {
if (!file_exists($this->logFile)) {
return [];
}
$all = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
return array_slice($all, -$lines);
}
}
$log = new Logger('app.log');
$log->info('App started');
$log->warning('Config file not found, using defaults');
$log->error('Database connection timed out');
$log->info('App finished');
echo "<h3>Recent Logs</h3><pre>" . implode("\n", $log->getRecent(10)) . "</pre>";
?>
3. الكشف عن الملفات
PHP
<?php
$file = 'test.txt';
// Existence checks
var_dump(file_exists($file)); // bool
var_dump(is_file($file)); // Also check it's a file (not a directory)
var_dump(is_dir($file)); // Check if it's a directory
// Read/Write checks
var_dump(is_readable($file)); // Can it be read?
var_dump(is_writable($file)); // Can it be written to?
// File information
echo filesize($file) . " bytes<br>"; // Size
echo filemtime($file); // Last modified time (Unix timestamp)
echo date("Y-m-d H:i:s", filemtime($file)) . "<br>"; // Formatted date
echo pathinfo($file, PATHINFO_EXTENSION); // txt
?>
▶ مثال: ذاكرة التخزين المؤقت للملفات
PHP
<?php
class FileCache {
private string $cacheDir;
public function __construct(string $dir = 'cache') {
$this->cacheDir = $dir;
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
}
}
public function get(string $key, int $ttl = 3600): mixed {
$file = "{$this->cacheDir}/{$key}.cache";
if (!file_exists($file)) return null;
if (time() - filemtime($file) > $ttl) {
unlink($file);
return null;
}
return unserialize(file_get_contents($file));
}
public function set(string $key, mixed $value): void {
$file = "{$this->cacheDir}/{$key}.cache";
file_put_contents($file, serialize($value), LOCK_EX);
}
}
$cache = new FileCache();
$cache->set('config', ['app_name' => 'MyBlog', 'version' => '1.0']);
print_r($cache->get('config'));
?>
4. مرجع سريع لعمليات الملفات
PHP
<?php
$src = 'source.txt';
$dst = 'backup.txt';
// Copy
copy($src, $dst);
// Rename / Move
rename($src, 'new-name.txt');
rename('/tmp/upload.txt', '/var/www/files/upload.txt'); // Move
// Delete
unlink('old-file.txt');
// Directory operations
mkdir('new-folder', 0755, true); // true = recursive creation
rmdir('empty-folder'); // Only deletes empty directories
// Traverse a directory
foreach (scandir('uploads') as $item) {
if ($item !== '.' && $item !== '..') {
echo "{$item} — " . (is_dir("uploads/{$item}") ? 'Directory' : 'File') . "<br>";
}
}
// Use glob for pattern-based file search
$images = glob('uploads/*.{jpg,png,gif}', GLOB_BRACE);
echo "Found " . count($images) . " images";
?>
5. قراءة وكتابة ملفات CSV
يُعد CSV التنسيق العالمي لتبادل البيانات — حيث يمكن لبرنامج Excel فتحه، كما يمكن لأي لغة برمجة قراءته وكتابته:
PHP
<?php
// === Writing CSV ===
$data = [
['Name', 'Age', 'City'],
['John', 25, 'Beijing'],
['Jane', 22, 'Shanghai'],
['Bob', 28, 'Guangzhou'],
];
$handle = fopen('users.csv', 'w');
// Write UTF-8 BOM (helps Excel recognize the encoding correctly)
fwrite($handle, "\xEF\xBB\xBF");
foreach ($data as $row) {
fputcsv($handle, $row);
}
fclose($handle);
echo "CSV file generated ✅<br>";
// === Reading CSV ===
$handle = fopen('users.csv', 'r');
// Skip BOM
fseek($handle, 3);
// Read headers
$headers = fgetcsv($handle);
while (($row = fgetcsv($handle)) !== false) {
// Use headers as keys
$item = array_combine($headers, $row);
echo "{$item['Name']}, {$item['Age']} years old, lives in {$item['City']}<br>";
}
fclose($handle);
?>
▶ مثال: تصدير البيانات بتنسيق CSV
PHP
<?php
function exportToCSV(array $data, string $filename): void {
header('Content-Type: text/csv; charset=utf-8');
header("Content-Disposition: attachment; filename={$filename}");
$output = fopen('php://output', 'w');
fwrite($output, "\xEF\xBB\xBF"); // BOM
// Headers
if (!empty($data)) {
fputcsv($output, array_keys($data[0]));
}
// Data
foreach ($data as $row) {
fputcsv($output, $row);
}
fclose($output);
}
// exportToCSV($usersData, 'users_export.csv');
?>
6. قفل الملفات (منع عمليات الكتابة المتزامنة)
PHP
<?php
class Counter {
private string $file;
public function __construct(string $file = 'counter.dat') {
$this->file = $file;
if (!file_exists($this->file)) {
file_put_contents($this->file, 0);
}
}
public function increment(): int {
$handle = fopen($this->file, 'c+');
// Acquire an exclusive lock (other processes wait)
if (flock($handle, LOCK_EX)) {
$count = (int)fread($handle, 100);
$count++;
// Go back to the beginning of the file
fseek($handle, 0);
ftruncate($handle, 0); // Clear it
fwrite($handle, (string)$count);
flock($handle, LOCK_UN); // Unlock
fclose($handle);
return $count;
}
fclose($handle);
return -1;
}
}
?>
❓ أسئلة شائعة
س كيف أختار بين
file_get_contents() وfopen + fgets؟ج استخدم
file_get_contents() للملفات الصغيرة (<1 ميغابايت) — سطر واحد ويكون الأمر قد انتهى. استخدم fgets() لقراءة الملفات الكبيرة (عشرات الآلاف من أسطر السجل) سطراً سطراً — فهي لا تستهلك الكثير من الذاكرة. إذا كنت لا تعرف الحجم، فابدأ باستخدام fopen.س هل تظهر الأحرف الصينية مشوهة في برنامج Excel؟
ج أضف علامة BOM لترميز UTF-8 (
"\xEF\xBB\xBF") في بداية ملف CSV. يقرأ برنامج Excel الملفات باستخدام الترميز المحلي بشكل افتراضي — وتُعلم علامة BOM البرنامج بأن الملف مكتوب بترميز UTF-8.س هل قفل الملف باستخدام
flock ضروري فعلاً؟ج بالتأكيد، عندما تقوم عدة عمليات بقراءة وكتابة الملف نفسه في وقت واحد. فقد تتعرض العدادات وذاكرات التخزين المؤقت والسجلات إلى حالات التنافس، حيث تُقرأ القيم بعد أن تكون عملية أخرى قد عدّلتها بالفعل — في حالة عدم وجود قفل.
📖 ملخص
file_get_contents()يقرأ ملفًا في سطر واحد، وfile_put_contents()يكتب ملفًا في سطر واحدfopen + fgetsيقرأ سطراً سطراً — وهو الخيار الأفضل للملفات الكبيرةfile_put_contents($file, $data, FILE_APPEND | LOCK_EX)يُلحق بأمانfile_exists()/is_readable()/is_writable()— يرجى التحقق قبل التشغيل- CSV:
fputcsv()للكتابة،fgetcsv()للقراءة، وتمنع علامة BOM تشويه النص في Excel flock($handle, LOCK_EX)يوفر قفلًا حصريًّا لمنع تعارضات الكتابة المتزامنة
📝 تمارين
- اكتب برنامجًا لحساب عدد الزوار: مع كل تحديث للصفحة، يزداد العدد بمقدار 1، ويتم تخزين هذا العدد في ملف.
- إنشاء سجل زوار بسيط: يتم إرسال رسالة عبر نموذج → إضافتها إلى ملف → قراءة وعرض جميع الرسائل من الملف (مع الطوابع الزمنية).
- قم بتصدير جدول المستخدمين إلى ملف CSV (قراءة البيانات من MySQL → إنشاء ملف CSV → توفير رابط للتنزيل).



