iT邦幫忙

0

PHP include function邏輯錯誤

php
  • 分享至 

  • xImage

這是一個進修時老師出的作業,但不管怎麼修正邏輯上輸入正確的帳號密碼總是回報錯誤
想麻煩各位高手幫忙找出錯誤所在.....(這段程式已經卡第三個星期了QWQ")

首先一個簡單的LOGIN頁面

<meta http-equiv="content-type" content="text/html"; charset = "UTF-8">


<form method = "POST" action = "view.php">
ID:<input type = "text" name = "acc"><br>
PW:<input type = "text" name = "pw"><br>
<input type = "submit" value = "送出">
</form>

然後是寫的自訂function,存成一個叫做function的檔案

<?php
$confirm = false;
function verity($acc,$pw,$user,$userData)
{
for($i = 0;$i < sizeof($user);$i++)
{
if($acc == $user[$i])
{
break;
} 
if($pw == $userdata[$i]['password'])
{
return $user[$i]['email'];
}
}

return false;
}
?>

user部分老師已經先寫好讓我們用include方式加入

<?php
$user = array(
 'allan',
 'bill',
 'cindy',
 'david'
);

$userData['allan'] = array(
 'password' => '1234',
 'email' => 'allan@csie.org'
);

$userData['bill'] = array(
 'password' => '5678',
 'email' => 'bill@ntu.edu.tw'
);

$userData['cindy'] = array(
 'password' => '0000',
 'email' => 'cindy@csie.tw'
);

$userData['david'] = array(
 'password' => '1111',
 'email' => 'david@gamil.com'
);
?>

最後是當輸入正會印出使用者EMAIL,但我總是會導到"讀取失敗",

<meta http-equiv="content-type" content="text/html"; charset = "UTF-8">


<?php
include('user.php');
include('function.php');

$check = verity($_POST['acc'],$_POST['pw'],$user,$userData);

if($confirm == 'true')
{
echo '電子信箱是'.$check;
}
else
{
echo '讀取失敗!!';
}
?>

檢查很久還是不知道錯誤在哪裡,所以希望有高手大大指導>"<
話說課程都衝到資料庫了我還卡在這裡QWQ"

看更多先前的討論...收起先前的討論...
外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:13:27 檢舉
那個函式的邏輯頗怪...
一般來說,使用者的驗證,要比對帳號與密碼都正確
而,這個函式,卻在比對到了正確的帳號之後,直接跳出迴圈,return false...
反而,沒有比對到正確帳號的,繼續驗證密碼....
所以,只有在輸入錯誤帳號、正確密碼的狀況下,才能取得email...
匪夷所思...落寞
外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:14:47 檢舉
雖然,這整個函式,在$confirm=false的影響下,永遠都不會顯示email...
但是,函式的邏輯設計,極需要重新思考一下囉
這是給老闆的陷阱 生鎖D槽大門 只有輸入錯誤的人可以進去汗毆飛
wiseguy iT邦超人 1 級 ‧ 2013-07-24 22:58:25 檢舉
wiselou兄用我們程式老江湖的眼光,看在進修班學程式的小老弟寫的東西,沒口吐白沫已經算好的了 ... 汗
wiseguy iT邦超人 1 級 ‧ 2013-07-24 23:10:52 檢舉
兩個技巧分享:
1. 這個範例 function 不需要用 for/foreach 迴圈,只要醬子即可:
function verity($acc,$pw,$user,$userData)
{
	return (in_array($acc, $user) && $userData[$acc]['password'] == $pw) ? $userData[$acc]['email']: false;
}

2. 如果要用迴圈,別在判斷式用函數
for($i = 0;$i < sizeof($user);$i++) // 這樣寫 sizeof() 會做5次

或改成倒反即就能優化
for($i = sizeof($user)-1; $i >= 0;$i--) // 這樣寫 sizeof() 只做1次
灑花灑花
筆記筆記
謝謝謝謝
wiseguy提到:
沒口吐白沫已經算好的了

那看我的程式可以心驚膽跳 三魂出竅了失神
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
16
外獅佬
iT邦大師 1 級 ‧ 2013-07-24 15:20:01
最佳解答

$confirm永遠都是false....落寞

看更多先前的回應...收起先前的回應...

獅子一出 鳥禽急跑逃跑

iT邦幫忙MVPwiselou提到:
$confirm永遠都是false....

這才是事實的真相 獅子觀察力太敏銳了!!

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 15:47:47 檢舉

程式出錯,永遠都是最簡單的那個環節惹的禍。

總裁 iT邦好手 1 級 ‧ 2013-07-24 15:48:31 檢舉

很多事情是不能勉強的...落寞

yesyesok iT邦研究生 4 級 ‧ 2013-07-24 16:00:51 檢舉

剛剛仔細看了一下果然= ="
只能說自己還有很多需要努力的地方ㄚ....(遠目

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:16:11 檢舉

函式本身的邏輯也有問題...多思考、測試囉

yesyesok大大 加油!!
多跌倒幾次就會走了讚

yesyesok iT邦研究生 4 級 ‧ 2013-07-24 16:28:19 檢舉

我重新改寫成這樣

&lt;pre class="c" name="code">

function verity($acc,$pw,$user,$userData)
{
for($i = 0;$i &lt; sizeof($user);$i++)
{
if($acc == $user[$i] && $pw == $userdata[$i]['password'])
{
$confirm = 'true';
return $user[$i]['email'];
}
else
{ 
$confirm = 'false';
return false;
}
}

}

結果還是錯誤QWQ"

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:30:14 檢舉

因為...$confirm是區域變數...Orz

yesyesok iT邦研究生 4 級 ‧ 2013-07-24 16:31:48 檢舉

大哥說的對.........Orz

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:33:08 檢舉

這個呢,要是我,會用by refrence回傳$email變數

&lt;pre class="c" name="code">
function verity($acc,$pw,$user,$userData,&$email){  
  for($i = 0;$i &lt; sizeof($user);$i++){
    if($acc == $user[$i] && $pw == $userdata[$i]['password']){
      $email = $user[$i]['email'];
      return true;
    }
  }  
  return false;  
}
外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:34:26 檢舉

不對啦!!是因為你的if else的問題啦!!
只會判斷第一組帳號密碼...只有輸入第一組帳號密碼才會得到email...
因為...else之後return false..迴圈結束。

temo iT邦新手 1 級 ‧ 2013-07-24 17:36:25 檢舉

汗我看不出來if else的邏輯哪裡錯.......
不是包在for迴圈裡面再用if else去判斷??
看了迴圈5分鐘還是看不出來哪裡錯,看來我還是太嫩了Orz

話說sizeof是陣列大小??跟user.length一樣?

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 17:39:15 檢舉

temo提到:
if else的邏輯哪裡錯

因為...只會比對第一筆資料...Orz
if...
return true;
else ...
return false;

temo iT邦新手 1 級 ‧ 2013-07-24 18:57:21 檢舉

瞭解,原來是把if else包在迴圈裡
所以跑完第一筆就直接判斷結束不會在傳回第二筆

自己寫出答案不過一下轉不過來.....Orz

temo iT邦新手 1 級 ‧ 2013-07-24 19:03:20 檢舉

打太快語句感覺怪怪......
應該說是else false在迴圈裡,所以只能抓出第一筆資料
第二筆直接判斷false了

沒在IDE裡跑一次直接看有時會直接給他順順的看過去暈

ted99tw iT邦高手 1 級 ‧ 2013-07-24 19:52:05 檢舉

temo提到:
打太快..感覺怪怪...

快慢其實沒什麼差啦,反正都是一翻兩瞪眼...

10
老鷹(eagle)
iT邦高手 1 級 ‧ 2013-07-24 15:16:33

我可以提另一種方式嗎?
我先口述一下,
當使用者key in帳密之後,傳送到驗證頁面
使用WHERE(帳) AND WHERE(密)當提取資料為null or 空值,
則返回登入頁面 當提取出有資料 提取echo E-MAIL.
假如要實CODE的再跟我說,我要轉回土砲模式不然我都是用框架開發

temo iT邦新手 1 級 ‧ 2013-07-24 17:38:55 檢舉

chingfeng提到:
土砲模式

疑惑

solzxer大大的土炮模式,手工純PHP.
我的是自走砲模式,PHP框架開發

10
純真的人
iT邦大師 1 級 ‧ 2013-07-24 16:19:21
&lt;pre class="c" name="code">


&lt;meta http-equiv="content-type" content="text/html"; charset = "UTF-8">


&lt;?php
include('user.php');
include('function.php');

$check = verity($_POST['acc'],$_POST['pw'],$user,$userData);

if($check)
{
echo '電子信箱是'.$check;
}
else
{
echo '讀取失敗!!';
}
?>
看更多先前的回應...收起先前的回應...
yesyesok iT邦研究生 4 級 ‧ 2013-07-24 16:26:49 檢舉

這個跟老師的解答很像,但我不了解的地方在於check在function裡只會回傳mail跟false,所以我另外設一個變數$confirm,用來判斷輸入資料是否正確,所以將check直接擺到判斷式裡的原因是?@@

外獅佬 iT邦大師 1 級 ‧ 2013-07-24 16:42:56 檢舉

因為...PHP是弱型別,所以用if($check===false)比對比較不會有閃失。

$check 也好, $confirm 也好
都是用來「接」verity function 的回傳值
一般寫在 function 外面
不必寫在 function 裡面

yesyesok提到:
check在function裡只會回傳mail跟false

一個function回傳兩種不同資料型態,容易造成混淆

建議以下兩種做法擇一
1.回傳 true/false 表示成功/失敗,email用wiselou大大的方法回傳
2.回傳 email/空字串 表示成功/失敗

其實一般function建議最好只傳回true或false

樓主的function傳回了兩種型態~

雖然if($check)會true,是因為代表物件存在~

你直接測試就知道了~

&lt;pre class="c" name="code">
if("test"){
	echo "有test";
}else{
	echo "沒test";
}

if(false){
	echo "有test";
}else{
	echo "沒test";
}
10
炎之虛空
iT邦高手 3 級 ‧ 2013-07-24 19:47:18

安咧

&lt;pre class="c" name="code">    &lt;?php  
    function verity($acc,$pw,$user,$userData)  
    {  
        foreach ($use as $key => $value) {
            if($acc = $value && $userdata[$value]['password'])
            {
                return $userdata[$value]['email'];
            }else{
                return false; 
            }
        }

    }  
    ?>  
ted99tw iT邦高手 1 級 ‧ 2013-07-24 19:53:41 檢舉

solzxer提到:
已經煮熟的腦袋

大火再按三分鐘,爛一點較好入口...

豆花 好吃的豆花又來了 請快點來買 燒燙燙的豆花驚毆飛

2
classday2004
iT邦新手 5 級 ‧ 2013-07-30 14:55:13

綜合以上各位大大提出的問題,花了一點時間修改,可以正常運作

這個題目,除了考迴圈、邏輯還考到二維陣列的使用,
另外提醒你大小寫也會影響結果喔~善用echo進行除錯可以幫助你找出問題所在,
附上改寫的code供你參考(修改function.php、view.php)

function.php

&lt;pre class="c" name="code">
&lt;?php   
  
//用以判斷比對情況的區域變數$confirm,預設值為false   
$confirm = false;   
  
//檢驗函式   
function verity($acc,$pw,$user,$userData)   
{   
    //迴圈比對傳過來的array   
    for($i = 0;$i &lt; sizeof($user);$i++)   
    {   
        //這裡要用到二維陣列,可以先echo看看有沒有順利取得二維陣列的值   
        echo $user[$i].",".$userData[$user[$i]]['password']."&lt;br>";   
        
        //這裡,您的大小寫寫錯囉~這些都會造成取不到值的原因 
        if($acc == $user[$i] && $pw == $userData[$user[$i]]['password'])   
        {   
            //有比對到,則   
            //1.傳回email,email也要從二維陣列取   
            return $userData[$user[$i]]['email'];   
            //2.變更$confirm的狀態為true   
            $confirm = true;   
        }   
    }      
    //$confirm為false,表示沒有比對成功,回傳空值   
    if($confirm == false){   
        return '';   
    }   
}   
?>  

view.php

&lt;pre class="c" name="code">
   
   
&lt;meta http-equiv="content-type" content="text/html"; charset = "UTF-8">   
   
   
&lt;?php   
include('user.php');   
include('function.php');  
 
//用$check接值,有值則顯示email內容,值為空則顯示讀取   
$check = verity($_POST['acc'],$_POST['pw'],$user,$userData);   
  
if($check != '')   
{   
    echo '電子信箱是'.$check;   
}   
else  
{   
    echo '讀取失敗!!';   
}   
?>   
   
  

我要發表回答

立即登入回答