الانتقال بتطبيق من PHP 8.4 إلى PHP 8.5 خطوة صغيرة في أغلب الأحيان، لكن عبارة "في أغلب الأحيان" ليست خطة. يسرد دليل الترحيل الرسمي التغييرات غير المتوافقة مع الإصدارات السابقة والميزات المُهملة، ونختار في هذا الدليل أكثرها تأثيرًا في التطبيقات والخوادم الفعلية، ونبيّن كيف تجدها في شيفرتك، ثم نشرح تبديل خادم Debian أو Ubuntu دون توقف طويل.
إن كنت قادمًا من 8.3 أو أقدم فاعمل على كل دليل ترحيل وسيط بالترتيب (من 8.3 إلى 8.4 ثم من 8.4 إلى 8.5) بدل القفز إلى الأخير مباشرة.
التغييرات الكاسرة الأكثر احتمالًا
الإعدادات والمحرك
- أُزيل الإعداد
disable_classesلأنه كان يخلّ بافتراضات المحرك، والإعدادات التي ما زالت تضبطه لم تعد تحصل على الحماية المتوقعة منه. - أصبح OPcache جزءًا من الملف التنفيذي، فهو مدمج ومحمّل دائمًا، والسطر
zend_extension=opcache.soيولّد الآن تحذيرًا. احذف هذه الأسطر من أي إعدادات تنقلها من إصدارات أقدم، مع بقاءopcache.enableوopcache.enable_cliفاعلين. - تحذيرات جديدة عند التحويل بين الأنواع: تحويل عدد عشري (أو نص يشبهه) لا يمكن تمثيله عددًا صحيحًا يولّد تحذيرًا في التحويل الصريح والضمني، وكذلك تحويل
NAN. قد تبدأ الشيفرة التي تعالج أرقامًا غير موثوقة بتسجيل تحذيرات. - تفكيك قيم ليست مصفوفات (عدا
null) باستخدام[]أوlist()يولّد تحذيرًا. - السمات على أهداف غير صالحة: تطبيق
#[\Attribute]على صنف مجرد أو enum أو واجهة أو trait أصبح خطأً عند الترجمة بدل أن يفشل لاحقًا عبر الانعكاس. - لم تعد
class_alias()تقبلarrayأوcallableاسمًا مستعارًا.
الامتدادات
- PDO: وسائط المُنشئ المستخدمة مع
PDO::FETCH_CLASSتتبع الآن دلالاتcall_user_func_array()المعتادة، فالمفاتيح النصية تعمل وسائطَ مسماة. كما تغيّرت القيم العددية للثوابتFETCH_GROUPوFETCH_UNIQUEوFETCH_CLASSTYPEوFETCH_PROPS_LATEوFETCH_SERIALIZE، وهذا يهم فقط إن كانت الشيفرة تخزّن الأرقام أو تكتبها مباشرة بدل الثوابت. - الجلسات: كتابة بيانات جلسة يحتوي أحد مفاتيح
$_SESSIONفيها على الرمز|تولّد الآن تحذيرًا بدل الفشل الصامت، وأصبحتsession_start()أكثر صرامة في التحقق من مصفوفة الخيارات. - MySQLi: استدعاء مُنشئ
mysqliمرة ثانية على كائن مُنشأ مسبقًا يرمي الآنError. - Intl يتطلب ICU بالإصدار 57.1 أو أحدث، وmbstring يستخدم بيانات Unicode 17.0.
- الدوال القياسية: تمرير العدد
0وسيطًا للّغة فيsetlocale()يرمي الآنTypeError، ولم يعدArrayObjectيقبل قيم enum. - كثير من دوال Bzip2 وPOSIX وSockets وSNMP وTidy وغيرها أصبحت ترمي
ValueErrorعند تمرير قيم خارج النطاق أو تحتوي على بايت صفري، بعد أن كانت تتسامح معها.
إهمالات ينبغي تنظيفها
الميزات المُهملة تعمل في 8.5 لكنها تولّد رسائل E_DEPRECATED، وإصلاحها الآن يبقي السجلات مقروءة ويهيئ الشيفرة لإصدار رئيسي لاحق. أكثرها ظهورًا في الشيفرات القديمة:
- تنفيذ أوامر النظام بعلامة backtick (استخدم
shell_exec()صراحةً، والأفضل تجنب استدعاء الصدفة أصلًا). - التحويلات
(boolean)و(integer)و(double)و(binary). - عبارات
caseالمنتهية بفاصلة منقوطة بدل النقطتين. - استخدام
nullمفتاحًا في مصفوفة أو فيarray_key_exists()(استخدم نصًا فارغًا). - زيادة النصوص غير الرقمية بالمعامل
++(استخدمstr_increment()). - الدالتان
__sleep()و__wakeup()(إهمال مرن، والبديل__serialize()و__unserialize()). - استدعاءات التنظيف التي لم يعد لها أثر:
curl_close()وcurl_share_close()وfinfo_close()وimagedestroy()وxml_parser_free(). - الدالة
ReflectionProperty::setAccessible()وأخواتها في الانعكاس، إذ لم يعد لها أي أثر، وهي شائعة في مجموعات الاختبار والمكتبات القديمة. - الأسماء المستعارة
mysqli_execute()وsocket_set_timeout()، وتمرير قيم خارج النطاق من 0 إلى 255 إلىchr()، وتمرير نص ليس بايتًا واحدًا إلىord(). - مخطط DSN ذو البادئة
uri:في PDO، بسبب مخاطر تحميل DSN من روابط بعيدة. - اشتقاق
$_SERVER['argc']و$_SERVER['argv']من سلسلة الاستعلام خارج سطر الأوامر: اضبطregister_argc_argv=0واقرأ$_GETأو$_SERVER['QUERY_STRING']بدلًا من ذلك.
كيف تجدها في شيفرتك
ابدأ بعمليات بحث سريعة، ثم دع الأدوات والاختبارات تكمل المهمة. شغّل الأوامر من جذر المشروع مع استبعاد مجلد vendor/ لفحص شيفرتك أنت:
grep -rnE '\((boolean|integer|double|binary)\)' --include='*.php' --exclude-dir=vendor .
grep -rnE '\b(curl_close|curl_share_close|finfo_close|imagedestroy|xml_parser_free|mysqli_execute|socket_set_timeout)\s*\(' --include='*.php' --exclude-dir=vendor .
grep -rn 'setAccessible(' --include='*.php' --exclude-dir=vendor .
grep -rnE 'disable_classes|opcache\.so' /etc/php/ثم:
- افحص الصياغة بالملف التنفيذي الجديد. الأمر
php8.5 -lيترجم الملفات دون تشغيلها، ويقبل منذ PHP 8.3 عدة ملفات دفعة واحدة. يكشف أخطاء الصياغة لكنه لا يكشف ما يظهر أثناء التشغيل فقط.find . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 200 php8.5 -l | grep -v '^No syntax errors' - شغّل مجموعة الاختبارات على 8.5 مع إظهار رسائل الإهمال، بضبط
error_reporting = E_ALLوlog_errors = Onوdisplay_errors = Offفي بيئة الاختبار، ثم اقرأ السجل. - التحليل الساكن. أدوات مثل PHPStan تستطيع تحليل الشيفرة على أساس إصدار مستهدف (عبر المعامل
phpVersion)، فتأكد أن إصدار الأداة الذي تثبته يفهم PHP 8.5. - الاعتماديات. الأمر
composer prohibits php 8.5(واسمه المستعارwhy-not) يعرض الحزم التي تمنع قيودها الانتقال إلى PHP 8.5، فحدّثها أولًا.
تبديل الإصدار على خادم Debian أو Ubuntu
ثبّت 8.5 بجانب الإصدار الحالي، واختبره، ثم انقل الحركة إليه. في Ubuntu 26.04 LTS تتوفر حزم php8.5 في أرشيف التوزيعة نفسه. أما Debian 13 فيأتي مع 8.4، ويتطلب PHP 8.5 فيه حاليًا مستودعًا خارجيًا مثل packages.sury.org، فاقرأ تعليماته الرسمية واضبط تثبيت الأولوية (pinning) قبل إضافته.
sudo apt update
sudo apt install php8.5-fpm php8.5-cli php8.5-mysql php8.5-xml php8.5-mbstring php8.5-curl php8.5-intl
# compare loaded extensions with the old version
php8.4 -m > /tmp/mods-84.txt; php8.5 -m > /tmp/mods-85.txt; diff /tmp/mods-84.txt /tmp/mods-85.txtانقل تعديلاتك أنت فقط (إعدادات المجمّع في /etc/php/8.5/fpm/pool.d/ والملفات الصغيرة في conf.d/) لا ملف php.ini قديمًا بأكمله، ثم وجّه خادم الويب إلى المقبس الجديد:
# Nginx: in the PHP location block
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
sudo nginx -t && sudo systemctl reload nginx
# Apache with PHP-FPM
sudo a2disconf php8.4-fpm
sudo a2enconf php8.5-fpm
sudo apachectl configtest && sudo systemctl reload apache2أبقِ خدمة 8.4 FPM مثبتة وعاملة حتى تطمئن، فيصبح التراجع مجرد إعادة توجيه المقبس وإعادة التحميل. وتذكّر أن مهام cron وعمّال الطوابير تستخدم الأمر php الذي تديره حزم Debian عبر update-alternatives، فتحقق بالأمر php -v واضبطه صراحةً عند الحاجة بالأمر sudo update-alternatives --config php.
أخطاء شائعة
- ترقية PHP قبل ترقية إطار العمل أو نظام إدارة المحتوى، فراجع الإصدارات التي يدعمها المورّد.
- امتدادات ناقصة بعد التبديل، وتظهر عادةً في أخطاء من نوع "class not found" أو "function not found"، وأمر
diffأعلاه يكشفها. - نسخ إعدادات OPcache المضبوطة للإصدار القديم دون تمحيص، والأفضل البدء من الإعدادات الافتراضية للحزمة ثم إعادة ما قِسته فعلًا.
- نسيان العمليات الدائمة (الطوابير والمجدولات وsupervisor) التي تواصل تشغيل الملف التنفيذي القديم حتى يُعاد تشغيلها.
ما الذي ينبغي فعله
- اقرأ دليل الترحيل الرسمي من 8.4 إلى 8.5 كاملًا مرة واحدة، ودوّن البنود التي تمس شيفرتك.
- شغّل عمليات البحث وفحص الصياغة والاختبارات على 8.5 في بيئة تجريبية مع تسجيل كل رسائل الإهمال.
- أزل قيود Composer المانعة بمساعدة
composer prohibits php 8.5. - ثبّت 8.5 بجانب الإصدار الحالي، وبدّل مقبس FPM، وأبقِ الإصدار القديم جاهزًا للتراجع السريع.
- بعد التبديل راقب سجلات الأخطاء بضعة أيام، ثم أزل حزم PHP القديمة.
المصادر
- php.net/manual/en/migration85.php
- php.net/manual/en/migration85.incompatible.php
- php.net/manual/en/migration85.deprecated.php
- php.net/manual/en/migration85.other-changes.php
- php.net/releases/8.5/en.php
- php.net/manual/en/features.commandline.options.php
- getcomposer.org/doc/03-cli.md#prohibits-why-not
- phpstan.org/config-reference#phpversion
- packages.ubuntu.com/resolute/php8.5-fpm
- packages.debian.org/trixie/php
- salsa.debian.org/php-team/php/-/blob/debian/main/8.4/debian/php-fpm.conf
- salsa.debian.org/php-team/php/-/blob/debian/main/8.4/debian/php-cli.postinst.extra
Comments
0 total · 0 threads