2011-05-09 119 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