مقالات علاء عامر

نقدم مجموعة شاملة من مقالات التعليمية الهامة في تطوير الويب لتحويل أفكارك إلى واقع رقمي

تحسين أداء تطبيقات PHP: استراتيجيات متقدمة

PHP 2025-12-31 علاء عامر

تحسين أداء تطبيقات PHP: استراتيجيات متقدمة

دليل متخصص من علاء عامر - مطور ومصمم مواقع وتطبيقات احترافية

تحسين الأداء هو جانب حاسم في تطوير تطبيقات PHP الناجحة. سرعة التطبيق تؤثر مباشرة على تجربة المستخدم وترتيب محركات البحث.

2️⃣ تحسين إعدادات PHP

أهم إعدادات php.ini للأداء:

; php.ini للإنتاج
; الذاكرة
memory_limit = 512M
max_execution_time = 30
max_input_time = 60

; OPcache (أهم شيء لتحسين الأداء)
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 12
opcache.max_accelerated_files = 60000
opcache.revalidate_freq = 0
opcache.validate_timestamps = 0  ; للإنتاج فقط
opcache.save_comments = 0
opcache.fast_shutdown = 1

; تحسين Session
session.save_handler = redis
session.save_path = "tcp://localhost:6379"

; إيقاف الأخطاء في الإنتاج
display_errors = 0
error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING
log_errors = 1
error_log = /var/log/php_errors.log

; تحسين رفع الملفات
post_max_size = 50M
upload_max_filesize = 50M
max_file_uploads = 20

; تحسين الشبكة
default_socket_timeout = 5

فئة لمراقبة الأداء:

<?php
// classes/PerformanceMonitor.php

class PerformanceMonitor
{
    private static $startTime;
    private static $startMemory;
    private static $queries = [];
    private static $checkpoints = [];

    public static function start()
    {
        self::$startTime = microtime(true);
        self::$startMemory = memory_get_usage(true);
    }

    public static function checkpoint($name)
    {
        self::$checkpoints[$name] = [
            'time' => microtime(true) - self::$startTime,
            'memory' => memory_get_usage(true) - self::$startMemory,
            'peak_memory' => memory_get_peak_usage(true)
        ];
    }

    public static function logQuery($sql, $executionTime)
    {
        self::$queries[] = [
            'sql' => $sql,
            'time' => $executionTime,
            'timestamp' => microtime(true)
        ];
    }

    public static function getReport()
    {
        $totalTime = microtime(true) - self::$startTime;
        $totalMemory = memory_get_usage(true) - self::$startMemory;
        $peakMemory = memory_get_peak_usage(true);

        return [
            'total_execution_time' => round($totalTime * 1000, 2) . 'ms',
            'memory_usage' => self::formatBytes($totalMemory),
            'peak_memory' => self::formatBytes($peakMemory),
            'query_count' => count(self::$queries),
            'queries' => self::$queries,
            'checkpoints' => self::$checkpoints,
            'opcache_status' => function_exists('opcache_get_status') ? opcache_get_status() : null
        ];
    }

    private static function formatBytes($bytes)
    {
        $units = ['B', 'KB', 'MB', 'GB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);

        return round($bytes / (1024 ** $pow), 2) . ' ' . $units[$pow];
    }

    public static function profileFunction($callback, $name = 'anonymous')
    {
        $startTime = microtime(true);
        $startMemory = memory_get_usage(true);

        $result = call_user_func($callback);

        $endTime = microtime(true);
        $endMemory = memory_get_usage(true);

        error_log(sprintf(
            "Profile [%s]: Time: %.2fms, Memory: %s",
            $name,
            ($endTime - $startTime) * 1000,
            self::formatBytes($endMemory - $startMemory)
        ));

        return $result;
    }
}

// الاستخدام
PerformanceMonitor::start();

// في بداية العملية
PerformanceMonitor::checkpoint('after_bootstrap');

// عند الانتهاء
PerformanceMonitor::checkpoint('before_response');
$report = PerformanceMonitor::getReport();

4️⃣ نظام Caching متقدم

Redis Cache Implementation:

<?php
// classes/CacheManager.php

class CacheManager
{
    private $redis;
    private $defaultTtl = 3600; // ساعة واحدة
    private $keyPrefix = 'app:';

