it-swarm.asia

"إشعار: متغير غير معرّف" ، "إشعار: فهرس غير معرّف" ، و "إشعار: تعويض غير معروف" باستخدام PHP

أقوم بتشغيل PHP برنامج نصي ، ومواصلة تلقي أخطاء مثل:

إشعار: متغير غير معروف: my_variable_name في C:\wamp\www\mypath\index.php على السطر 10

إشعار: فهرس غير محدد: my_index C:\wamp\www\mypath\index.php على السطر 11

يبدو السطر 10 و 11 هكذا:

echo "My variable value is: " . $my_variable_name;
echo "My index value is: " . $my_array["my_index"];

ما معنى رسائل الخطأ هذه؟

لماذا تظهر فجأة؟ اعتدت على استخدام هذا البرنامج النصي لسنوات ولم يسبق لي أن واجهت أي مشكلة.

كيف يمكنني إصلاحها؟

هذا هو السؤال المرجعي العام بالنسبة للأشخاص للربط به كمكرر ، بدلاً من الاضطرار إلى شرح المشكلة مرارًا وتكرارًا. أشعر أن هذا ضروري لأن معظم إجابات العالم الحقيقي حول هذه المسألة محددة للغاية.

مناقشة التعريف ذات الصلة:

1069
Pekka 웃

ملحوظة: تغيير غير معرف

من الحكمة الواسعة لـ PHP Manual :

يعد الاعتماد على القيمة الافتراضية لمتغير غير مهيأ مشكلة في حالة تضمين ملف واحد في ملف آخر يستخدم نفس اسم المتغير. إنها أيضًا مخاطرة كبيرة الأمان مع register_globals قيد التشغيل. E_NOTICE خطأ المستوى يصدر في حالة العمل مع متغيرات غير مهيأة ، ولكن ليس في حالة إلحاق عناصر بالصفيف غير المهيأ. isset () لغة البناء يمكن استخدامها للكشف عما إذا كان قد تم بالفعل تهيئة متغير. بالإضافة إلى ذلك ، فإن الحل هو فارغة () لأنه لا ينشئ رسالة تحذير أو خطأ إذا لم تتم تهيئة المتغير.

من PHP التوثيق :

لا يتم إنشاء تحذير في حالة عدم وجود المتغير. هذا يعني فارغة () هي في الأساس المعادل المختصر لـ! isset ($ var) || $ var == false .

هذا يعني أنه يمكنك استخدام empty() فقط لتحديد ما إذا كان المتغير مضبوطًا ، بالإضافة إلى أنه يتحقق من المتغير مقابل ما يلي ، 0,"",null.

مثال:

$o = [];
@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
    echo (!isset($v) || $v == false) ? 'true ' : 'false';
    echo ' ' . (empty($v) ? 'true' : 'false');
    echo "\n";
});

اختبر المقتطف أعلاه في 3v4l.org عبر الإنترنت PHP المحرر

على الرغم من أن PHP لا تتطلب إعلانًا متغيرًا ، إلا أنه يوصي به لتجنب بعض الثغرات الأمنية أو الأخطاء حيث ينسى المرء إعطاء قيمة للمتغير الذي سيتم استخدامه لاحقًا في البرنامج النصي. ما يفعله PHP في حالة المتغيرات غير المعلنة هو إصدار خطأ مستوى منخفض جدًا ، E_NOTICE ، خطأ لا يتم الإبلاغ عنه بشكل افتراضي ، لكن الدليل ينصح بالسماح أثناء التطوير.

طرق التعامل مع المشكلة:

  1. مستحسن: قم بتعريف المتغيرات الخاصة بك ، على سبيل المثال عند محاولة إلحاق سلسلة بمتغير غير معروف. أو استخدم isset() / !empty() للتحقق مما إذا كانت قد أعلنت قبل الرجوع إليها ، كما في:

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

    لقد أصبح هذا أكثر نظافة اعتبارًا من PHP 7.0 ، الآن يمكنك استخدام عامل التماسك الخالي :

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
    
  2. قم بتعيين معالج خطأ مخصص لـ E_NOTICE وإعادة توجيه الرسائل بعيدًا عن الإخراج القياسي (ربما إلى ملف سجل):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
    
  3. تعطيل E_NOTICE من التقارير. طريقة سريعة لاستبعاد E_NOTICE هي:

    error_reporting( error_reporting() & ~E_NOTICE )
    
  4. قمع الخطأ مع @ المشغل .

ملاحظة: يوصى بشدة بتطبيق النقطة 1 فقط.

إشعار: مؤشر غير محدد/تعويض غير محدد

يظهر هذا الإشعار عندما تحاول (أو PHP) الوصول إلى فهرس غير محدد للصفيف.

