web-dev-qa-db-ja.com

$ _POSTを使用した未定義のインデックス

単純なログインスクリプトを作成するためのいくつかのPHP基本を再学習しようとしていますが、以前に受け取ったことのないエラーが発生します(同じスクリプトを1年以上前に作成し、このエラーは一度もありませんでした。どの領域に問題があるかを確認するためにテストできる限りコードを簡素化しました。問題は次のとおりです。

<?php
$user = $_POST["username"];
if($user != null)
{
    echo $user;
    echo " is your username";
}
else
{
    echo "no username supplied";
}
?>

現在、このコードは変数をスクリプトに送信すると正常に機能しますが、変数が指定されていない場合はエラーが発生します。ユーザー名/パスが指定されていない場合はエラーが予想されるため、理論的にはこれで問題ありません。コードがスクリプトに送信される前に、これを確認するためにチェックしますが、どういうわけか空の文字列が漏れて、未知のエラーを吐き出すのではないかと心配しています。ここに私が得るエラーがあります:

( ! ) Notice: Undefined index: username in C:\wamp\www\verify_login.php on line 2

Call Stack

    Time    Memory  Function    Location
1   0.0003  668576  {main}( )   ..\verify_login.php:0

ユーザー名が指定されていません

コードが変数を提供していないことを確認できますが、変数が見つからないことを意味するものと想定されるエラーが発生します。誰かがこれを明確にしてくれますか?

37
Xander Luciano

PHPでは、設定されていない変数または配列要素は、値がnull;であるものとは異なります。そのようなnset値にアクセスしようとすると、ランタイムエラーになります。

それがあなたが実行していることです:配列$_POSTはキー"username"に要素を持たないため、インタープリターはプログラムが無効テストに到達する前に中止します。

幸いなことに、実際にアクセスしようとせずに、変数または配列要素の存在をテストできます。それが特別な演算子issetが行うことです:

if (isset($_POST["username"]))
{
  $user = $_POST["username"];
  echo $user;
  echo " is your username";
} 
else 
{
  $user = null;
  echo "no username supplied";
}

これは、PHPが$_POST["username"]の値を取得して関数isset()の引数として渡そうとすると、コードとまったく同じように爆発するようです。ただし、isset()は実際には関数ではなく、評価段階の前に認識される特別な構文なので、PHPインタープリターは実際に値を取得しようとせずに値の存在をチェックします。

また、実行時エラーが発生すると、欠落している配列要素はマイナーなものと見なされることにも注意してください(E_NOTICEレベルが割り当てられます)。 error_reportingレベルを変更して通知を無視する場合、元のコードは実際に書かれたとおりに機能し、配列アクセスを試みるとnullが返されます。しかし、それは、特に本番コードの場合、悪い習慣と見なされます。

サイドノート:PHPは文字列補間を行うため、echoブロック内のifステートメントは1つに結合できます。

echo "$user is your username";
50
Mark Reed

つかいます:

if (isset($_POST['user'])) {
   //do something
}

ただし、より適切な検証を使用する必要があります。 Zend FrameworkまたはSymfonyの単純な正規表現または堅実な実装を試してください。

http://framework.zend.com/manual/en/zend.validate.introduction.html

http://symfony.com/doc/current/book/validation.html

または、組み込みのフィルター拡張機能でも:

http://php.net/manual/en/function.filter-var.php

ユーザー入力を決して信用しないでください。何も信用しないでください。あなたが受け取るものが本当にあなたが期待するものであることを常に確認してください。数字にする必要がある場合は、必ず数字にしてください。

大幅に改善されたコード:

$user = filter_var($_POST['user'], FILTER_SANITIZE_STRING);
$isValid = filter_var($user, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => "/^[a-zA-Z0-9]+$/")));

if ($isValid) {
    // do something
}

消毒と検証。

6
vinnylinux

あなたのコード仮定何かの存在:

$user = $_POST["username"];

PHPは、$_POST配列に「ユーザー名」がないことを知らせています。この場合、値にアクセスしようとする前に、値isset()を確認する方が安全です。

if ( isset( $_POST["username"] ) ) {
    /* ... proceed ... */
}

または、||演算子をハイジャックしてデフォルトを割り当てることもできます。

$user = $_POST["username"] || "visitor" ;

ユーザーの名前がfalsyの値でない限り、この方法はかなり信頼できると考えることができます。 default-assignmentへのより安全なルートは、三項演算子を使用することです。

$user = isset( $_POST["username"] ) ? $_POST["username"] : "visitor" ;
3
Sampson

PHP 5.2.0以上の前に filter_input() を使用する必要があります。これは、名前、オプションでget、post、cookie変数などの特定の外部ユーザー入力を取得するために特に作成されますサイトでのXSS /インジェクション攻撃を防ぐためにフィルタリングします。例えば:

$user = filter_input(INPUT_POST, 'username');

INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER、またはINPUT_ENVのいずれかを使用できます。

オプションの3番目の引数を使用すると、さまざまな filtersvalidatingsanitizingfiltering または その他 )、たとえばFILTER_SANITIZE_SPECIAL_CHARSFILTER_SANITIZE_ENCODEDなど.

例えば:

<?php
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
$search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
echo "You have searched for $search_html.\n";
echo "<a href='?search=$search_url'>Search again.</a>";
?>

構文は次のとおりです。

mixed filter_input(int $ type、string $ variable_name [、int $ filter = FILTER_DEFAULT [、mixed $ options]])

(PHP 5> = 5.2.0、PHP 7)

参照: filter_input()を使用するほうが良いのはなぜですか?

2
kenorb

isset()の代わりに、エラーをミュートする短いものを使用できます。それは@$_POST['field']です。次に、フィールドが設定されていない場合、ページにエラーが出力されません。

2

これを試して:

私はこれを$ _POSTリクエストがあるすべての場所で使用します。

$username=isset($_POST['username']) ? $_POST['username'] : "";

これは単なる短いブール値です。issetの場合は$ _POST ['username']に設定され、そうでない場合は空の文字列に設定されます。

使用例:

if($username===""){ echo "Field is blank" } else { echo "Success" };
2
Rust

あなたが言う時:

$user = $_POST["username"];

PHPインタープリターに$userのキー(またはインデックス)がusernameである$_POST配列の値を割り当てるように要求しています。存在しない場合、PHPは適合します。

isset($_POST['user'])を使用して、その変数の存在を確認します。

if (isset($_POST['user'])) {
  $user = $_POST["username"];
  ...
1
Blender

私はこれが古い投稿であることを知っていますが、誰かが助けることができます:

function POST($index, $default=NULL){
        if(isset($_POST[$index]))
        {
            if(!empty(trim($_POST[$index])))    
                return $_POST[$index];
        }
        return $default;
    }

上記のこのコードは、どこでも使用している基本的なPOST関数です。ここでは、フィルター、正規表現などを配置できます。高速でクリーンです。私の高度なPOST関数は、配列、文​​字列型、デフォルト値などを受け入れてチェックするのがより複雑です。ここで想像力を働かせましょう。

次のようなユーザー名を簡単に確認できます。

$username = POST("username");
if($username!==null){
    echo "{$username} is in the house.";
}

また、POSTがアクティブでないかコンテンツが存在しない場合にデフォルト値を定義できる$default文字列を追加しました。

echo "<h1>".POST("title", "Stack Overflow")."</h1>";

それで遊びます。

試してみる

if(isset($_POST['username']))
    echo $_POST['username']." is your username";
else
    echo "no username supplied";
0
white-shy-guy