2011-05-09 112 views
3

嗨 我遇到了一個PHP頁面的問題:我在寫一個使用this教程的CMS。 我設法編寫一個我用來與菜單進行交互的類,並且所有工作都很好:我可以在頁面中插入,刪除和獲取菜單的所有項目,我可以對它們進行重新排序。 當我開始寫,爲用戶在同一頁,我遇到了一個問題:我使用的是一個哨兵類驗證用戶在每個頁面:本地變量覆蓋PHP中的會話變量

require_once('../includes/Sentry.php'); 
$theSentry = new Sentry(); 
if (!$theSentry->checkLogin(1)){ header("Location: index.php"); die(); } 

現在:如果我單獨使用此驗證,頁面運作良好,但我需要查詢數據庫,並提取所有用戶在user_admin.php頁:

require_once('../includes/DbUser.php'); 
$user_connector = new DbUser(); 
$all_users = array(); 
$all_users = $user_connector->getUserArray(); 
foreach($all_users as $id => $user){ echo " ... " }; 

如果我評論這兩個部分中的一個,一切工作正常,但如果我離開這個代碼運行在一起,頁面被正確創建,但下一次使用Sentry類運行頁面時,我被重定向到登錄頁面,並顯示錯誤消息。 Sentry類使用Validator類來檢查憑據,並且此類中的方法報告數組輸入而不是單個值輸入。

我的問題是:如何從兩個不同的類創建兩個不同的對象可能會產生這樣的問題?我認爲你需要這兩個方法的代碼:

class Sentry { 

... 

function checkLogin($group=9,$user='',$pass='',$goodRedirect='',$badRedirect='') { 
     // Include database and validation classes, and create objects 
     require_once('DbConnector.php'); 
     require_once('Validator.php'); 
     $validate = new Validator(); 
     $loginConnector = new DbConnector(); 

     // If user is already logged in then check credentials 
     if ($_SESSION['user'] && $_SESSION['pass']){ 

      // Validate session data 
      if (!$validate->validateTextOnly($_SESSION['user'])){return false;} 
      if (!$validate->validateTextOnly($_SESSION['pass'])){return false;} 

      if ($_SESSION['gruppo'] <= $group){ 
       // Existing user ok, continue 
       if ($goodRedirect != '') { 
        header("Location: ".$goodRedirect) ; 
       }   
       return true; 
      }else{ 
       // Existing user not ok, logout 
       //$this->logout(); 
       header("Location: low_perm.php"); 
       die; 
       //return false; 
      } 

     // User isn't logged in, check credentials 
     }else{ 
      // Validate input 
      if (!$validate->validateTextOnly($user)){return false;} 
      if (!$validate->validateTextOnly($pass)){return false;} 

      // Look up user in DB 
      $getUser = $loginConnector->query("SELECT * FROM `utenti` WHERE `usr` = '".$user."' AND `psw` = PASSWORD('".$pass."') AND `gruppo` <= ".$group." AND `attivo` = 1"); 
      $this->userdata = $loginConnector->fetchArray($getUser); 

      if ($loginConnector->getNumRows($getUser) > 0){ 
       // Login OK, store session details 
       // Log in 
       $_SESSION["user"] = $user; 
       $_SESSION["pass"] = $this->userdata['pass']; 
       $_SESSION["gruppo"] = $this->userdata['gruppo']; 

       if ($goodRedirect) { 
        header("Location: ".$goodRedirect); 
       } 
       return true; 

      }else{ 
       // Login BAD 
       unset($this->userdata); 
       if ($badRedirect) { 
        header("Location: ".$badRedirect) ; 
       }  
       return false; 
      } 
     }   
    } 
} 

這是獲得用戶的功能:

class DbUser extends DbConnector{ 

... 

    function getUserArray() { 
     while ($row = mysql_fetch_object($this->user_result)) { 
      $this->users[$row->id] = $row; 
     } 
     return $this->users;  
    } 
} 

我知道這是一個難以解釋的問題,所以讓我知道如果我需要指定別的東西...... 感謝

編輯:該錯誤是在Validator類,在這種功能(帶的preg_match()行):