طرق التعامل مع المشكلة:

  1. تحقق من وجود الفهرس قبل الوصول إليه. لهذا يمكنك استخدام isset() أو array_key_exists() :

    //isset()
    $value = isset($array['my_index']) ? $array['my_index'] : '';
    //array_key_exists()
    $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
    
  2. قد ينشئ بناء اللغة list() هذا عندما يحاول الوصول إلى فهرس صفيف غير موجود:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

يتم استخدام متغيرين للوصول إلى عنصري صفيف ، ومع ذلك هناك عنصر صفيف واحد فقط ، الفهرس 0 ، لذلك سيتم إنشاء:

إشعار: غير محدد الإزاحة: 1

المتغير $_POST/$_GET/$_SESSION

تظهر الإشعارات أعلاه غالبًا عند العمل مع $_POST أو $_GET أو $_SESSION. بالنسبة لـ $_POST و $_GET ، عليك فقط التحقق مما إذا كان الفهرس موجودًا أم لا قبل استخدامه. بالنسبة لـ $_SESSION ، يتعين عليك التأكد من بدء الجلسة بـ session_start() وأن الفهرس موجود أيضًا.

لاحظ أيضًا أن جميع المتغيرات الثلاثة هي superglobals وهي كبيرة.

ذات صلة:

981
Alin Purcaru

جرب هذا

Q1: يعني هذا الإشعار لم يتم تعريف $ varname في النطاق الحالي للبرنامج النصي.

Q2: استخدام شروط isset () ، فارغة () قبل استخدام أي متغير مشبوه يعمل بشكل جيد.

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name = '';
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

أو كحل سريع وقذّر:

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

ملاحظة حول الجلسات:

123
Ish

خطأ في العرض @ operator

بالنسبة للإشعارات غير المرغوب فيها والمتكررة ، يمكن استخدام المشغل المخصص @ إلى "إخفاء" رسائل متغير/فهرس غير محددة.

$var = @($_GET["optional_param"]);
  • وعادة ما يتم تثبيط هذا. يميل القادمون الجدد إلى الإفراط في استخدامه.
  • إنه غير مناسب تمامًا للرمز في عمق منطق التطبيق (تجاهل المتغيرات غير المعلنة حيث لا ينبغي لك ذلك) ، على سبيل المثال لمعلمات الوظيفة ، أو في الحلقات.
  • يوجد جانب واحد أعلى على isset?: أو ?? super-suctionion. إشعارات لا يزال يمكن الحصول على تسجيل. وقد يقوم أحدهم بإحياء الإشعارات الخفية @- مع: set_error_handler("var_dump");
    • بالإضافة إلى ذلك ، يجب ألا تستخدم/توصِّف عادة if (isset($_POST["shubmit"])) في الكود الأولي.
    • القادمون الجدد لن يكتشفوا مثل هذه الأخطاء. إنه يحرمك فقط من إشعارات PHPs لتلك الحالات بالذات. أضف @ أو isset فقط بعد التحقق من الوظيفة.
    • إصلاح السبب الأول. ليس الإشعارات.

  • @ مقبول بشكل أساسي لمعلمات الإدخال $_GET/$_POST ، وتحديدا إذا كانت اختيارية .

وبما أن هذا يغطي معظم هذه الأسئلة ، فلنوسع في أكثر الأسباب شيوعًا:

