1

私は何か奇妙なことに遭遇しています、そしてそれがなぜ起こっているのか分かりません!

私は次のようなURLを持っています:

http://mysite.com/users/USER_ID

このユーザーIDは、FacebookページアドレスのようなものであるINT可能性があります。ページIDをロードしてページを呼び出すと、「my_page_name」のようなページ名で呼び出すこともできます。STRING

1したがって、IDがあり、アドレスがであるユーザーを想像してみてmy_name ください。私のphpページでは、クエリデータベースが必要ですが、その前に、どの列を検索するかを知る必要がありますidpage_name

だから私はこの解決策を思いついた:

<?php
    $id = $_GET['id'];
    $id_inted = intval($_GET['id']);

    if($id == $id_inted){
    // The column which I should look into is id
    $column = 'id';
    }else{
    // The column which I should look into is page_name
    $column = 'page_name';
    }

    $query = mysql_qyery(SELECT * FROM members WHERE $column = '$id');
?>

それで私はそれをテストしました、しかし私がこのURLを呼んでも、結果は奇妙です:

http://mysite.com/users/page_name

これは起こります:$column = 'id';

新しいテストページを開きました:

<?php
$real_string = 'abcdefg';
$string_inted = intval($real_string);
echo "Real String is: " . $real_string . "<br />"; 
echo "The same string as int is: " . $string_inted . "<br />"; 
if($real_string == $string_inted) echo "Weird!"; else echo "Fine...";
?>

そして結果:

Real String is: abcdefg
The same string as int is: 0
Weird!

なぜこれが起こっているのですか?

前もって感謝します。

4

5 に答える 5

5

PHPは、いわゆる型ジャグリングと実際に「配線」されています。これは、ほとんどのPHPスクリプトの中で最もエラーが発生しやすい部分です。そのため、常に安全を確保し、最も堅牢なチェックを使用する必要があります。たとえばintval("twelve")、有効な整数である0を返します。しかし、「false」とも見なされますprint if (intval("one")) ? "yup" : "nope"。「nope」を出力します。

この場合、intval整数がゼロより大きいかどうかのチェックと組み合わせてを使用すると、トリックを実行する必要があります。

<?php
$id = intval($_GET['id']);

if($id > 0){
  // The column which I should look into is id
  $column = 'id';
}else{
  // The column which I should look into is page_name
  $column = 'page_name';
}

$query = mysql_qyery(SELECT * FROM members WHERE $column = '$id');
?>

または、短い:

$id = intval($_GET['id']);

$column = ($id > 0) ? "id" : "page_name";
$query = mysql_qyery(SELECT * FROM members WHERE $column = '$id');

$ _GET ["id"]が設定されていない可能性があることに注意してください。これにより、コードに通知がスローされます。

そして最後に、もちろん重要なことですがSQLインジェクション?id=LittleBobby';Drop table users

編集コメンターが指摘しているように、私のコードには論理的な欠陥があり、phpshでのみテストしたという事実に端を発しています。is_int()tointvalとを使用しないようにリファクタリングしました> 0。Web環境では、$ _GET["id"]は常に文字列です。何があっても。したがってis_int()、常に。を返しFALSEます。

于 2012-12-08T11:34:23.103 に答える
4

数値が要求されているかどうかを確認するには、を使用しますis_numeric

于 2012-12-08T11:19:47.717 に答える
2

型に関しては、PHP は少し奇妙です。

基本的に、あなたがしているのは、文字列を数値に解析して ('abcdef'数値ではないため 0 を返します)、元の文字列を数値と比較することです。

これで、これが誤りであると仮定する理由がわかりましたが、PHP は賢くしようとしています。基本的に、==型を強制し、その値の 1 つが数値である場合、ほとんどの場合、数値を強制します。したがって、文字列に対して行ったのと同じ変換を使用してから比較しています。

===型もチェックする whichを使用することをお勧めします。

于 2012-12-08T11:14:52.283 に答える
2

http://php.net/manual/en/language.operators.comparison.phpから

Example       Name        Result

$a == $b      Equal       TRUE if $a is equal to $b after type juggling.

$a === $b     Identical   TRUE if $a is equal to $b,
                          and they are of the same type. 

==演算子の型ジャグリングとintval()文字列の戻り値のため、文字列は整数にキャストされます0

$id == $id_intedこれは、コードで true と評価される理由を説明しています。

===代わりにno 型でテストを行うと、==ジャグリングが実行されます。

于 2012-12-08T11:13:26.130 に答える
1

成功した場合は var の整数値、失敗した場合は 0。空の配列は 0 を返し、空でない配列は 1 を返します (php.net intval() より)

intval('abcdefg') はエラーをトリガーし、関数は 0 を返します。

于 2012-12-08T11:11:14.170 に答える