function validateTextOnly($theinput,$description = ''){ 
    $result = preg_match ("/^[A-Za-z0-9\ ]+$/", $theinput); 
    if ($result AND $theinput!=''){ 
     return true; 
    }else{ 
     $this->errors[] = $description; 
     return false; 
    } 
} 

個好消息:我發現那裏的錯誤是,但我無法理解爲什麼這個代碼不工作:

$user_connector = new DbUser(); 
$all_users = array(); 
$all_users = $user_connector->getUsers(); 
foreach($all_users as $id => $user){ ... } 

foreach語句是一點:當我使用$all_user作爲$id=>$user,它實際上用週期中使用的最後一個對象(「用戶」對象)覆蓋$ _SESSION ['user']的內容。任何人都可以解釋一下本地變量如何覆蓋會話之一? 我想說清楚:我解決了這個問題(改變$id => $user$id => $userObj),但我正在尋找一個解釋。 謝謝!

+0

我們能否收到錯誤信息? – krifur 2011-05-09 09:00:57

+0

當然,但我認爲是沒有用的......是關於Validator類的錯誤: 警告:preg_match()期望參數2是字符串,在/web/htdocs/www.subamiata.it/中給出的對象home/nuovo/includes/Validator.php 21行 – Paciotti 2011-05-09 09:09:49

+0

好了,現在顯示Validator.php,我們會看看21行。 – 2011-05-09 09:34:02

回答

5

我和你有完全相同的問題,在我的情況下,這是因爲PHP的註冊全局變量已打開。

註冊全局變量是一個php配置設置,它爲在$ _SESSION中設置的每個變量創建一個局部變量。這意味着當你設置$ _SESSION ['user']時,還會爲你創建一個局部變量$ user。如果您在代碼中覆蓋了此變量,如您所報告的那樣,新值也將在$ _SESSION中設置。有關注冊全局變量的更多信息,請看here

要關閉此設置,您必須編輯爲您正在使用的Web服務器加載的php.ini文件,並將register_globals設置爲Off,然後重新啓動Web服務器。請記住,如果您打算在任何其他網絡服務器上運行此代碼,則此設置也必須關閉以使代碼正常運行。

+0

哦,男人!我沒有想到註冊全局變量!我知道它是什麼,但我知道對於較新版本的PHP,它默認關閉......我正在運行最後一個版本,但是從舊的服務器升級了幾次。非常感謝你! – Paciotti 2011-06-04 08:10:11

0

如果你正在創建一個框架,我建議你使用自動加載。 在索引控制器上,您可以指定一個函數以在找不到類時調用。 示例。

您使用: require_once('../ includes/DbUser.php'); $ user_connector = new DbUser();

如果你寫這個,首先你必須控制文件是否包含一次。這花了一些時間在PHP過程中。 方法是從不寫「require」或「include」,並讓php「找不到」他正在尋找的課程。然後,您必須控制該類Dbuser在Dbuser.php文件中,具有相同的名稱。最後插入一個只能被觸發一次的自動加載(比如根目錄下的index.php)。 你必須那樣做:

 
function classAutoload($className){ 
    if (!class_exists($className, false)){ 
     @include_once(dirname(__FILE__).'/includes/'.$className.'.php'); 
} 
spl_autoload_register('classAutoload'); 

如果包含類PHP會管理,如果沒有,它會加載之前得到一個實例。沒有更多的包括和要求,只是上課。 您可以根據需要添加儘可能多的自動加載,並始終確保只實例一次這段代碼。

你也應該使用「& &」而不是php的「AND」。 AND只是一個別名,作爲雙引號,php必須在內部找到這個字符。效率在框架中很重要,請記住,您將在每次網絡調用中使用它...

我希望你能幫助你的框架。

+0

好吧,我不知道我明白:我可以使用這個類,但我必須寫在每個文件上。對?相反,我可以在單獨的文件上編寫幷包含它,但這種方式有點悖論!無論如何,這怎麼能解決我的問題? – Paciotti 2011-05-09 11:36:33

+0

好吧,我明白了!沒有什麼是矛盾的!對不起... – Paciotti 2011-05-09 11:38:03

+0

...但我仍然需要解決我的問題... – Paciotti 2011-05-09 18:41:54