$_GET/$_POST/$_REQUEST إدخال غير محدد

  • أول شيء تقوم به عند مواجهة فهرس/إزاحة غير محدد ، هو التحقق من الأخطاء المطبعية:
    $count = $_GET["whatnow?"];

    • هل هذا اسم مفتاح متوقع وموجود في طلب صفحة ؟
    • أسماء المتغيرات و تشير مجموعة الصفيف إلى حالة حساسة في PHP.
  • ثانياً ، إذا لم يكن للإشعار سبب واضح ، فاستخدم var_dump أو print_r للتحقق الكل صفيف الإدخال للمحتوى الحالي:

    var_dump($_GET);
    var_dump($_POST);
    //print_r($_REQUEST);
    

    كلاهما سيكشف ما إذا كان قد تم استدعاء البرنامج النصي الخاص بك مع أي معلمات على اليمين أم لا.

  • البديل أو إضافة إلى ذلك استخدام devtools المتصفح (F12) وفحص علامة تبويب الشبكة للطلبات والمعلمات:

    browser developer tools / network tab

    سيتم عرض معلمات POST وإدخال GET بشكل منفصل.

  • بالنسبة إلى معلمات $_GET ، يمكنك أيضًا إلقاء نظرة خاطفة على QUERY_STRING in

    print_r($_SERVER);
    

    PHP لديه بعض القواعد إلى توحيد أسماء المعلمات غير القياسية في superglobals. أباتشي قد تفعل بعض إعادة كتابة كذلك. يمكنك أيضًا الاطلاع على $_COOKIES الخام المرفق ورؤوس طلب HTTP الأخرى بهذه الطريقة.

  • من الواضح أن ننظر إلى شريط عنوان المتصفح الخاص بك عن معلمات GET :

    http://example.org/script.php?id=5&sort=desc

    أزواج name=value بعد علامة الاستفهام ? هي معلمات طلب البحث (GET). وبالتالي ، قد يؤدي عنوان URL هذا إلى $_GET["id"] و $_GET["sort"] فقط.

  • أخيرًا تحقق من <form> و <input> التصريحات ، إذا كنت تتوقع معلمة لكنك لا تتلقى شيئًا.

    • تأكد من أن كل إدخال مطلوب يحتوي على <input name=FOO>
    • لا تكفي السمة id= أو title=.
    • يجب أن يملأ نموذج method=POST$_POST.
    • في حين أن method=GET (أو تتركه خارجًا) قد ينتج عنه متغيرات $_GET.
    • من الممكن أيضًا أن يقدم نموذج ما action=script.php?get=param عبر $ _GET وحقول method=POST المتبقية في $ _POST جنبًا إلى جنب.
    • من خلال التكوينات الحديثة PHP _ (≥ 5.6) أصبح مجديًا (غير مناسب) لاستخدام $_REQUEST['vars'] مرة أخرى ، وهو ما يهرس GET و POST المعلمات.
  • إذا كنت تستخدم mod_rewrite ، فعليك التحقق من كل من access.log بالإضافة إلى تمكين RewriteLog لمعرفة المعلمات الغائبة.

$_FILES

  • تنطبق نفس عمليات التعقل على عمليات تحميل الملفات و $_FILES["formname"].
  • وعلاوة على ذلك ، تحقق من enctype=multipart/form-data
  • وكذلك method=POST في إعلان <form> الخاص بك.
  • راجع أيضًا: PHP فهرس غير معروف خطأ $ _FILES؟

$_COOKIE

  • لا يتم ملء صفيف $_COOKIE أبدًا بعد setcookie() ، ولكن فقط على أي طلب HTTP للمتابعة.
  • بالإضافة إلى انتهاء صلاحية صلاحيتها ، يمكن أن تكون قيدًا على النطاقات الفرعية أو المسارات الفردية ، ويمكن للمستخدم والمتصفح فقط رفضها أو حذفها.
58
mario

عموما بسبب "البرمجة السيئة" ، واحتمال الأخطاء الآن أو في وقت لاحق.

  1. إذا كان خطأ ، فقم بإجراء الواجب المناسب للمتغير أولاً: $ varname = 0؛
  2. إذا تم تعريفها بالفعل في بعض الأحيان فقط ، فاختبرها: if (isset($varname)) ، قبل استخدامها
  3. إذا كان السبب في ذلك هو أنك كتبت خطأ ، فقم بتصحيح ذلك
  4. ربما تتحول التحذيرات فيك إعدادات PHP
41
Erik

هذا يعني أنك تقوم باختبار أو تقييم أو طباعة متغير لم تقم بتعيين أي شيء له بعد. هذا يعني أن لديك خطأ مطبعي ، أو تحتاج إلى التحقق من تهيئة المتغير إلى شيء أولاً. تحقق من مسارات المنطق الخاصة بك ، وقد يتم تعيينها في مسار واحد ولكن ليس في مسار آخر.

38
DGM

لم أكن أريد تعطيل الإشعارات لأنها مفيدة ، لكنني أردت تجنب الكثير من الكتابة.

وكان حل بلدي هذه الوظيفة:

function ifexists($varname)
{
  return(isset($$varname)?$varname:null);
}

لذلك إذا أردت الإشارة إلى اسم $ والصدى في حالة وجوده ، فأنا ببساطة أكتب:

<?=ifexists('name')?>

لعناصر الصفيف:

function ifexistsidx($var,$index)
{
  return(isset($var[$index])?$var[$index]:null);
}

في الصفحة إذا كنت أريد أن أشير إلى $ _REQUEST ['name']:

<?=ifexistsidx($_REQUEST,'name')?>
33
Ferenci Zoltán László

أفضل طريقة للحصول على إدخال سلسلة هي:

$value = filter_input(INPUT_POST, 'value');

يكافئ هذا الخط الواحد:

if (!isset($_POST['value'])) {
    $value = null;
} elseif (is_array($_POST['value'])) {
    $value = false;
} else {
    $value = $_POST['value'];
}

إذا كنت تريد سلسلة قيمة ، تمامًا مثل:

$value = (string)filter_input(INPUT_POST, 'value');
25
mpyw

