Переменная записи локальной переменной в PHP - PullRequest
3 голосов
/ 09 мая 2011

Привет У меня возникли проблемы со страницей PHP: я пишу небольшую 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'] последним объектом, использованным в цикле (объект "user" ). Кто-нибудь может объяснить мне, как локальная переменная может перезаписать сеанс? Я хотел бы прояснить: я решаю проблему (меняя $id => $user на $id => $userObj), но я ищу объяснение. Спасибо!

Ответы [ 2 ]

5 голосов
/ 03 июня 2011

У меня была точно такая же проблема, как и у вас, и в моем случае это произошло потому, что глобальные регистры PHP были включены.

Глобальные регистры - это параметр конфигурации php, который создает локальную переменную для каждой установленной переменной.в $ _SESSION.Это означает, что когда вы устанавливаете $ _SESSION ['user'], для вас также будет создана локальная переменная $ user.Если вы переписали эту переменную в своем коде, как вы сообщали, новое значение также будет установлено в $ _SESSION.Для получения дополнительной информации о глобалах регистров, посмотрите здесь .

Чтобы отключить эту настройку, вы должны отредактировать файл php.ini, который загружен для используемого вами веб-сервера, и установитьустановите для register_globals значение Off, а затем перезапустите свой веб-сервер.Помните, что если вы планируете запускать этот код на любом другом веб-сервере, этот параметр также должен быть отключен для правильной работы кода.

0 голосов
/ 09 мая 2011

Если вы создаете фреймворк, я рекомендую вам использовать автозагрузку.В контроллере индекса вы можете указать функцию для вызова, когда класс не найден.Пример.

Вы используете: require_once ('../ includes / DbUser.php');$ user_connector = new DbUser ();

Если вы пишете это, прежде всего вы всегда должны контролировать, если файл включен один раз.Это тратит некоторое время на процесс php.Это НИКОГДА не пишите "require" или "include" и позволяйте php "не найти" класс, который он ищет.Затем вы должны контролировать, что класс Dbuser находится внутри файла Dbuser.php с тем же именем.Наконец, вставьте автозагрузку, где можно запустить только один раз (например, index.php для root).Вы должны сделать это следующим образом:

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

PHP справится, если класс включен, и если нет, он загрузится до получения экземпляра.Больше не включает и требует, просто получить классы.Вы можете добавить столько автозагрузок, сколько вам нужно, всегда следя за тем, чтобы этот экземпляр кода создавался только один раз.

Вы также должны использовать «&&» вместо «AND» в php.AND - это просто псевдоним, и, как двойная кавычка, php должен найти, что это за символ.Эффективность очень важна для фреймворка, помните, что вы будете использовать его при каждом веб-вызове ...

Я надеюсь, что вы поможете с вашей фреймворком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...