    public function __construct($redisHost = 'localhost', $redisPort = 6379)
    {
        $this->redis = new Redis();
        $this->redis->connect($redisHost, $redisPort);
    }

    public function get($key, $default = null)
    {
        $value = $this->redis->get($this->keyPrefix . $key);

        if ($value === false) {
            return $default;
        }

        return json_decode($value, true);
    }

    public function set($key, $value, $ttl = null)
    {
        $ttl = $ttl ?? $this->defaultTtl;
        $encodedValue = json_encode($value);

        return $this->redis->setex($this->keyPrefix . $key, $ttl, $encodedValue);
    }

    public function remember($key, $callback, $ttl = null)
    {
        $value = $this->get($key);

        if ($value !== null) {
            return $value;
        }

        $value = call_user_func($callback);
        $this->set($key, $value, $ttl);

        return $value;
    }

    public function forget($key)
    {
        return $this->redis->del($this->keyPrefix . $key);
    }

    public function flush()
    {
        $keys = $this->redis->keys($this->keyPrefix . '*');
        if (!empty($keys)) {
            return $this->redis->del($keys);
        }
        return true;
    }

    // Cache Tags للتجميع
    public function tags($tags)
    {
        return new TaggedCache($this, (array)$tags);
    }

    // Cache بناءً على العمليات
    public function cacheQuery($sql, $params, $callback, $ttl = 600)
    {
        $key = 'query:' . md5($sql . serialize($params));

        return $this->remember($key, $callback, $ttl);
    }

    // Cache للصفحات الكاملة
    public function cachePage($uri, $callback, $ttl = 1800)
    {
        $key = 'page:' . md5($uri);

        return $this->remember($key, $callback, $ttl);
    }
}

class TaggedCache
{
    private $cache;
    private $tags;

    public function __construct(CacheManager $cache, array $tags)
    {
        $this->cache = $cache;
        $this->tags = $tags;
    }

    public function get($key, $default = null)
    {
        return $this->cache->get($this->taggedKey($key), $default);
    }

    public function set($key, $value, $ttl = null)
    {
        $taggedKey = $this->taggedKey($key);

        // إضافة المفتاح لكل tag
        foreach ($this->tags as $tag) {
            $this->cache->redis->sadd("tag:{$tag}", $taggedKey);
        }

        return $this->cache->set($taggedKey, $value, $ttl);
    }

    public function flush()
    {
        foreach ($this->tags as $tag) {
            $keys = $this->cache->redis->smembers("tag:{$tag}");
            if (!empty($keys)) {
                $this->cache->redis->del($keys);
                $this->cache->redis->del("tag:{$tag}");
            }
        }
    }

    private function taggedKey($key)
    {
        return 'tagged:' . implode(':', $this->tags) . ':' . $key;
    }
}

نظام File Cache للبيانات الثقيلة:

<?php
// classes/FileCache.php

class FileCache
{
    private $cacheDir;
    private $defaultTtl = 3600;

    public function __construct($cacheDir = 'cache')
    {
        $this->cacheDir = rtrim($cacheDir, '/');

        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
    }

    public function get($key, $default = null)
    {
        $filename = $this->getFilename($key);

        if (!file_exists($filename)) {
            return $default;
        }

        $data = file_get_contents($filename);
        $cached = unserialize($data);

        // التحقق من انتهاء الصلاحية
        if ($cached['expires'] > 0 && $cached['expires'] < time()) {
            unlink($filename);
            return $default;
        }

        return $cached['value'];
    }

    public function set($key, $value, $ttl = null)
    {
        $ttl = $ttl ?? $this->defaultTtl;
        $expires = $ttl > 0 ? time() + $ttl : 0;

        $cached = [
            'value' => $value,
            'expires' => $expires,
            'created' => time()
        ];

        $filename = $this->getFilename($key);
        $this->ensureDirectoryExists(dirname($filename));

        return file_put_contents($filename, serialize($cached), LOCK_EX) !== false;
    }