ردًا على "" لماذا تظهر فجأة؟ اعتدت استخدام هذا البرنامج النصي لسنوات ولم أواجه أي مشكلة على الإطلاق. "

من الشائع جدًا أن تعمل معظم المواقع في إطار الإبلاغ عن الأخطاء "الافتراضي" عن "إظهار جميع الأخطاء ، ولكن ليس" الإشعارات "و" المهملة ". سيتم تعيين ذلك في php.ini وسيتم تطبيقه على جميع المواقع على الخادم. هذا يعني أن تلك "الإشعارات" المستخدمة في الأمثلة سيتم إخمادها (مخفية) بينما سيتم عرض/تسجيل الأخطاء الأخرى ، التي تعتبر أكثر أهمية.

الإعداد الحاسم الآخر هو أن الأخطاء يمكن إخفاؤها (على سبيل المثال ، display_errors مضبوط على "off" أو "syslog").

ما سيحدث في هذه الحالة هو أنه تم تغيير error_reporting أيضًا لإظهار الإشعارات (وفقًا للأمثلة) و/أو تغيير الإعدادات إلى display_errors على الشاشة (على عكس منعها/تسجيلها).

لماذا غيروا؟

الإجابة الواضحة/الأبسط هي أن شخصًا ما قام بضبط أي من هذه الإعدادات في php.ini ، أو نسخة مطورة من PHP يستخدم الآن php.ini مختلفًا من قبل. هذا هو المكان الأول للنظر.

ومع ذلك فمن الممكن أيضًا تجاوز هذه الإعدادات في

  • .htconf (تكوين خادم الويب ، بما في ذلك vhosts والتكوينات الفرعية) *
  • هتكس
  • في رمز php نفسه

وأي من هذه يمكن أيضا أن تتغير.

هناك أيضًا المضاعفات الإضافية المتمثلة في أن تكوين خادم الويب يمكنه تمكين/تعطيل توجيهات htaccess ، لذلك إذا كان لديك توجيهات في .htaccess تبدأ فجأة/تتوقف عن العمل ، فأنت بحاجة إلى التحقق من ذلك.

(.htconf/.htaccess تفترض أنك تعمل باسم Apache. إذا كان تشغيل سطر الأوامر لن ينطبق هذا ؛ إذا كان يتم تشغيل IIS أو خادم ويب آخر ، فستحتاج إلى التحقق من هذه التكوينات وفقًا لذلك)

ملخص

  • تحقق من توجيهات error_reporting و display_errors php في php.ini لم تتغير ، أو أنك لا تستخدم php.ini مختلفة من قبل.
  • تحقق من تغييرين error_reporting و display_errors php في .htconf (أو vhosts وما إلى ذلك) لم يتغيرا
  • تحقق من توجيهات error_reporting و display_errors php في .htaccess لم تتغير
  • إذا كان لديك توجيه في .htaccess ، فتحقق مما إذا كان لا يزال مسموحًا به في ملف .htconf
  • أخيرًا تحقق الكود ربما مكتبة غير ذات صلة ؛ لمعرفة ما إذا كان قد تم تعيين توجيهات error_reporting و display_errors php هناك.
24
Robbie

لأن المتغير '$ user_location' لا يتم تعريفه. إذا كنت تستخدم أي حلقة إذا كنت داخلها تعلن عن متغير "$ user_location" ، فيجب أن يكون لديك أيضًا حلقة أخرى وتعريفها. فمثلا:

$a=10;
if($a==5) { $user_location='Paris';} else { }
echo $user_location;

ستنشئ الشفرة أعلاه خطأ حيث لم يتم استيفاء حلقة if ولم يتم تعريف الحلقة الأخرى "$ user_location" في الحلقة الأخرى. لا يزال PHP طُلب منه صدى المتغير. لذلك لتعديل الكود ، يجب عليك القيام بما يلي:

$a=10;
if($a==5) { $user_location='Paris';} else { $user_location='SOMETHING OR BLANK'; }
echo $user_location;
24
Roger

الإصلاح السريع هو تعيين المتغير الخاص بك لإلغاء في الجزء العلوي من التعليمات البرمجية الخاصة بك

$user_location = null;
19
Shahin Mammadzada

اعتدت أن ألعن هذا الخطأ ، لكن من المفيد أن أذكرك بالهروب من إدخال المستخدم.

على سبيل المثال ، إذا كنت تعتقد أن هذا رمز ذكي مختزل:

// Echo whatever the hell this is
<?=$_POST['something']?>

...فكر مرة اخرى! الحل الأفضل هو:

// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>

(يمكنني استخدام وظيفة html() مخصصة للهروب من الحروف ، قد يختلف عدد الأميال المقطوعة)

15
rybo111

