2012-05-30 295 views
31

我想重新學習一些簡單的登錄腳本的PHP基礎知識,但是我得到一個錯誤,我還沒有收到過(我做了一年多一點的同一個腳本,從來沒有這個錯誤我簡化了代碼,就像我所能來測試一下,看看哪個區域是有問題的,這裏的問題:

<?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 

沒有用戶名供應

正如你所看到的代碼註冊,沒有變量被提供,但是它給出了和錯誤,我認爲意味着一個變量沒有被發現是一個預期的或類似的東西。有人能爲我澄清這一點嗎?

+0

發佈您的表單代碼。它看起來像_POST [用戶名]沒有設置 –

+0

因爲如果你所做的一切都正確,你只需在HTML頁面方法中命名爲'get'並且你用'$ _POST'捕獲參數。您需要將其重命名爲$ _GET。就這些。 – CodeToLife

回答

39

在PHP中,從未設置的變量或數組元素與值爲null的變量或數組元素不同;試圖訪問這樣的一個未設置值是一個運行時錯誤。

這就是你遇到的情況:數組$_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確實串插,所以在ifecho語句可以合併成一個:

echo "$user is your username"; 
+5

謝謝。非常徹底但簡單的答案,爲什麼我得到這個錯誤以及如何解決它。我不只是想要一個「如何修復/擺脫這個錯誤」的答案,我想了解它,這就是你爲我所做的,謝謝。 –

+0

@ViperCode你的'$ _POST [「username」]'變量未設置 – Bender

6

用途:

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 
} 

消毒和驗證。

+1

或者,您可以使用'array_key_exists($ _ POST,'user')' – mpen

+0

我喜歡您所說的確保。這基本上是一個登錄腳本,我打算使用mysql_real_escape();我相信它就是所謂的。用戶名將是事物和密碼的任意組合,只應該是MD5,在發送給腳本之前在程序中進行散列。另外我應該注意到,這是一個遊戲的驗證,而不是一個網站。 –

+0

Never,EVER,使用mysql_real_escape()。瞭解準備好的陳述並開始使用PDO。 http://php.net/manual/pdo.prepared-statements.php – vinnylinux

1

當你說:

$user = $_POST["username"]; 

你問PHP解釋器將$_POST數組的值設爲$user,該數組的密鑰(或索引)爲username。如果它不存在,PHP會拋出一個合適的結果。

使用isset($_POST['user'])檢查該變量的存在:

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

謝謝,就像mark reed解釋過的那樣。 –

3

您的代碼假定的東西存在:

$user = $_POST["username"]; 

PHP是讓你知道,有沒有「用戶名「在$_POST陣列中。在這種情況下,你會更安全檢查,看看是否值isset()試圖訪問它之前:或者

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

,你可以HI-插孔||運營商分配默認:

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

只要用戶的名字不是價值的,你可以認爲這種方法相當可靠。一個更安全的路線默認賦值是使用三元運算符:

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

嘗試

if(isset($_POST['username'])) 
    echo $_POST['username']." is your username"; 
else 
    echo "no username supplied"; 
+1

謝謝。我剛剛沒有遇到這個錯誤,現在我明白了。 –

-2

相關問題:What is the best way to access unknown array elements without generating PHP notice?

使用從問題的答案上面,你如果密鑰不存在,可以安全地從$ _POST獲取值,而不會生成PHP通知。

echo _arr($_POST, 'username', 'no username supplied'); 
// will print $_POST['username'] or 'no username supplied' 
+0

這在很多層面都是錯誤的... – vinnylinux

+0

Downvoters&@vinnylinux:爲什麼它錯了? – flowfree

+0

可能是因爲它不會產生輸出,OP希望'[username]是你的用戶名(我不是那個downvoted的人,如果這很重要,那麼理由可能會不同)? – tigrang

1

相反的isset()你可以用更短的東西越來越靜音的錯誤,這是@$_POST['field']。然後,如果該字段未設置,您將不會在頁面上打印錯誤。

1

試試這個:

我在任何地方使用$ _POST請求。

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

這只是一個短暫的手布爾值,如果isset將其設置爲$ _POST [「用戶名」],如果沒有,那麼它會爲它設置爲空字符串。

用例:

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

在此之前PHP 5.2.0及以上,你應該使用哪一個專爲創建filter_input()得到一個特定的外部用戶輸入諸如姓名GET,POST或餅乾變量可以對其進行過濾以避免您的站點發生任何XSS /注入攻擊。例如:

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

您可以使用INPUT_GET,INPUT_POST,INPUT_COOKIE,INPUT_SERVER,或INPUT_ENV之一。

通過使用可選的第三個參數,則可以通過各種filters(對於validatingsanitizingfilteringother),例如它延伸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>"; 
?> 

的語法是:

混合filter_input(INT $型,字符串$變量名[摘要$濾波器= FILTER_DEFAULT [,混合(PHP 5> = 5.2.0,PHP 7)

參見:Why is better to use filter_input()?

0

我知道這是舊的文章,但有人可以幫助:

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."; 
} 

另外我補充$default字符串,你可以定義一些默認的值,如果POST未激活或內容不存在。

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

播放它。