您好 我在PHP页面遇到了一些问题:我正在使用this教程编写一个小CMS。 我设法编写一个用于与菜单交互的类,一切运行良好:我可以在一个页面中插入,删除和获取菜单的所有项目,我可以对它们进行重新排序。 当我开始为用户编写同一页面时,我遇到了一个问题:我正在使用Sentry类来验证每个页面中的用户:
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 :(得分:5)
我和你有完全相同的问题,在我的情况下,这是因为PHP的寄存器全局变量已经打开。
注册globals是一个php配置设置,它为$ _SESSION中设置的每个变量创建一个局部变量。这意味着当你设置$ _SESSION ['user']时,也会为你创建一个局部变量$ user。如果您在代码中覆盖此变量,正如您所报告的那样,新值也将在$ _SESSION中设置。有关寄存器全局变量的更多信息,请查看here。
要关闭此设置,您必须编辑为正在使用的Web服务器加载的php.ini文件,并将register_globals设置为Off,然后重新启动Web服务器。请记住,如果您计划在任何其他Web服务器上运行此代码,则必须关闭此设置才能使代码正常运行。
答案 1 :(得分:0)
如果您正在创建框架,我建议您使用自动加载。 在索引控制器上,您可以指定在找不到类时要调用的函数。 实施例。
您使用: require_once( '../包括/ DbUser.php'); $ user_connector = new DbUser();
如果您这样写,首先您必须始终控制文件是否包含一次。这花费了一些时间在PHP过程中。 方法是永远不要写“require”或“include”,让php“找不到”他正在寻找的课程。然后你必须控制Dbuser类在Dbuser.php文件中,具有相同的名称。最后插入一个只能被触发一次的自动加载(如root上的index.php)。 你必须这样做:
function classAutoload($className){ if (!class_exists($className, false)){ @include_once(dirname(__FILE__).'/includes/'.$className.'.php'); } spl_autoload_register('classAutoload');
PHP将管理是否包含类,如果不包含,它将在获取实例之前加载。没有更多包含和要求,只需要上课。 您可以根据需要添加任意数量的自动加载,始终确保只执行一次此代码。
你也应该使用“&amp;&amp;”而不是PHP的“AND”。 AND只是一个别名,作为双引号,php必须找到internaly这个字符到底是什么。效率在框架上很重要,记住你会在每次网络电话上使用它......
我希望你能帮助你的框架。