يمكنني استخدام وظيفة مفيدة في كل الوقت exst () التي تعلن المتغيرات تلقائيا.

كودك سيكون -

$greeting = "Hello, ".exst($user_name, 'Visitor')." from ".exst($user_location);


/** 
 * Function exst() - Checks if the variable has been set 
 * (copy/paste it in any place of your code)
 * 
 * If the variable is set and not empty returns the variable (no transformation)
 * If the variable is not set or empty, returns the $default value
 *
 * @param  mixed $var
 * @param  mixed $default
 * 
 * @return mixed 
 */

function exst( & $var, $default = "")
{
    $t = "";
    if ( !isset($var)  || !$var ) {
        if (isset($default) && $default != "") $t = $default;
    }
    else  {  
        $t = $var;
    }
    if (is_string($t)) $t = trim($t);
    return $t;
}
13
user2253362

في PHP 7.0 ، أصبح من الممكن الآن استخدام عامل التضمين Null:

echo "My index value is: " . ($my_array["my_index"] ?? '');

يساوي:

echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');

PHP manual PHP 7.0

13
Lachezar Lechev

لماذا IS هذا يحدث؟

بمرور الوقت ، أصبحت PHP لغة أكثر تركيزًا على الأمان. الإعدادات التي كان يتم إيقاف تشغيلها بشكل افتراضي يتم الآن تشغيلها افتراضيًا. مثال مثالي على ذلك هو E_STRICT ، الذي أصبح قيد التشغيل افتراضيًا اعتبارًا من PHP 5.4.0 .

علاوة على ذلك ، وفقًا لـ PHP الوثائق ، بشكل افتراضي ، يتم تعطيل E_NOTICE في php.ini. PHP يوصي مستندات تشغيله لأغراض التصحيح . ومع ذلك ، عندما أقوم بتنزيل PHP من مستودع Ubuntu — ومن مكدس Windows BitNami — أرى شيئًا آخر.

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

لاحظ أنه تم تعيين error_reporting فعليًا على قيمة الإنتاج افتراضيًا ، وليس على القيمة "الافتراضية" افتراضيًا. هذا مربك إلى حد ما ولا يتم توثيقه خارج php.ini ، لذلكلاقمت بالتحقق من صحة ذلك على توزيعات أخرى.

للإجابة على سؤالك ، يظهر هذا الخطأ الآن عندما لم يظهر من قبل لأنه:

  1. قمت بتثبيت PHP والإعدادات الافتراضية الجديدة موثقة إلى حد ما ولكن لا تستبعد E_NOTICE.

  2. تساعد تحذيرات E_NOTICE مثل المتغيرات غير المحددة والفهارس غير المحددة على جعل الشفرة أكثر نظافة وأمانًا. أستطيع أن أخبرك أنه ، منذ سنوات ، اضطرني حفظ E_NOTICE إلى إعلان متغيراتي. لقد جعل الأمر أكثر سهولة لتعلم C ، ولم يكن إعلان المتغيرات أكبر من مصدر إزعاج.

ما الذي يمكنني القيام به حيال ذلك؟

  1. قم بإيقاف تشغيل E_NOTICE عن طريق نسخ "القيمة الافتراضية" E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED واستبدالها بما هو غير مكتمل حاليًا بعد تسجيلات الدخول في error_reporting =. أعد تشغيل Apache ، أو PHP إذا كنت تستخدم CGI أو FPM. تأكد من أنك تقوم بتحرير php.ini "الصحيح". سيكون Apache الصحيح هو إذا كنت تقوم بتشغيل PHP مع Apache أو fpm أو php-fpm إذا كنت تستخدم PHP-FPM أو cgi إذا كنت تستخدم PHP-CGI ، إلخ. هذه ليست الطريقة الموصى بها ، ولكن إذا كنت لديك كود قديم سيكون من الصعب للغاية تعديله ، ثم قد يكون أفضل رهان لك.

  2. قم بإيقاف تشغيل E_NOTICE على مستوى الملف أو المجلد. قد يكون هذا هو الأفضل إذا كان لديك بعض الرموز القديمة ولكنك تريد أن تفعل الأشياء بالطريقة "الصحيحة" على خلاف ذلك. للقيام بذلك ، يجب عليك الرجوع إلى Apache2 أو Nginx أو أيًا كان الخادم الذي تختاره. في Apache ، يمكنك استخدام php_value داخل <Directory>.

  3. أعد كتابة الكود لتكون أكثر نظافة إذا كنت بحاجة إلى القيام بذلك أثناء الانتقال إلى بيئة الإنتاج أو لا تريد أن يرى شخص ما أخطائك ، فتأكد من تعطيل أي عرض للأخطاء ، وفقط تسجيل / أخطائك (انظر display_errors و log_errors في php.ini وإعدادات الخادم الخاص بك).

