جديد PHP7 من مميزات ومن تغييرات ومن تحسينات
قام فريق تطوير PHP بتحسينات جبارة في PHP 7 حيث تم زيادة سرعتها إلى الضعف تخيل معي أن PHP 7 سرعتها الآن ضعف سرعة PHP 5.6 والفضل يعود إلى المحرك المستخدم لتطوير PHP حيث ان نسخة PHP 7 تم بنائها على Zend Engine جديد كليا كان الهدف الأساسي القوة والمرونة والسرعة وايضا دعم أفضل لـ64-bit وليس هذا فقط ماتقدمه PHP 7 حيث تم أيضا إضافة مميزات جديدة من دوال و كلاسات قيمة تسرع من أعمالك البرمجية وتسهلها و تحسين عمل وظائف سابقة وتطويرها للأفضل ومن أهم التطورات بهذه النسخة أنه تم إزالة العديد من المكتبات والإضافات القديمة الغير مستخدمة سنستعرض جميع المميزات الجديدة واهم جوانبها بأمثلة ميسرة وبسيطة لفهمها من الناحية البرمجية
قبل أن نبدأ قمت بتثبيت PHP 7 على جهازي بإستخدام هذه المكتبة php7dev وهي تعتمد بعملها على vagrant و VirtualBox وجميعهم مجانية وسهل التركيب مازالت PHP7 بمراحل التطوير وقريبا بهذا الشهر سوف يتم إصدار النسخة النهائية مالم يكن هنالك طارئ يمنع ذلك
تحديد نوع المتغيرات المدخلة على أي دالة Scalar type declarations
اصبح من الممكن في PHP7 تحديد نوع المتغيرات عند ادخالها بأي دالة لديك ليتم معالجتها بشكل صحيح لنفرض ان لديك دالة تقوم بعملية حسابية مثلا جمع وترغب ان تكون جميع المدخلات عبارة عن ارقام لتعمل الدالة بشكل سليم بدون أي مشاكل مع PHP7 اصبح سهلا تحديد النوع المطلوب إدخاله للدالة لتعمل او سوف ينتج خطأ عند عمل الكود يبلغ المستخدم انك لم تقم بإدخال النوع الصحيح للدالة لتعمل بدون مشاكل طبعا لتسهل عليك أكثر سابقا في PHP5 كانت يطلق على هذه الميزة Type Hints ولكن عيبها انها كانت محدودة على انواع قليلة من البيانات مثل class و array و callable و self و interface تم تطويرها في PHP7 لتدعم انواع اكثر مثل string و boolean و integer و float
يوجد طريقتين لعمل هذه الخاصية الأولى coercive وهي الإفتراضية و الطريقة الثانية strict
بالنسبة للطريقة الأولى coercive وهي الإفتراضية فان PHP ستحاول ان تكون مرنة وتقوم بتحويل النوع المدخل الى النوع الذي قمت بتحديده عند تعريفك للدالة فإن تم التحويل بنجاح سوف تعمل الدالة بدون مشاكل وان لم يتم التحويل سوف ينتج خطأ من نوع TypeError
مثال بسيط لتوضح الصورة لهذه الميزة
<?php
// Coercive mode
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
في هذا المثال سيكون الناتج كالتالي
لاحظ بهذا المثال طلبنا ان يكون النوع المدخل ارقام صحيحة باستخدام المفتاح int ولكن عند إستخدام الدالة زودناها بارقام صحيحة وارقام عشرية ونص بالرقم ٣ طبعا PHP7 ستقوم بتحويل هذه الأنواع الى أعداد صحيحة ثم استخدامها داخل الدالة لتعمل بشكل سليم ولكن
عند إستخدام الطريقة الثانية strict ويتم تعريفها داخل الملف باستخدام الدالة declare فإن التحقق سيكون صارم وغير مرن بحيث يجب ان تكون جميع المتغيرات المدخلة على الدالة بنفس النوع المحدد او أنه سينتج خطأ عند عمل الكود يخبرك ان النوع المدخل خطأ
نفس المثال السابق ولكن بتفعيل الخاصية strict
<?php
// Strict mode
declare(strict_types=1);
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
في هذا المثال سيكون الناتج كالتالي
ملاحظة: عند استخدام strict داخل الملف فإنه سيؤثر على جميع العمليات في PHP داخل الملف عند معالجتها لتكون اكثر صرامة وبدون مرونة فلن تقوم PHP بالتحويل بين الأنواع لإستخدامها ولكن سينتج خطأ مباشرة عند إدخال أي نوع خاطئ
تحديد نوع القيم المرجعة عند إستخدام أي دالة Return type declarations
في PHP7 تم تطوير هذه الميزة لتسمح لك بتحديد نوع المخرجات او القيم المرجعة بعد معالجتها داخل الدالة مثلا لديك دالة وترغب ان يكون الناتج دائما رقم صحيح حتى لو قمت بإدخال أرقام عشرية فإن هذه الميزة تسمح لك بتحديد نوع الناتج بكل سهولة
ملاحظة: هذه الميزه شبيه بعملها مثل Scalar type declarations فانها ستعمل افتراضيها تحت coercive mode اي ستكون مرنة او تحت strict mode عند تعريفها بالملف وتكون صارمة بالتحقق من أنواع البيانات
مثال بسيط لتوضح الفكرة أكثر
<?php
// Coercive mode
function sum($a, $b): int {
return $a + $b;
}
// Note that an int will be returned.
var_dump(sum(1, 2.5));
الناتج سيكون كالتالي عند عمل الكود
لو تلاحظ بالمثال ادخلنا احد القيم عشرية ومع ذلك ناتج الجمع كان عدد صحيح والسبب اننا قمنا بتحديد نوع القيمة المرجعة بعد معالجتها ان تكون من نوع عدد صحيح باستخدام المفتاح int
ولكن عند تفعيل strict mode
<?php
//Strict mode
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
// Note that an Error will be returned.
var_dump(sum(1, 2.5));
فإن الناتج سيكون كالتالي
عامل Null coalesce operator (??)
في البرمجة اصبح شائعا استخدام عامل ternary مع دالة isset وذلك للتحقق من قيمة أي متغير إذا كانت موجودة وليست NULL فإنه سوف يتم إرجاع القيمة الموجودة او نقوم بإرجاع قيمة أخرى
مثال على استخدام isset مع عامل ternary وهما خاصية قديمة في PHP مفيد عن التعامل مع النماذج ومعالجتها
<?php
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
هذا المثال سوف يتحقق من وجود
$_GET['user']
إن كان قيمته موجودة وليست من النوع NULL سيتم استخدام القيمة المدخلة للمتغير username وإن كانت القيمة NULL او غير موجودة سيتم تعيين قيمة username الى nobody
اصبح في PHP7 تنفيذ هذا الأمر بكل سهولة بإستخدام عامل Null coalesce (??)
نفس المثال السابق ممكن تنفيذه بالتالي
<?php
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
وأيضا تستطيع التحقق من قيم متعددة وإرجاع القيمة الموجودة والتي لايكون محتواها NULL كالتالي
<?php
// Coalesces can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
في هذا المثال سوف تقوم PHP7 بالتحقق من قيم المتغيرات بالترتيب وعندما يتحقق الشرط أي ان القيمة موجودة وليست NULL سوف يتم استخدامها مباشرة
مثلا لو قيمة
$_GET['user']
معرفة وليست NULL فانه سيتم تعيينه كقيمة للمتغير username وفي حال عدم تحقق الشرط سيتم التحقق من
$_POST['user']
فإن كان معرف وليس NULL سيتم تعيينه كقيمة للمتغير username بالأخير إن لم يتحقق الشرط فإنه سيتم تعيين قيمة username إلى nobody
عامل Spaceship operator <=>
عامل مقارنة جديد في PHP7 وظيفته المقارنة بين (تعبيرين expressions) سيكون ناتج هذه المقارنة إما -1 او 0 او 1
مثلا عند المقارنة بين متغيرين المتغير a والمتغير b سيكون ناتج المقارنة بالإعتماد على قيم المتغيرين كالتالي
- سيكون الناتج -1 إن كان المتغير a اصغر من b
- سيكون الناتج 0 إن كان المتغير a يساوي b
- سيكون الناتج 1 إن كان المتغير a اكبر من b
مثال بسيط لتوضح الصورة أكثر
<?php
// Integers
echo 1 <=> 1; // 0 equal
echo 1 <=> 2; // -1 less than
echo 2 <=> 1; // 1 greater than
// Floats
echo 1.5 <=> 1.5; // 0 equal
echo 1.5 <=> 2.5; // -1 less than
echo 2.5 <=> 1.5; // 1 greater than
// Strings
echo "a" <=> "a"; // 0 equal
echo "a" <=> "b"; // -1 less than
echo "b" <=> "a"; // 1 greater than
تعريف مصفوفة كثابت Constant arrays بإستخدام الدالة define
اصبح بإمكانك تعريف مصفوفة بكثابت اي ان جميع قيم المصفوفة يتكون متغيرات من نوع constatnt باستخدام الدالة define في PHP 5.6 كان من الممكن تعريف المصفوفة على انها constatnt باستخدام المفتاح const فقط ولكن في PHP7 اصبح من الممكن استخدام الدالة define
مثال بسيط
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
ناتج عمل الكود كالتالي
تعريف كلاسات مجهولة Anonymous classes
الآن أصبح بإمكانك تعريف كلاسات مجهولة أي لم يسبق ان تم تعريفها من قبل بإستخدام new class مفيدة إذا كنت ترغب بإستخدام كلاس لمرة واحدة داخل مشروعك ولاترغب بكتابة ملف جديد وتعرف الكلاس بداخله تحت مسمى معين ثم إستدعائه ليتم إستخدامه الآن تستطيع مباشرة تعريف الكلاس بشكل مجهول في PHP7
مثال بسيط لتوضح الصورة
<?php
// new Anonymous class and assigne it to $newClass
$newClass = new class(10) {
private $num;
public function __construct($num)
{
$this->num = $num;
}
};
var_dump($newClass);
ناتج عمل الكود كالتالي
في السابق كان يجب ان نقوم بتعريف الكلاس ثم عمل نسخه من هذا الكلاس باستخدام الممفتاح new وتعيينه كقيمة لمتغير لينتج لدينا كائن نتعامل معه بكل سهولة يوجد بالموقع سلسلة مقالات توضح البرمجة الكائنية للفائدة ومعرفتها بشكل أفضل
دعم طباعة رموز Unicode بالنصوص
في PHP7 أصبح بإمكانك طباعة Unicode codepoint بكل سهولة بإستخدام Unicode codepoint escape syntax
مثال بسيط لتوضح الصورة
<?php
echo "\u{aa}";
echo "\u{0000aa}"; //(same as before but with optional leading 0's)
echo "\u{9999}";
طبعا سيتم طباعة أي Unicode codepoint صحيح مع إمكانية تجاهل الأصفار التي تأتي بالبداية
الناتج سيكون كالتالي
ربط دالة بكائن بإستخدام Closure::call
هي طريقة مختصرة لربط عمل دالة باستدعاء كائن Object داخلها وتنفيذ محتواها في السابق كنا نستخدم bindTo لربط الكلاس المراد تضمينه داخل الدالة لتنفيذ آوامر الدالة بالشكل المرغوب
مثال بسيط
<?php
class A {private $x = 1;}
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
في هذا المثال قمنا بإنشاء كلاس باسم A ثم أنشائنا متغير getXCB وبداخله دالة بسيطة ستقوم بإرجاع قيمة x وهذا المتغير عباره عن porperty لكائن لتعمل هذه الدالة بشكل سليم يجب ان نقوم بربط أي كائن يحتوي على property بمسمى x لتقوم الدالة بإرجاع القيمة المطلوبة وبإستخدام bindTo نسطيع ربط الكائن الصحيح بهذه الدالة لتعمل بدون مشاكل
المميز في PHP7 اصبحت هذه العملية ابسط و أوضح باستخدام call لإنشاء الربط مثال بسيط لشكل الكود في PHP7
<?php
class A {private $x = 1;}
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);
النتيجة لعمل المثالين ستكون متشابهة كالتالي
فلترة للكائنات عند استخدام الدالة unserialize
تم إضافة هذه الميزة في PHP7 لزيادة الأمان عند إستخدام الدالة unserialize عندما تستخدم على كائنات objects من مصادر غير موثوقة فهي تمنع امكانية حقن أي أكواد غير مرغوب فيها حيث يحدد المطور ماهي الكلاسات التي يرغب بعمل دالة unserialize عليها
مثال بسيط لتوضح الصورة
<?php
//Clasess
class MyClass
{
public $name = 'ali';
};
class MyClass2{};
class MyClass3{};
//instantiate the class and Serilize it into String
$foo = serialize(new MyClass);
//Print the serialized String
echo $foo;
echo "<br>"; //HTML tag
// converts all objects into __PHP_Incomplete_Class object
$data = unserialize($foo, ["allowed_classes" => false]);
//Print the unserialized string
var_dump($data);
في هذا المثال قمنا بإنشاء مجموعة من الكلاسات ثم بعد ذلك أنشائنا متغير بإسم foo وبداخله قمنا بعمل serialize للكلاس MyClass بعدها طبعنا قيمة المتغير سيكون قيمته
O:7:"MyClass":1:{s:4:"name";s:3:"ali";}
ثم بعد ذلك عرفنا متغير جديد بإسم data وقمنا بداخله عمل unserialize للمتغير foo مع عمل فلتر بعدم عمل الدالة وفك أي كائن يحمل الكلاس MyClass كما تلاحظ أصبحت الدالة unserialize تقبل مدخلين الأول المتغير المراد عمل الدالة عليه والثاني الفلتر المراد تطبيقة عند عمل الدالة
ناتج عمل الكود السابق سيكون كالتالي
والسبب انه لم نسمح بعمل الدالة unserialize على MyClass ولذلك سيتم إدراجها تحت object(__PHP_Incomplete_Class) ولن يتم تنفيذ محتواها
تستطيع إستخدام أكثر من فلتر مثلا إذا كنت ترغب بالسماح بجميع انواع الكائنات و الكلاسات كل ماعليك هو تغيير قيمة allowed_classes من false إلى true
وتسطيع أيضا إدخال مجموعة من الكلاسات التي ترغب بعمل دالة unserialize عليهم دفعة واحد بتغير قيمة allowed_classes الى مصفوفة تحمل مسميات الكلاسات
مثال لتوضيح انواع الفلاتر الممكن إستخدامها
<?php
//Clasess
class MyClass
{
public $name = 'ali';
};
class MyClass2{};
class MyClass3{};
//instantiate the class and Serilize it into String
$foo = serialize(new MyClass);
//Print the serialized String
echo $foo;
echo "<br>"; //HTML tag
// converts all objects into __PHP_Incomplete_Class object
$data = unserialize($foo, ["allowed_classes" => false]);
//Print the unserialized string
var_dump($data);
echo "<br>"; //HTML tag
// converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
//Print the unserialized string
var_dump($data);
echo "<br>"; //HTML tag
// default behaviour (same as omitting the second argument) that accepts all classes
$data = unserialize($foo, ["allowed_classes" => true]);
//Print the unserialized string
var_dump($data);
بالمثال الأول لم تعمل الدالة وتم حفظ الكائن داخل __PHP_Incomplete_Class ولكن بالمثالين الآخرين عملت بدون مشاكل وتم عمل unserialize لهم ليرجعوا لشكلهم الطبيعي
ناتج عمل الكود كالتالي
كلاس IntlChar
عبارة عن كلاس جديد في PHP7 للتعامل مع Unicode ويحتوي على عدد من Methods الأفعال الممكن تطبيقها على أي Unicode
مثال بسيط لتوضح الصورة
<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo '<br>'; // HTML tag
echo IntlChar::charName('@');
echo '<br>'; // HTML tag
var_dump(IntlChar::ispunct('!'));
echo '<br>'; // HTML tag
ناتج عمل الكود كالتالي
ملاحظة: لعمل هذا الكود بدون مشكل يجب ان تكون هذه المكتبة Intl مثبتة
زيادة مرونة الدالة assert بإضافة Expectations
تم زيادة مرونة دالة الإختبار assert وإضافة Expectations لها مما يسمح لك بإدخال كائن لتعريف نوع الخطأ ورسالة الخطأ التي يتم عرضها في السابق كان المدخل الثاني لهذه الدالة يجب ان يكون نص لعرض رسالة الخطأ اما الآن أصبح بإمكانك إدراج كائن Object ليقوم بدوره بعرض الخطأ Throwable عند فشل الإختبار
مثال بسيط لتوضح الصورة
<?php
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(false, new CustomError('Some error message'));
ناتج عمل هذا الكود كالتالي
أيضا تم زيادة مرونة هذه الدالة وأصبح بإمكانك إدخال مقارانات بينما في السابق كنا نستطيع ادخال النصوص أو قيم boolean لوحدها فقط
مثال لمقارنة بين true و flase نفس عمل المثال السابق ولكن غيرنا قيمة اول مدخل في الدالة
<?php
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(true == false, new CustomError('True is not false!'));
تستطيع مشاهدة المزيد عن هذه الدالة من هنا assert
إستدعاء مجموعة كلاسات أو دوال أو ثوابت بإستخدام Group use declarations
لو كان لدينا مجموعة كلاسات أو دوال أو ثوابت معرفة داخل namespace معين في السابق كنا نستدعيها كل واحد بامر بإستخدام المفتاح use ولكن في PHP7 تم تطوير المفتاح use ليقبل مجموعة من المسميات ليقوم بإستدعائهم دفعة واحدة
قبل PHP7 كنا نستدعي جميع الملفات التي نريد بهذه الطريقة
<?php
// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
ولكن في PHP7 نقوم بإستدعاء نفس الملفات بهذه الطريقة
<?php
// PHP 7+ code
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
Generator Return Expressions
تم تطوير Generator في PHP5.5 وكانت من أهم التطورات في PHP ولكن لايمكن إستخدام المفتاح return داخلها فتم تطويرها في PHP7 وإدراج إمكانية إستدعاء آخر قيمة مرجعة بواسطة المفتاح return كنتيجة نهائية بعد إنتهاء عمل الكود بإستخدام getReturn عند الحاجة
مثال بسيط
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
ناتج هذا الكود كالتالي سيتم تجاهل المفتاح return عن التعامل مع Generator
ولكن بإستخدام getReturn نستطيع طباعة آخر قيمة مرجعة بواسطة المفتاح return والتي لايمكن إستخدامها إلا عند إنتهاء عمل Generator
مثال لتوضح الصورة أكثر
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
عند عمل هذا الكود فإنه سيتم طباعة جميع الأرقام حتى ٣
وهنا تأتي أهمية هذا الأمر حيث أحيانا ترغب بتنفيذ عملية أخيرة يتم إنتاجها فقط عند إنتهاء عمل Generator وعرض ناتج العملية بشكل سهل ومرن في السابق كان يتم التحقق إذا وصل Generator للخطوة الأخيرة قم بتنفيذ هذا الكود وإدراجه ضمن النتائج الآن أصبح أسهل و أوضح في PHP7
Generator delegation
عند العمل مع Generator معين الآن أصبح بمقدورك تعريف مدخلات أو خطوات من Generator آخر بكل سهولة ومرونة
مثال بسيط لتوضح الصورة أكثر
<?php
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
ناتج عمل هذا الكود كالتالي
قسمة الأعداد الصحيحة بواسطة الدالة intdiv
تسطيع الآن تنفيذ القسمة على الأعداد الصحيحة وتكون النتيجة المرجعة عدد صحيح بواسطة الدالة indiv
مثال بسيط لتوضيح الميزة
<?php
var_dump(intdiv(10, 3));
ناتج عمل هذا الكود سيكون كالتالي
إعدادات الجلسات Session options
الدالة session_start() أصبحت الآن تقبل مصفوفة من الإعدادات والتي بدورها تقوم بتعديل الإعدادات التي كانت بالسابق يجب ان تعدل في php.ini والتي تخص الجلسات طبعا التعديل يؤثر فقط على الملف المستخدم فيه الجلسة وتستطيع استخدام read_and_close ضمن هذه الإعدادات لتخبر PHP بأن هذه الإعدادات يجب أن تقرأ فقط وتغلق الجلسة مباشرة بدون تعديل إعدادات الجلسات
مثال بسيط لتغير أحد الإعدادات
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
لمعرفة المزيد من الإعدادات الممكن تغييرها من هنا session configuration directives
دالة preg_replace_callback_array
تم إضافة هذه الدالة لتسهيل عملية البحث عن أكثر من regular expression في نص واحد بكل سهولة ومرونة عكس سابقا كنا نستخدم preg_replace_callback() وكان البحث يكون عن regular expression واحد عن طريق callback يتفرع لاقسام متعددة ممايجعل الأكواد غير مقرؤة وصعبة الفهم تخيل انك تريد البحث عن أكثر من تعبير داخل نص كم كود تحتاج لكتابته للحصول على النتيجة
مثال بسيط لتوضيح الصورة
<?php
$subject = 'Aaaaaa Bbb';
preg_replace_callback_array(
[
'~[a]+~i' => function ($match) {
echo strlen($match[0]), ' matches for "a" found <br>';
},
'~[b]+~i' => function ($match) {
echo strlen($match[0]), ' matches for "b" found';
}
],
$subject
);
كما تلاحظ فإن هذه الدالة تقبل مدخلين الأول مصفوفة من regular expression والمدخل الثاني أسم المتغير المراد البحث بداخله المميز انه بإمكانك إدخال ماترغب من regular expression ليتم البحث عنهم داخل النص دون ان تقوم بإعادة كتابة دالة أخرى لنفس الهدف
دوال تشفير جديدة CSPRNG Functions
تم تطوير دالتين جديدة للمساعدة بإنتاج أرقام عشوائية أو نصوص و أرقام عشوائية لإستخدامها بالتشفير وهما
random_bytes() لإنتاج نصوص وأرقام عشوائية ودالة random_int() لإنتاج أرقام عشوائية بكل سهولة ومرونة
تطوير list
تم تطوير هذه الميزة حيث انه كان في السابق لاتعمل بشكل سليم مع الكائنات التي تعتمد على ArrayAccess التي تسمح لك التعامل مع الكائن كأنه مصفوفة حيث في PHP7 تم حل هذه المشكلة نهائيها وأيضا عند تعريف المتغيرات وتعين قيمهم من المصفوفة فإنه سابقا القيم المرجعة تكون بترتيب مقلوب الآن تم حل هذه المشكلة وأصبح الترتيب صحيح على حسب تعريفك للمتغيرات وترتيبك لهم ولاتعمد علي آلية الترتيب كثيرا يمكن ان تتغير بالمستقبل
في الختام
أتمنى أن يكون المقال ذو فائدة لكم ولمشاريعكم البرمجية وفي حالة وجود أي إستفسار تستطيع ترك تعليق او التوجه لقسم سؤال وجواب وطرح سؤالك سأكون أكثر من سعيد للإجابة على جميع إستفساراتكم
التعليقات (0)
عرض المزيد.. جديد مقالاتي
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !