parsing اختبار - أخطاء تحليل / بناء جملة PHP ؛ وكيفية حلها؟




check test (12)

غير متوقع T_STRING

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

  1. سلاسل مكتوبة

    هذا الخطأ في بناء الجملة هو الأكثر شيوعًا بالنسبة لقيم السلسلة غير الصحيحة. أي اقتباس " أو " غير مبسوط وشارد سيشكل تعبيرًا غير صالح:

                   ⇓                  ⇓
     echo "<a href="http://example.com">click here</a>";
    

    تسليط الضوء على بناء الجملة سيجعل هذه الأخطاء واضحة للغاية. من المهم تذكر استخدام الخطوط المائلة العكسية للهروب \" علامات اقتباس مزدوجة ، أو \' علامات اقتباس مفردة - اعتمادًا على الذي تم استخدامه كحظر سلسلة .

    • من أجل الراحة ، يجب عليك تفضيل الاقتباسات الفردية الخارجية عند إخراج HTML عادي مع علامات تنصيص مزدوجة داخلها.
    • استخدام سلاسل مقتبسة مزدوجة إذا كنت ترغب في استيفاء المتغيرات ، ولكن احترس من الهروب " الاقتباسات المزدوجة " .
    • للإخراج الأطول ، تفضل خطوط echo / print متعددة بدلاً من الهروب والخروج. من الأفضل التفكير في قسم HEREDOC .

    راجع أيضًا ما الفرق بين السلاسل المقتبسة والعلامة المزدوجة في PHP؟ .

  2. سلاسل غير مغلقة

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

                                                           ⇓
    echo "Some text", $a_variable, "and some runaway string ;
    success("finished");
             ⇯
    

    انها ليست مجرد حرفيا T_STRING الصورة التي قد الاحتجاج المحلل ثم. هناك تباين آخر متكرر هو Unexpected '>' للحروف HTML غير المدروسة.

  3. يقتبس سلسلة غير البرمجة

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

    $text = ’Something something..’ + ”these ain't quotes”;
    

    علامات الطباعة / الرموز الذكية هي رموز Unicode. يعاملهم PHP كجزء من نص أبجدي رقمي مجاور. على سبيل المثال ”these يتم تفسيرها على أنها معرف ثابت. ولكن يتم بعد ذلك مشاهدة أي نص حرفي لاحق على أنه bareword / T_STRING بواسطة المحلل اللغوي.

  4. الفاصلة المنقوطة مرة أخرى

    إذا كان لديك تعبير غير مكرر في السطور السابقة ، عندئذٍ ، يتم النظر إلى أي عبارة أو بنية لغة كمعرّف أولي:

           ⇓
    func1()
    function2();
    

    لا تستطيع PHP فقط معرفة ما إذا كنت تقصد تشغيل وظيفتين تلو الآخر ، أو إذا كنت تقصد مضاعفة نتائجها ، أو إضافتها ، أو مقارنتها ، أو تشغيل واحد فقط || أو الآخر.

  5. علامات مفتوحة قصيرة ورؤوس <?xml في نصوص PHP

    هذا غير شائع إلى حد ما. ولكن إذا تم تمكين short_open_tags ، فلا يمكنك بدء برامج نصوص PHP الخاصة بك مع تصريح XML :

          ⇓
    <?xml version="1.0"?>
    

    سيرى PHP <? واستردها لنفسها. لن يفهم ما هو المقصود xml الشارد. سيتم تفسيرها على أنها ثابتة. ولكن سوف ينظر إلى version على أنه حرفي / ثابت آخر. وبما أن المحلل اللغوي لا يمكن أن يكون له معنى في القيمتين / القيمتين اللاحقتين بدون عامل تعبير بينهما ، فسيكون ذلك إخفاق المحلل اللغوي.

  6. أحرف Unicode غير مرئية

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

    <?php
        print 123;
    

    تحتاج لكسر محرر نص آخر. أو حتى hexeditor. ما يبدو مثل المساحات العادية والخطوط الجديدة هنا ، قد يحتوي على ثوابت غير مرئية. أحيانًا تكون IDEs المستندة إلى Java غير متسامحة مع UTF-8 BOM المتشابكة ضمن مسافات صفرية العرض ، فواصل الفقرات ، إلخ. حاول إعادة تثبيت كل شيء ، وإزالة المسافات البيضاء وإضافة مسافات عادية مرة أخرى.

    يمكنك تضييقها مع إضافة زائدة عن الحاجة ; فواصل البيان عند كل سطر تبدأ:

    <?php
        ;print 123;
    

    الإضافي فاصلة منقوطة هنا سوف تقوم بتحويل الحرف غير المرئي السابق إلى مرجع ثابت غير معرف (تعبير كإفادة). وهذا بدوره يجعل PHP منتجًا مفيدًا.

  7. علامة `$` مفقودة أمام أسماء المتغيرات

    يتم تمثيل المتغيرات في PHP بعلامة الدولار متبوعة باسم المتغير.

    علامة الدولار ( $ ) هي sigil الذي يميز المعرف كاسم لمتغير. بدون هذا sigil ، يمكن أن يكون المعرّف عبارة عن كلمة أساسية للغة أو constant .

    يعد هذا خطأ شائعًا عندما تم "ترجمة" شفرة PHP من شفرة مكتوبة بلغة أخرى (C ، و Java ، و JavaScript ، وما إلى ذلك). في مثل هذه الحالات ، يمكن لإعلان نوع المتغير (عندما تكون الشفرة الأصلية مكتوبة بلغة تستخدم متغيرات مكتوبة) أن يتسلل وينتج هذا الخطأ.

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

خطأ تحليل PHP: خطأ في بناء الجملة ، غير متوقع "{" في index.php على السطر 20

رمز غير متوقع ليس دائما الجاني الحقيقي. لكن رقم السطر يعطي فكرة تقريبية من أين تبدأ النظر.

ننظر دائما في سياق التعليمات البرمجية . غلطة بناء الجملة غالباً ما يخفي في خطوط التعليمات البرمجية السابقة . قارن التعليمة البرمجية الخاصة بك مقابل أمثلة بناء الجملة من الدليل.

بينما لا تتطابق كل حالة مع الأخرى. ومع ذلك ، هناك بعض الخطوات العامة لحل أخطاء الجملة . لقد لخصت هذه المراجع المزالق الشائعة:

مراجع وثيقة الصلة:

و:

في حين أن ترحب أيضًا بمراتب المبتدئين ، إلا أنها تستهدف في الغالب أسئلة البرمجة الاحترافية.

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

إذا كان متصفحك يعرض رسائل خطأ مثل "SyntaxError: character غير قانوني" ، فهذا يعني أنه لا يرتبط فعليًا بـ php ، ولكنه خطأ في بناء الجملة javascript .


Unexpected T_IF
Unexpected T_ELSEIF
Unexpected T_ELSE
Unexpected T_ENDIF

Conditional control blocks if , elseif and else follow a simple structure. When you encounter a syntax error, it's most likely just invalid block nesting → with missing { curly braces } - or one too many.

  1. Missing { or } due to incorrect indentation

    Mismatched code braces are common to less well-formatted code such as:

    if((!($opt["uniQartz5.8"]!=$this->check58)) or (empty($_POST['poree']))) {if
    ($true) {echo"halp";} elseif((!$z)or%b){excSmthng(False,5.8)}elseif (False){
    

    If your code looks like this, start afresh! Otherwise it's unfixable to you or anyone else. There's no point in showcasing this on the internet to inquire for help.

    You will only be able to fix it, if you can visually follow the nested structure and relation of if/else conditionals and their { code blocks } . Use your IDE to see if they're all paired.

    if (true) {
         if (false) {
                  …
         }
         elseif ($whatever) {
             if ($something2) {
                 …
             } 
             else {
                 …
             }
         }
         else {
             …
         }
         if (false) {    //   a second `if` tree
             …
         }
         else {
             …
         }
    }
    elseif (false) {
        …
    }
    

    Any double } } will not just close a branch, but a previous condition structure. Therefore stick with one coding style; don't mix and match in nested if/else trees.

    Apart from consistency here, it turns out helpful to avoid lengthy conditions too. Use temporary variables or functions to avoid unreadable if -expressions.

  2. IF cannot be used in expressions

    A surprisingly frequent newcomer mistake is trying to use an if statement in an expression, such as a print statement:

                       ⇓
    echo "<a href='" . if ($link == "example.org") { echo …
    

    Which is invalid of course.

    You can use a ternary conditional , but beware of readability impacts.

    echo "<a href='" . ($link ? "http://yes" : "http://no") . "</a>";
    

    Otherwise break such output constructs up: use multiple if s and echo s .
    Better yet, use temporary variables , and place your conditionals before:

    if ($link) { $href = "yes"; } else { $href = "no"; }
    echo "<a href='$href'>Link</a>";
    

    Defining functions or methods for such cases often makes sense too.

    Control blocks don't return "results"

    Now this is less common, but a few coders even try to treat if as if it could return a result :

    $var = if ($x == $y) { "true" };
    

    Which is structurally identical to using if within a string concatenation / expression.

    • But control structures (if / foreach / while) don't have a "result" .
    • The literal string "true" would also just be a void statement.

    You'll have to use an assignment in the code block :

    if ($x == $y) { $var = "true"; }
    

    Alternatively, resort to a ?: ternary comparison.

    If in If

    You cannot nest an if within a condition either:

                        ⇓
    if ($x == true and (if $y != false)) { ... }
    

    Which is obviously redundant, because the and (or or ) already allows chaining comparisons.

  3. Forgotton ; semicolons

    Once more: Each control block needs to be a statement. If the previous code piece isn't terminated by a semicolon, then that's a guaranteed syntax error:

                    ⇓
    $var = 1 + 2 + 3
    if (true) { … }
    

    Btw, the last line in a {…} code block needs a semicolon too.

  4. Semicolon too early

    Now it's probably wrong to blame a particular coding style, as this pitfall is too easy to overlook:

                ⇓
    if ($x == 5);
    {
        $y = 7;
    }
    else           ←
    {
        $x = -1;    
    }
    

    Which happens more often than you might imagine.

    • When you terminate the if () expression with ; it will execute a void statement. The ; becomes a an empty {} of its own!
    • The {…} block thus is detached from the if , and would always run.
    • So the else no longer had a relation to an open if construct, which is why this would lead to an Unexpected T_ELSE syntax error.

    Which also explains a likewise subtle variation of this syntax error:

    if ($x) { x_is_true(); }; else { something_else(); };
    

    Where the ; after the code block {…} terminates the whole if construct, severing the else branch syntactically.

  5. Not using code blocks

    It's syntactically allowed to omit curly braces {} for code blocks in if / elseif / else branches. Which sadly is a syntax style very common to unversed coders. (Under the false assumption this was quicker to type or read).

    However that's highly likely to trip up the syntax. Sooner or later additional statements will find their way into the if/else branches:

    if (true)
        $x = 5;
    elseif (false)
        $x = 6;
        $y = 7;     ←
    else
        $z = 0;
    

    But to actually use code blocks, you do have to write {} them as such!

    Even seasoned programmers avoid this braceless syntax, or at least understand it as an exceptional exception to the rule.

  6. Else / Elseif in wrong order

    One thing to remind yourself is the conditional order , of course.

    if ($a) { … }
    else { … }
    elseif ($b) { … }
    ↑
    

    You can have as many elseif s as you want, but else has to go last . That's just how it is.

  7. Class declarations

    As mentioned above , you can't have control statements in a class declaration:

    class xyz {
        if (true) {
            function ($var) {}
        }
    

    You either forgot a function definition, or closed one } too early in such cases.

  8. Unexpected T_ELSEIF / T_ELSE

    This is more or less a variation of incorrect indentation - presumably often based on wrong coding intentions.
    You cannot mash other statements inbetween if and elseif / else structural tokens:

    if (true) {
    }
    echo "in between";    ←
    elseif (false) {
    }
    ?> text <?php      ←
    else {
    }
    

    Either can only occur in {…} code blocks, not in between control structure tokens.

    • This wouldn't make sense anyway. It's not like that there was some "undefined" state when PHP jumps between if and else branches.
    • You'll have to make up your mind where print statements belong to / or if they need to be repeated in both branches.

    Nor can you part an if/else between different control structures:

    foreach ($array as $i) {
        if ($i) { … }
    }
    else { … }
    

    There is no syntactic relation between the if and else . The foreach lexical scope ends at } , so there's no point for the if structure to continue.

  9. T_ENDIF

    If an unexpected T_ENDIF is complained about, you're using the alternative syntax style if:elseif:else:endif; . Which you should really think twice about.

    • A common pitfall is confusing the eerily similar : colon for a ; semicolon . (Covered in "Semicolon too early")

    • As indentation is harder to track in template files, the more when using the alternative syntax - it's plausible your endif; does not match any if: .

    • Using } endif; is a doubled if -terminator.

    While an "unexpected $end" is usually the price for a forgotten closing } curly brace.

  10. Assignment vs. comparison

    So, this is not a syntax error, but worth mentioning in this context:

           ⇓
    if ($x = true) { }
    else { do_false(); }
    

    That's not a == / === comparison, but an = assignment . This is rather subtle, and will easily lead some users to helplessly edit whole condition blocks. Watch out for unintended assignments first - whenver you experience a logic fault / misbeheviour.


Unexpected T_IF
Unexpected T_FOREACH
Unexpected T_FOR
Unexpected T_WHILE
Unexpected T_DO
Unexpected T_ECHO