للتوسع في الخيار 3: هذا هو المثالي. إذا كنت تستطيع أن تذهب في هذا الطريق ، يجب عليك. إذا لم تكن تسير في هذا الطريق في البداية ، ففكر في نقل هذا المسار في النهاية عن طريق اختبار الرمز في بيئة تطوير. أثناء تواجدك فيه ، تخلص من ~E_STRICT و ~E_DEPRECATED لمعرفة ما قد يحدث في المستقبل. سترى الكثير من الأخطاء غير المألوفة ، لكن ذلك سيمنعك من مواجهة أي مشاكل غير سارة عندما تحتاج إلى ترقية PHP في المستقبل.

ماذا تعني الأخطاء؟

Undefined variable: my_variable_name - يحدث هذا عندما لا يتم تعريف متغير قبل الاستخدام. عندما يتم تنفيذ البرنامج النصي PHP ، فإنه داخليًا يفترض وجود قيمة خالية. ومع ذلك ، في أي سيناريو ستحتاج إلى التحقق من متغير قبل تحديده؟ في النهاية ، هذه حجة لـ "رمز قذر". كمطور ، يمكنني أن أخبرك أنني أحبها عندما أرى مشروعًا مفتوح المصدر حيث يتم تعريف المتغيرات على أنها عالية في نطاقاتها حيث يمكن تعريفها. يجعل الأمر أسهل في تحديد المتغيرات التي ستظهر في المستقبل ويجعل من الأسهل قراءة/معرفة الكود.

function foo()
{
    $my_variable_name = '';

    //....

    if ($my_variable_name) {
        // perform some logic
    }
}

Undefined index: my_index - يحدث هذا عند محاولة الوصول إلى قيمة في صفيف وهو غير موجود. لمنع هذا الخطأ ، قم بإجراء فحص مشروط.

// verbose way - generally better
if (isset($my_array['my_index'])) {
    echo "My index value is: " . $my_array['my_index'];
}

// non-verbose ternary example - I use this sometimes for small rules.
$my_index_val = isset($my_array['my_index'])?$my_array['my_index']:'(undefined)';
echo "My index value is: " . $my_index_val;   

خيار آخر هو إعلان مجموعة فارغة في الجزء العلوي من وظيفتك. ليس هذا ممكنا دائما.

$my_array = array(
    'my_index' => ''
);

//...

$my_array['my_index'] = 'new string';

(نصيحة إضافية)

  • عندما كنت أواجه هذه المشكلات وغيرها ، استخدمت NetBeans IDE (مجاني) وأعطاني مجموعة من التحذيرات والإشعارات. بعضها يقدم نصائح مفيدة للغاية. هذا ليس شرطا ، وأنا لا تستخدم IDEs بعد الآن باستثناء المشاريع الكبيرة. أنا أكثر من شخص vim هذه الأيام :).
7
smcjones

لماذا لا تبقي الأمور بسيطة؟

<?php
error_reporting(E_ALL); // making sure all notices are on

function idxVal(&$var, $default = null) {
         return empty($var) ? $var = $default : $var;
  }

echo idxVal($arr['test']);         // returns null without any notice
echo idxVal($arr['hey ho'], 'yo'); // returns yo and assigns it to array index, Nice

?>
7
gts

يعني الفهرس غير المحدد في صفيف طلبته لفهرس صفيف غير متوفر على سبيل المثال

<?php 

$newArray[] = {1,2,3,4,5};
print_r($newArray[5]);

?>

متغير غير معرف يعني أنك استخدمت متغيراً غير موجود بالكامل أو لم يتم تعريفه أو تهيئته بهذا الاسم على سبيل المثال

<?php print_r($myvar); ?>

الإزاحة غير المحددة تعني في الصفيف أنك طلبت مفتاحًا غير موجود. والحل لهذا هو التحقق قبل الاستخدام

php> echo array_key_exists(1, $myarray);
5
Sinte

فيما يتعلق بهذا الجزء من السؤال:

لماذا تظهر فجأة؟ اعتدت على استخدام هذا البرنامج النصي لسنوات ولم يسبق لي أن واجهت أي مشكلة.