    public function delete($key)
    {
        $filename = $this->getFilename($key);

        if (file_exists($filename)) {
            return unlink($filename);
        }

        return true;
    }

    public function clear()
    {
        $this->deleteDirectory($this->cacheDir);
        mkdir($this->cacheDir, 0755, true);
        return true;
    }

    // Cache للصور المصغرة
    public function cacheImage($originalPath, $width, $height, $quality = 80)
    {
        $key = "image:" . md5($originalPath . $width . $height . $quality);
        $filename = $this->getFilename($key, 'jpg');

        if (file_exists($filename) && filemtime($filename) > filemtime($originalPath)) {
            return $filename;
        }

        // إنشاء صورة مصغرة
        $this->createThumbnail($originalPath, $filename, $width, $height, $quality);

        return $filename;
    }

    private function getFilename($key, $extension = 'cache')
    {
        $hash = md5($key);
        $dir1 = substr($hash, 0, 2);
        $dir2 = substr($hash, 2, 2);

        return "{$this->cacheDir}/{$dir1}/{$dir2}/{$hash}.{$extension}";
    }

    private function ensureDirectoryExists($dir)
    {
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
    }

    private function deleteDirectory($dir)
    {
        if (!is_dir($dir)) {
            return true;
        }

        $files = array_diff(scandir($dir), ['.', '..']);

        foreach ($files as $file) {
            $path = $dir . '/' . $file;
            is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
        }

        return rmdir($dir);
    }

    private function createThumbnail($source, $destination, $width, $height, $quality)
    {
        $imageInfo = getimagesize($source);
        $srcWidth = $imageInfo[0];
        $srcHeight = $imageInfo[1];
        $mimeType = $imageInfo['mime'];

        // إنشاء resource حسب نوع الصورة
        switch ($mimeType) {
            case 'image/jpeg':
                $srcImage = imagecreatefromjpeg($source);
                break;
            case 'image/png':
                $srcImage = imagecreatefrompng($source);
                break;
            case 'image/gif':
                $srcImage = imagecreatefromgif($source);
                break;
            default:
                return false;
        }

        // حساب الأبعاد الجديدة مع الحفاظ على النسب
        $aspectRatio = $srcWidth / $srcHeight;

        if ($width / $height > $aspectRatio) {
            $width = $height * $aspectRatio;
        } else {
            $height = $width / $aspectRatio;
        }

        // إنشاء الصورة الجديدة
        $destImage = imagecreatetruecolor($width, $height);
        imagecopyresampled($destImage, $srcImage, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight);

        // حفظ الصورة
        $this->ensureDirectoryExists(dirname($destination));
        imagejpeg($destImage, $destination, $quality);

        // تحرير الذاكرة
        imagedestroy($srcImage);
        imagedestroy($destImage);

        return true;
    }
}

6️⃣ HTTP Response Optimization

<?php
// classes/ResponseOptimizer.php

class ResponseOptimizer
{
    public static function enableGzipCompression()
    {
        if (!headers_sent() && extension_loaded('zlib') && !ob_get_length()) {
            ini_set('zlib.output_compression', 'On');
            ini_set('zlib.output_compression_level', 6);
        }
    }

    public static function setCacheHeaders($maxAge = 3600, $etag = null)
    {
        if (headers_sent()) return;

        // Cache Control
        header("Cache-Control: public, max-age={$maxAge}");
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $maxAge) . ' GMT');