Control constructs such as if , foreach , for , while , list , global , return , do , print , echo may only be used as statements. They usually reside on a line by themselves.

  1. Semicolon; where you at?

    Pretty universally have you missed a semicolon in the previous line if the parser complains about a control statement:

                 ⇓
    $x = myfunc()
    if (true) {
    

    Solution: look into the previous line; add semicolon.

  2. Class declarations

    Another location where this occurs is in class declarations . In the class section you can only list property initializations and method sections. No code may reside there.

    class xyz {
        if (true) {}
        foreach ($var) {}
    

    Such syntax errors commonly materialize for incorrectly nested { and } . In particular when function code blocks got closed too early.

  3. Statements in expression context

    Most language constructs can only be used as statements . They aren't meant to be placed inside other expressions:

                       ⇓
    $var = array(1, 2, foreach($else as $_), 5, 6);
    

    Likewise can't you use an if in strings, math expressions or elsewhere:

                   ⇓
    print "Oh, " . if (true) { "you!" } . " won't work";
    // Use a ternary condition here instead, when versed enough.
    

    For embedding if -like conditions in an expression specifically, you often want to use a ?: ternary evaluation .

    The same applies to for , while , global , echo and a lesser extend list .

              ⇓
    echo 123, echo 567, "huh?";
    

    Whereas print() is a language builtin that may be used in expression context. (But rarely makes sense.)

  4. Reserved keywords as identifiers

    You also can't use do or if and other language constructs for user-defined functions or class names. (Perhaps in PHP7. But even then it wouldn't be advisable.)


غير متوقع T_CONSTANT_ENCAPSED_STRING
T_ENCAPSED_AND_WHITESPACE غير متوقع

تشير الأسماء T_CONSTANT_ENCAPSED_STRING عملية T_CONSTANT_ENCAPSED_STRING و T_ENCAPSED_AND_WHITESPACE إلى القيم الحرفية "string" المقتبسة.

يتم استخدامها في سياقات مختلفة ، ولكن مشكلة تركيب الجملة متشابهة تمامًا. T_ENCAPSED ... تحدث التحذيرات في سياق سلسلة مقتبس مزدوج ، في حين أن السلاسل T_CONSTANT… غالبًا ما تكون ضالة في عبارات أو عبارات PHP.

  1. الاستيفاء متغير غير صحيح

    ويأتي في معظم الأحيان لاستيفاء متغير PHP غير صحيح:

                              ⇓     ⇓
    echo "Here comes a $wrong['array'] access";
    

    نقلا عن مفاتيح صفائف أمر لا بد منه في سياق PHP. ولكن في سلاسل مزدوجة مقتبسة (أو HEREDOCs) هذا خطأ. يشكو المحلل اللغوي من 'string' مفردة 'string' ، لأنه عادة ما يتوقع معرف / مفتاح حرفية هناك.

    بتعبير أدق ، يكون من الصواب استخدام بنية بسيطة على نمط PHP2 ضمن علامات تنصيص مزدوجة لمراجع الصفيف:

    echo "This is only $valid[here] ...";
    

    ومع ذلك ، تتطلب المصفوفات المتداخلة أو مراجع الكائنات الأكثر عمقًا صيغة تعبير سلسلة التجميع المعقدة :

    echo "Use {$array['as_usual']} with curly syntax.";
    

    إذا لم تكن متأكدًا ، فسيكون استخدام هذا الأمر أكثر أمانًا. انها في كثير من الأحيان تعتبر أكثر قابلية للقراءة. و IDEs أفضل بالفعل استخدام تلوين بناء الجملة مميزة لذلك.

  2. سلسلة مفقودة

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

                           ⇓
    print "Hello " . WORLD  " !";
    

    في حين أنه من الواضح بالنسبة لك ولي ، فبإمكان PHP ألا يخمن أن السلسلة كان من المفترض أن يتم إلحاقها به.

  3. مربعات الاقتباس سلسلة مربكة

    يحدث خطأ بناء الجملة نفسه عند conf deling سلسلة المحددات . تنتهي أيضًا سلسلة تبدأ بـ " اقتباس " مفرد أو " مضاعف " .

                    ⇓
    print "<a href="' . $link . '">click here</a>";
          ⌞⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟
    

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

    تلميح : قم بتعيين المحرر / IDE الخاص بك لاستخدام التلوين المميز قليلاً للسلاسل المقتبسة الفردية والمزدوجة. (كما أنه يساعد في منطق التطبيق على تفضيل مثل السلاسل المزدوجة المقتبسة للإخراج النصي ، والسلاسل المقتبسة الوحيدة فقط للقيم المتشابهة.)

    هذا مثال جيد حيث لا ينبغي عليك الخروج من علامات الاقتباس المزدوجة في المقام الأول. بدلاً من ذلك ، استخدم فقط \" الهروب لسمات HTML ' المناسبة :

    print "<a href=\"{$link}\">click here</a>";
    

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

  4. افتراضية افتتاحية الافتتاح

    يتم تجاهل فتح " / ' وصفًا لأخطاء المحلل اللغوي:

                   ⇓
     make_url(login', 'open');
    

    هنا ', ' سوف يصبح ', ' سلسلة حرفية بعد bareword ، عندما كان من الواضح أن login كان يعني أن يكون معلمة سلسلة.

  5. قوائم المصفوفة

    إذا فاتتك a , فاصلة في كتلة إنشاء مصفوفة ، سيرى المحلل اللغوي سلسلتين متتاليتين:

    array(               ⇓
         "key" => "value"
         "next" => "....",
    );
    

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

  6. قوائم المعلمات الدالة

    نفس الشيء للمكالمات الدالة :

                             ⇓
    myfunc(123, "text", "and"  "more")
    
  7. سلاسل جامدة

    وهناك تباين مشترك هو ببساطة نسيان سلسلة terminators:

                                    ⇓
    mysql_evil("SELECT * FROM stuffs);
    print "'ok'";
          ⇑
    

    هنا PHP يشكو من اثنين من حرفية سلسلة يتبعون بعضهم البعض مباشرة. لكن السبب الحقيقي هو السلسلة السابقة غير المغلقة بالطبع.

أنظر أيضا


Unexpected T_IS_EQUAL
Unexpected T_IS_GREATER_OR_EQUAL
Unexpected T_IS_IDENTICAL
Unexpected T_IS_NOT_EQUAL
Unexpected T_IS_NOT_IDENTICAL
Unexpected T_IS_SMALLER_OR_EQUAL
Unexpected <
Unexpected >

Comparison operators such as == , >= , === , != , <> , !== and <= or < and > mostly should be used just in expressions, such as if expressions. If the parser complains about them, then it often means incorrect paring or mismatched ( ) parens around them.

  1. Parens grouping

    In particular for if statements with multiple comparisons you must take care to correctly count opening and closing parenthesis :

                            ⇓
    if (($foo < 7) && $bar) > 5 || $baz < 9) { ... }
                          ↑
    

    Here the if condition here was already terminated by the )

    Once your comparisons become sufficiently complex it often helps to split it up into multiple and nested if constructs rather.

  2. isset() mashed with comparing

    A common newcomer is pitfal is trying to combine isset() or empty() with comparisons:

                            ⇓
    if (empty($_POST["var"] == 1)) {
    

    Or even:

                        ⇓
    if (isset($variable !== "value")) {
    

    This doesn't make sense to PHP, because isset and empty are language constructs that only accept variable names. It doesn't make sense to compare the result either, because the output is only/already a boolean.

  3. Confusing >= greater-or-equal with => array operator

    Both operators look somewhat similar, so they sometimes get mixed up:

             ⇓
    if ($var => 5) { ... }
    

    You only need to remember that this comparison operator is called " greater than or equal " to get it right.

    See also: If statement structure in PHP

  4. Nothing to compare against

    You also can't combine two comparisons if they pertain the same variable name:

                     ⇓
    if ($xyz > 5 and < 100)
    

    PHP can't deduce that you meant to compare the initial variable again. Expressions are usually paired according to operator precedence , so by the time the < is seen, there'd be only a boolean result left from the original variable.

    See also: unexpected T_IS_SMALLER_OR_EQUAL

  5. Comparison chains

    You can't compare against a variable with a row of operators:

                      ⇓
     $reult = (5 < $x < 10);
    

    This has to be broken up into two comparisons, each against $x .

    This is actually more a case of blacklisted expressions (due to equivalent operator associativity). It's syntactically valid in a few C-style languages, but PHP wouldn't interpret it as expected comparison chain either.

  6. Unexpected >
    Unexpected <

    The greater than > or less than < operators don't have a custom T_XXX tokenizer name. And while they can be misplaced like all they others, you more often see the parser complain about them for misquoted strings and mashed HTML:

                            ⇓
    print "<a href='z">Hello</a>";
                     ↑
    

    This amounts to a string "<a href='z" being compared > to a literal constant Hello and then another < comparison. Or that's at least how PHP sees it. The actual cause and syntax mistake was the premature string " termination.

أنظر أيضا:


Unexpected T_LNUMBER

In PHP, and most other programming languages, variables cannot start with a number. The first character must be alphabetic or an underscore.

$1   // Bad
$_1  // Good

Unexpected '?'

If you are trying to use the null coalescing operator ?? in a version of PHP prior to PHP 7 you will get this error.

<?= $a ?? 2; // works in PHP 7+
<?= (!empty($a)) ? $a : 2; // All versions of PHP

غير متوقع

في هذه الأيام ، يتم عرض مجموعة الفلاتر غير المتوقعة في إصدارات PHP القديمة. يتوفر بناء جملة الصفيف القصير منذ PHP > = 5.4 . المنشآت القديمة تدعم فقط array() .

$php53 = array(1, 2, 3);
$php54 = [1, 2, 3];
         ⇑

كذلك لا تتوفر ميزة إلغاء الإشارة في نتيجة المصفوفة نتيجة لإصدارات PHP الأقدم:

$result = get_whatever()["key"];
                      ⇑

المرجع - ماذا يعني هذا الخطأ في PHP؟ - "خطأ في بناء الجملة ، غير متوقع \[ " يعرض الحلول الأكثر شيوعًا وعملية.

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

أنظر أيضا:

راجع للشغل ، وهناك أيضا preprocessors وبناء أسفل PHP 5.4 محولات إذا كنت حقا clingy مع الإصدارات القديمة + أبطأ PHP.

أسباب أخرى للأخطاء غير الصحيحة [ بناء الجملة]

إذا لم يكن عدم تطابق إصدار PHP ، فيكون في كثير من الأحيان خطأ مطبعي عادي أو خطأ في تركيب الوافد الجديد:

  • لا يمكنك استخدام تعريفات أو مصطلحات خاصية الصفيف في الفصول ، ولا حتى في PHP 7.

    protected $var["x"] = "Nope";
                  ⇑
    
  • مربكة [ مع فتح أقواس معقوفة { أو أقواس ( إشراف شائع.

    foreach [$a as $b)
            ⇑
    

    او حتى:

    function foobar[$a, $b, $c] {
                   ⇑
    
  • أو محاولة ثوابت الانحراف (قبل PHP 5.6) كمصفوفات:

    $var = const[123];
           ⇑
    

    يفسر PHP على الأقل أن const ك a اسم ثابت.

    إذا كنت تقصد الوصول إلى متغير صفيف (وهو السبب النموذجي هنا) ، فقم بإضافة sigil $ الرائدة - بحيث يصبح اسم $varname .


غير متوقع ] إغلاق قوس مربع

هذا ندر إلى حد ما ، ولكن هناك أيضا حوادث تركيبية مع مجموعة مصفوفة الإنهاء.

  • عدم التطابق مرة أخرى مع ) الأقواس أو الأقواس المتعرجة شائعة:

    function foobar($a, $b, $c] {
                              ⇑
    
  • أو محاولة إنهاء صفيف لا يوجد فيه أحد:

    $var = 2];
    

    والذي يحدث غالبًا في إعلانات الصفيف المتعددة الخطوط والمتداخلة .

    $array = [1,[2,3],4,[5,6[7,[8],[9,10]],11],12]],15];
                                                 ⇑
    

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


غير متوقع

عادةً ما يتبع فتح الأقواس بنى اللغة مثل / foreach / for / array / list أو بدء تعبير حسابي. إنها غير صحيحة من الناحية النحوية بعد "strings" ، و () سابقة ، و $ وحيد ، وفي بعض سياقات الإعلان النموذجية.

  1. معلمات تعريف الدالة

    محاولة نادرة لهذا الخطأ تحاول استخدام تعبيرات كمعلمات الدالة الافتراضية . هذا غير مدعوم ، حتى في PHP7:

    function header_fallback($value, $expires = time() + 90000) {
    

    يمكن أن تكون المعلمات في تعريف الدالة قيمًا حرفية أو تعبيرات ثابتة فقط. على عكس الدعوات الوظيفية ، حيث يمكنك استخدام whatever(1+something()*2) بحرية whatever(1+something()*2) إلخ.

  2. افتراضيات خاصية الفئة

    نفس الشيء بالنسبة لإعلانات أعضاء الفئة ، حيث يتم السماح فقط بالقيم الحرفية / الثابتة ، وليس التعبيرات:

    class xyz {                   ⇓
        var $default = get_config("xyz_default");
    

    ضع مثل هذه الأشياء في المنشئ. راجع أيضًا لماذا لا تسمح سمات PHP بالوظائف؟

    لاحظ مرة أخرى أن PHP 7 لا تسمح إلا بـ var $xy = 1 + 2 +3; تعابير ثابتة هناك.

  3. بناء جافا سكريبت في PHP

    استخدام جافا سكريبت أو بناء الجملة jQuery لن يعمل في PHP لأسباب واضحة:

    <?php      ⇓
        print $(document).text();
    

    عندما يحدث هذا ، فإنه يشير عادة إلى سلسلة سابقة غير محوَّرة. ومقاطع <script> الحرفية التي تتسرب إلى سياق شفرة PHP.

  4. isset (()) ، فارغ ، مفتاح ، التالي ، الحالي

    كل من isset() و empty() هي لغة مدمجة ، وليس وظائف. انهم بحاجة للوصول إلى متغير مباشرة . إذا أضفت عن غير قصد زوجًا من الأقواس كثيرًا ، فحينئذٍ يمكنك إنشاء تعبير:

              ⇓
    if (isset(($_GET["id"]))) {
    

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

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


غير متوقع )

  1. غائبة وظيفة المعلمة

    لا يمكن أن يكون لديك فواصل طائشة تدوم في استدعاء دالة . PHP تتوقع قيمة هناك وبالتالي يشتكي قوس إغلاق مبكر.

                  ⇓
    callfunc(1, 2, );
    

    يسمح بفاصلة زائدة فقط في بنيات array() أو list() .

  2. عبارات غير منتهية

    If you forget something in an arithmetic expression, then the parser gives up. Because how should it possibly interpret that:

                   ⇓
    $var = 2 * (1 + );
    

    And if you forgot the closing ) even, then you'd get a complaint about the unexpected semicolon instead.

  3. Foreach as constant

    For forgotten variable $ prefixes in control statements you will see:

                       ↓    ⇓
    foreach ($array as wrong) {
    

    PHP here sometimes tells you it expected a :: instead. Because a class::$variable could have satisfied the expected $variable expression..


Unexpected {

Curly braces { and } enclose code blocks. And syntax errors about them usually indicate some incorrec nesting.

  1. Unmatched subexpressions in an if

    Most commonly unbalanced ( and ) are the cause if the parser complains about the opening curly { appearing too early. مثال بسيط:

                                  ⇓
    if (($x == $y) && (2 == true) {
    

    Count your parens or use an IDE which helps with that. Also don't write code without any spaces. Readability counts.

  2. { and } in expression context

    You can't use curly braces in expressions. If you confuse parentheses and curlys, it won't comply to the language grammer:

               ⇓
    $var = 5 * {7 + $x};
    

    There are a few exceptions for identifier construction, such as local scope variable ${references} .

  3. Variable variables or curly var expressions

    This is pretty rare. But you might also get { and } parser complaints for complex variable expressions:

                          ⇓
    print "Hello {$world[2{]} !";
    

    Though there's a higher likelihood for an unexpected } in such contexts.


Unexpected }

When getting an "unexpected } " error, you've mostly closed a code block too early.

  1. Last statement in a code block

    It can happen for any unterminated expression.

    And if the last line in a function/code block lacks a trailing ; semicolon:

    function whatever() {
        doStuff()
    }            ⇧
    

    Here the parser can't tell if you perhaps still wanted to add + 25; to the function result or something else.

  2. Invalid block nesting / Forgotten {

    You'll sometimes see this parser error when a code block was } closed too early, or you forgot an opening { even:

    function doStuff() {
        if (true)    ⇦
            print "yes";
        }
    }   ⇧
    

    In above snippet the if didn't have an opening { curly brace. Thus the closing } one below became redundant. And therefore the next closing } , which was intended for the function, was not associatable to the original opening { curly brace.

    Such errors are even harder to find without proper code indentation. Use an IDE and bracket matching.


Unexpected { , expecting (

Language constructs which require a condition/declaration header and a code block will trigger this error.

  1. Parameter lists

    For example misdeclared functions without parameter list are not permitted:

                     ⇓
    function whatever {
    }
    
  2. Control statement conditions

    And you can't likewise have an if without condition .

      ⇓
    if {
    }
    

    Which doesn't make sense, obviously. The same thing for the usual suspects, for / foreach , while / do , etc.

    If you've got this particular error, you definitely should look up some manual examples.


Unexpected $end

When PHP talks about an "unexpected $end ", it means that your code ended prematurely. (The message is a bit misleading when taken literally. It's not about a variable named "$end", as sometimes assumed by newcomers. It refers to the "end of file", EOF .)

Cause: Unbalanced { and } for code blocks / and function or class declarations.

It's pretty much always about a missing } curly brace to close preceding code blocks.

  • Again, use proper indentation to avoid such issues.

  • Use an IDE with bracket matching, to find out where the } is amiss. There are keyboard shortcuts in most IDEs and text editors:

    • NetBeans, PhpStorm, Komodo: Ctrl [ and Ctrl ]
    • Eclipse, Aptana: Ctrl Shift P
    • Atom, Sublime: Ctrl m - Zend Studio Ctrl M
    • Geany, Notepad++: Ctrl B - Joe: Ctrl G - Emacs: CMn - Vim: %

Most IDEs also highlight matching braces, brackets and parentheses. Which makes it pretty easy to inspect their correlation:

Unterminated expressions

And Unexpected $end syntax/parser error can also occur for unterminated expressions or statements:

  • $var = func(1, ?> EOF

So, look at the end of scripts first. A trailing ; is often redundant for the last statement in any PHP script. But you should have one. Precisely because it narrows such syntax issues down.

Indented HEREDOC markers

Another common occurrence appears with HEREDOC or NOWDOC strings. The terminating marker goes ignored with leading spaces, tabs, etc.:

print <<< END
    Content...
    Content....
  END;
# ↑ terminator isn't exactly at the line start

Therefore the parser assumes the HEREDOC string to continue until the end of the file (hence "Unexpected $end"). Pretty much all IDEs and syntax-highlighting editors will make this obvious or warn about it.

Alternative syntax

Somewhat rarer you can see this syntax error when using the alternative syntax for statement/code blocks in templates. Using if: and else: and a missing endif; for example.

أنظر أيضا:


أعتقد أن هذا الموضوع مبالغة تماما / overcomplicated. استخدام IDE هو طريقة للذهاب لتجنب أي أخطاء في بناء الجملة. أود أن أقول إن العمل بدون IDE هو نوع من غير المهني. لماذا ا؟ لأن IDEs الحديثة تحقق من بناء الجملة بعد كل حرف تكتبه. عندما تتحول الشفرة وتحوّل خطك بالكامل إلى اللون الأحمر ، ويظهر لك إشعار تحذير كبير النوع الدقيق والموضع المحدد لخطأ في بناء الجملة ، فلن تكون هناك حاجة مطلقًا للبحث عن حل آخر.

استخدام IDE تدقيق بناء الجملة يعني:

لن تتعرض (بشكل فعال) أبدًا لأخطاء بناء الجملة مرة أخرى ، ببساطة لأنك تراها مباشرة أثناء الكتابة. بشكل جاد.

IDEs ممتازة مع التحقق من بناء الجملة (كل منهم متاح لينكس ، ويندوز وماك):

  1. NetBeans [مجاني]
  2. PHPStorm [199 دولارًا أمريكيًا]
  3. Eclipse مع PHP البرنامج المساعد [مجاني]
  4. Sublime [$ 80 USD] (بشكل رئيسي محرر نصوص ، ولكن قابلة للتوسيع مع ملحقات إضافية ، مثل محلل بناء جملة PHP )

كل إجابة هنا تغطي فقط جزء من المشكلة. في الواقع ، هناك أربعة أجزاء استعلام مختلفة يمكننا إضافتها إليها ديناميكيًا:

  • سلسلة
  • رقم
  • معرف
  • كلمة أساسية في بناء الجملة.

وتغطي البيانات المعدة فقط اثنين منهم.

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

بشكل عام ، يعتمد نهج الحماية هذا على القائمة البيضاء .

في هذه الحالة ، يجب أن تكون كل معلمة ديناميكية ضمنية في النص البرمجي ويتم اختيارها من هذه المجموعة. على سبيل المثال ، لتنفيذ الطلب الديناميكي:

$orders  = array("name", "price", "qty"); // Field names
$key     = array_search($_GET['sort'], $orders)); // See if we have such a name
$orderby = $orders[$key]; // If not, first one will be set automatically. smart enuf :)
$query   = "SELECT * FROM `table` ORDER BY $orderby"; // Value is safe

ومع ذلك ، هناك طريقة أخرى لتأمين المعرفات - الهروب. طالما كان لديك مُعرّف مُقتبس ، يمكنك الهروب من backticks في الداخل عن طريق مضاعفة.

وكخطوة أخرى ، يمكننا استعارة فكرة رائعة حقًا عن استخدام عنصر نائب (وكيل يمثل القيمة الفعلية في الاستعلام) من البيانات المعدة وأخترع عنصر نائب من نوع آخر - عنصر نائب.

لذا ، لجعل القصة طويلة قصيرة: إنه عنصر نائب ، لا يمكن اعتبار العبارة الجاهزة كدائرة فضية.

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

ومع ذلك ، هناك مشكلة مع الكلمات الأساسية لغوي SQL (مثل AND DESC و) ، ولكن يبدو أن القائمة البيضاء هي الطريقة الوحيدة في هذه الحالة.

تحديث

على الرغم من وجود اتفاق عام على أفضل الممارسات فيما يتعلق بحماية حقن SQL ، فلا يزال هناك العديد من الممارسات السيئة كذلك. وبعضها عميق الجذور في عقول مستخدمي PHP. على سبيل المثال ، في هذه الصفحة بالذات هناك (على الرغم من أنه غير مرئي لمعظم الزوار) أكثر من 80 إجابات محذوفة - تمت إزالتها جميعًا من قبل المجتمع بسبب الجودة السيئة أو الترويج للممارسات السيئة التي عفا عليها الزمن. والأسوأ من ذلك أن بعض الإجابات السيئة لا تُحذف ، بل تزدهر.

على سبيل المثال ، there(1) are(2) still(3) many(4) answers(5) many(4) answers(5) ، بما في ذلك share تقترح عليك الهروب اليدوي للسلسلة - وهو أسلوب قديم ثبت أنه غير آمن.

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

أعتقد أن كل هذا بسبب خرافة قديمة جدا ، مدعومة من قبل مثل هذه السلطات مثل OWASP أو دليل PHP ، والتي تعلن المساواة بين أي "الهروب" والحماية من حقن SQL.

بغض النظر عن ما قاله دليل PHP للأعمار ، فإن *_escape_string بأي حال من الأحوال يجعل البيانات آمنة ولا يُقصد بها أبدًا. إلى جانب كونه لا جدوى لأي جزء من أجزاء SQL بخلاف السلسلة ، فإن الهروب اليدوي يكون خاطئًا ، لأنه دليل على عكس ما هو أوتوماتيكي.

و OWASP يجعل الأمر أكثر سوءا ، مؤكدا على الهروب من مدخلات المستخدم وهو محض هراء: لا ينبغي أن يكون هناك مثل هذه الكلمات في سياق حماية الحقن. كل متغير يحتمل أن تكون خطرة - بغض النظر عن المصدر! أو بعبارة أخرى - يجب أن يتم تنسيق كل متغير بشكل صحيح ليتم وضعه في استعلام - بغض النظر عن المصدر مرة أخرى. إنها الوجهة المهمة. في اللحظة التي يبدأ فيها المطور في فصل الأغنام عن الماعز (مع الأخذ في الاعتبار ما إذا كان هناك متغير معين هو "آمن" أم لا) ، فإنه يأخذ أول خطوة نحو الكارثة. ناهيك عن أن حتى الصياغة تقترح الهروب بالجملة عند نقطة الدخول ، تشبه ميزة المقولات السحرية للغاية - المحتقنة بالفعل ، التي تم إهمالها وإزالتها.

لذا ، على عكس أي "هروب" ، فإن البيانات المعدة هي المقياس الذي يحمي بالفعل من حقن SQL (عند الاقتضاء).

إذا كنت مازلت غير مقتنع ، فإليك شرحًا تفصيليًا كتبته ، دليل Hitchhiker's to Prevention SQL prevent ، حيث شرحت كل هذه الأمور بالتفصيل وحتى جمعت قسمًا مخصصًا بالكامل للممارسات السيئة وإفشاءها.





php parsing debugging syntax-error