لا توجد إجابات محددة ولكن فيما يلي بعض التفسيرات المحتملة لسبب تغيير الإعدادات "فجأة":

  1. لقد قمت بالترقية PHP إلى إصدار أحدث يمكن أن يحتوي على إعدادات افتراضية أخرى للخطأ أو الإبلاغ عن الأخطاء أو الإعدادات الأخرى ذات الصلة.

  2. لقد قمت بإزالة أو إدخال بعض الكود (ربما في تبعية) التي تحدد الإعدادات ذات الصلة في وقت التشغيل باستخدام ini_set() أو error_reporting() (ابحث عن هذه في الكود)

  3. لقد قمت بتغيير تكوين خادم الويب (بافتراض Apache هنا): يمكن لملفات .htaccess وتكوينات vhost أيضًا معالجة إعدادات php.

  4. عادةً لا يتم عرض/الإبلاغ عن الإشعارات (راجع PHP دليل ) لذلك فمن الممكن عند إعداد الخادم ، تعذر تحميل ملف php.ini لسبب ما (أذونات الملف ؟؟) وكنت على الإعدادات الافتراضية. في وقت لاحق ، تم حل "الأخطاء" (عن طريق الصدفة) والآن يمكنه تحميل ملف php.ini الصحيح مع error_reporting لتعيين الإشعارات.

3
Wouter de Winter

إذا كنت تعمل مع الفئات ، فأنت بحاجة إلى التأكد من الرجوع إلى متغيرات الأعضاء باستخدام $this:

class Person
{
    protected $firstName;
    protected $lastName;

    public function setFullName($first, $last)
    {
        // Correct
        $this->firstName = $first;

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    }
}
2
John Conde

سبب آخر لإلغاء إشعار فهرس غير محدد ، هو حذف عمود من استعلام قاعدة البيانات.

أي.:

$query = "SELECT col1 FROM table WHERE col_x = ?";

ثم محاولة الوصول إلى المزيد من الأعمدة/الصفوف داخل حلقة.

أي.:

print_r($row['col1']);
print_r($row['col2']); // undefined index thrown

أو في حلقة while:

while( $row = fetching_function($query) ) {

    echo $row['col1'];
    echo "<br>";
    echo $row['col2']; // undefined index thrown
    echo "<br>";
    echo $row['col3']; // undefined index thrown

}

شيء آخر لا بد من الإشارة إليه هو أن الأمور حساسة لحالة الأحرف في نظام التشغيل * NIX OS و Mac OS X.

استشر الأسئلة والأجوبة التالية على المكدس:

2
Funk Forty Niner

استخدام ternary بسيط وقابل للقراءة ونظيف:

Pre PHP 7
عيّن متغيرًا إلى قيمة متغير آخر إذا تم تعيينه ، وإلا قم بتعيين null (أو أيا كانت القيمة {الافتراضية) التي تحتاجها):

$newVariable = isset($thePotentialData) ? $thePotentialData : null;

PHP 7+
نفس الشيء باستثناء استخدام Null Coalescing Operator . لم تعد هناك حاجة للاتصال بـ isset() نظرًا لأن هذا مضمّن ، وليس هناك حاجة لتوفير المتغير للعودة حيث يُفترض إرجاع قيمة المتغير الجاري فحصه:

$newVariable = $thePotentialData ?? null;

كلاهما سيوقف الإشعارات عن سؤال البروتوكول الاختياري ، و كلاهما تعادلان بالضبط:

if (isset($thePotentialData)) {
    $newVariable = $thePotentialData;
} else {
    $newVariable = null;
}


إذا كنت لا تحتاج إلى تعيين متغير جديد ، فيمكنك استخدام القيمة الثلاثية التي تم إرجاعها مباشرة ، مثل echo ، وسيطات الدوال ، إلخ:

الصدى:

echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';

الوظيفة:

$foreName = getForeName(isset($userId) ? $userId : null);

function getForeName($userId)
{
    if ($userId === null) {
        // Etc
    }
}

ما سبق سوف يعمل بنفس الطريقة مع المصفوفات ، بما في ذلك الجلسات وما إلى ذلك ، لتحل محل المتغير الجاري فحصه على سبيل المثال:
$_SESSION['checkMe']
أو مهما كانت مستويات كثيرة تحتاجها ، على سبيل المثال:
$clients['personal']['address']['postcode']


قمع:

من الممكن منع PHP الإشعارات باستخدام @ أو تقليل مستوى الإبلاغ عن الخطأ ، ولكنه لا يحل المشكلة ، إنه ببساطة يتوقف عن الإبلاغ عنها في سجل الأخطاء. هذا يعني أن الشفرة ما زالت تحاول استخدام متغير لم يتم تعيينه ، والذي قد يعني أو لا يعني أن شيئًا ما لا يعمل كما هو مقصود - وهذا يتوقف على مدى أهمية القيمة المفقودة.

يجب أن تقوم بالفعل بالتحقق من هذه المشكلة والتعامل معها بشكل مناسب ، إما تقديم رسالة مختلفة ، أو حتى مجرد إرجاع قيمة فارغة لكل شيء آخر لتحديد الحالة الدقيقة.

إذا كنت تهتم فقط بعدم وجود إشعار في سجل الأخطاء ، فعندئذٍ كخيار يمكنك ببساطة تجاهل سجل الأخطاء.