        // ETag
        if ($etag) {
            header("ETag: \"{$etag}\"");

            if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
                $_SERVER['HTTP_IF_NONE_MATCH'] === "\"{$etag}\"") {
                http_response_code(304);
                exit;
            }
        }

        // Last Modified
        $lastModified = gmdate('D, d M Y H:i:s', time()) . ' GMT';
        header("Last-Modified: {$lastModified}");
    }

    public static function optimizeImages($imagePath, $quality = 80)
    {
        if (!file_exists($imagePath)) {
            return false;
        }

        $imageInfo = getimagesize($imagePath);
        $mimeType = $imageInfo['mime'];

        // تحقق من دعم المتصفح لـ WebP
        $supportsWebP = strpos($_SERVER['HTTP_ACCEPT'] ?? '', 'image/webp') !== false;

        if ($supportsWebP && $mimeType !== 'image/webp') {
            $webpPath = preg_replace('/\.[^.]+$/', '.webp', $imagePath);

            if (!file_exists($webpPath) || filemtime($imagePath) > filemtime($webpPath)) {
                self::convertToWebP($imagePath, $webpPath, $quality);
            }

            if (file_exists($webpPath)) {
                return $webpPath;
            }
        }

        return $imagePath;
    }

    private static function convertToWebP($source, $destination, $quality)
    {
        $imageInfo = getimagesize($source);
        $mimeType = $imageInfo['mime'];

        switch ($mimeType) {
            case 'image/jpeg':
                $image = imagecreatefromjpeg($source);
                break;
            case 'image/png':
                $image = imagecreatefrompng($source);
                break;
            default:
                return false;
        }

        if ($image) {
            imagewebp($image, $destination, $quality);
            imagedestroy($image);
            return true;
        }

        return false;
    }

    public static function sendOptimizedResponse($content, $contentType = 'text/html')
    {
        self::enableGzipCompression();

        $etag = md5($content);
        self::setCacheHeaders(3600, $etag);

        header("Content-Type: {$contentType}; charset=utf-8");
        header('Content-Length: ' . strlen($content));

        echo $content;
    }
}

💡 نصائح سريعة لتحسين الأداء

  1. استخدم OPcache دائماً - يحسن الأداء بنسبة 50-80%
  2. قم بالـ Profiling المنتظم - استخدم Xdebug أو Blackfire
  3. حسن استعلامات قاعدة البيانات - استخدم EXPLAIN لفهم الاستعلامات
  4. طبق Lazy Loading - لا تحمل البيانات إلا عند الحاجة
  5. استخدم CDN للملفات الثابتة
  6. فعل HTTP/2 لتحسين تحميل الأصول المتعددة

الخطوة التالية

تعلم Load Balancing و Microservices Architecture للتطبيقات الكبيرة.

📩 تحتاج مساعدة في تحسين أداء تطبيقك؟

PHP Performance Optimization Caching Database Speed
قسم المقالة
PHP

تحسين أداء تطبيقات PHP: استراتيجيات متقدمة

دليل شامل لتحسين أداء تطبيقات PHP مع تقنيات الـ caching، تحسين قواعد البيانات، وأفضل الممارسات.

تحسين أداء تطبيقات PHP: استراتيجيات متقدمة
01

التواصل والاستشارة

تواصل مباشر عبر الواتساب أو الهاتف لفهم احتياجات مشروعك بدقة.

02

التخطيط والجدولة

وضع خطة عمل واضحة مع جدول زمني محدد لكل مرحلة من المشروع.

03

البرمجة والتطوير

تطوير المشروع بأحدث التقنيات لضمان الأداء والأمان العاليين.

04

المراجعة والتسليم

ختبار شامل ومراجعة دقيقة قبل التسليم النهائي للمشروع.

علاء عامر
علاء عامر

مطور ويب محترف بخبرة تزيد عن 10 سنوات في بناء حلول رقمية مبتكرة.

هل تحتاج هذه الخدمة؟

تواصل معي الآن للحصول على استشارة مجانية وعرض سعر

تواصل عبر واتساب رضاكم هو هدفنا الأسمى

عروض إضافية

  • صيانة وتحديث المواقع

    نحافظ على موقعك آمنًا ومحدّثًا دائمًا

  • ربط الأنظمة وواجهات البرمجة

    نربط أنظمتك بواجهات برمجية قوية ومرنة

  • تصميم وتحسين قواعد البيانات

    استعلامات أسرع وهيكلة أوضح وأخطاء أقل

  • تأمين المواقع والحماية المتقدمة

    حماية موقعك من التهديدات السيبرانية

  • أتمتة العمليات والمهام البرمجية

    نؤتمت المهام المتكررة ونوفّر وقتك دائمًا

لديك استفسار؟

اتصل بنا الآن

00201014714795

راسلنا عبر البريد الإلكتروني

[email protected]