1
James

لقد طرحت سؤالاً حول هذا الموضوع وتمت إحالتي إلى هذه المشاركة مع الرسالة:

هذا السؤال لديه بالفعل إجابة هنا:

"إشعار: متغير غير معرف" ، "إشعار: فهرس غير معرف" ، و "إشعار: تعويض غير معروف" باستخدام PHP

أشارك سؤالي وحلتي هنا:

هذا هو الخطأ:

 enter image description here

السطر 154 هو المشكلة. هذا ما لدي في السطر 154:

153    foreach($cities as $key => $city){
154        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

أعتقد أن المشكلة تكمن في أنني أكتب إذا كانت شروط المتغير $city ، وهي ليست المفتاح بل القيمة في $key => $city. أولاً ، هل يمكنك تأكيد ما إذا كان هذا هو سبب التحذير؟ ثانياً ، إذا كانت هذه هي المشكلة ، فلماذا لا أستطيع كتابة شرط على أساس القيمة؟ هل يجب أن يكون مع المفتاح الذي أحتاجه لكتابة الشرط؟

التحديث 1: المشكلة هي أنه عند تنفيذ $citiesCounterArray[$key] ، في بعض الأحيان يتوافق $key مع مفتاح غير موجود في صفيف $citiesCounterArray ، لكن هذا لا يحدث دائمًا بناءً على بيانات حلقي. ما أحتاجه هو تعيين شرط بحيث إذا كان $key موجودًا في المصفوفة ، فقم بتشغيل الكود ، وإلا ، تخطيه.

تحديث 2: هذه هي الطريقة التي قمت بإصلاحها باستخدام array_key_exists():

foreach($cities as $key => $city){
    if(array_key_exists($key, $citiesCounterArray)){
        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
0
Jaime Montoya

أحد الأسباب الشائعة لمتغير غير موجود بعد إرسال نموذج HTML هو عدم تضمين عنصر النموذج ضمن علامة <form>:

مثال: العنصر غير موجود في <form>

<form action="example.php" method="post">
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>

<select name="choice">
    <option value="choice1">choice 1</option>
    <option value="choice2">choice 2</option>
    <option value="choice3">choice 3</option>
    <option value="choice4">choice 4</option>
</select>

مثال: العنصر الموجود الآن ضمن <form>

<form action="example.php" method="post">
    <select name="choice">
        <option value="choice1">choice 1</option>
        <option value="choice2">choice 2</option>
        <option value="choice3">choice 3</option>
        <option value="choice4">choice 4</option>
    </select>
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>
0
John Conde

عند التعامل مع الملفات ، يلزم وجود نمط مناسب وطريقة POST ، مما يؤدي إلى تشغيل إشعار فهرس غير محدد إذا لم يتم تضمين أي منهما في النموذج.

ينص الدليل على الصيغة الأساسية التالية:

HTML

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

PHP

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);

print "</pre>";

?>

مرجع:

0
Funk Forty Niner

تحدث هذه الأخطاء عندما نستخدم متغيرًا لم يتم تعيينه.

أفضل طريقة للتعامل مع هذه هي إعداد تقرير عن الأخطاء أثناء التطوير.

لتعيين تقرير عن الخطأ في:

ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);

على خوادم الإنتاج ، يتم إيقاف الإبلاغ عن الأخطاء ، وبالتالي ، فإننا لا نحصل على هذه الأخطاء.

على خادم التطوير ، ومع ذلك ، يمكننا ضبط الإبلاغ عن الأخطاء على.

للتخلص من هذا الخطأ ، نرى المثال التالي:

if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

يمكننا تهيئة المتغيرات إلى NULL قبل تعيين قيمها أو استخدامها.

لذلك ، يمكننا تعديل الكود على النحو التالي:

$test = NULL;
if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

لن يزعج هذا أي منطق في البرنامج ولن ينتج عنه إشعار حتى لو لم يكن هناك قيمة $test.

لذلك ، في الأساس ، من الأفضل دائمًا تعيين الإبلاغ عن الخطأ للتطوير.

وإصلاح جميع الأخطاء.

وعلى الإنتاج ، يجب ضبط الإبلاغ عن الأخطاء.

0
Pupil

ربما كنت تستخدم الإصدار PHP القديم حتى الآن وقمت بالترقية PHP وهذا هو السبب في أنه كان يعمل دون أي خطأ حتى الآن منذ سنوات. حتى PHP4 ، لم يكن هناك أي خطأ إذا كنت تستخدم المتغير دون تعريفه ولكن اعتبارًا من PHP5 فصاعدًا ، فإنه يلقي أخطاء على أكواد مثل المذكورة في السؤال.

0
phvish