Является ли использование суперглобальных файлов в PHP хорошим или плохим? - PullRequest
8 голосов
/ 17 августа 2010

Итак, я не из огромного PHP-фона, и мне было интересно, если в правильно сформированном коде нужно использовать «суперглобальные переменные» напрямую, например, в середине какой-нибудь функции произнесите $_SESSION['x'] = 'y'; или если, как я обычно делал бы с переменными, лучше отправлять их в качестве аргументов, которые можно использовать оттуда, например:

class Doer {
    private $sess;
    public function __construct(&$sess) {
        $this->sess =& $sess;
    }
} 

$doer = new Doer($_SESSION);

, а затем используйте версию Doer->sess из Doer и тому подобное. (Преимущество этого метода состоит в том, что он дает понять, что Doer использует $ _SESSION.)

Каков подход PHP дизайн для этой проблемы?

Ответы [ 5 ]

13 голосов
/ 17 августа 2010

Мне нравится переносить $_SESSION, $_POST, $_GET и $_COOKIE в структуры ООП.

Я использую этот метод для централизации кода, который обрабатывает санацию и проверку, всенеобходимые isset () проверки, одноразовые значения, setcookie параметры и т. д. Это также позволяет клиентскому коду быть более читабельным (и дает мне иллюзию, что он более удобен в обслуживании).

Может быть трудно обеспечить использованиетакого рода структура, особенно если есть несколько кодеров.С $_GET, $_POST и $_COOKIE (я полагаю), ваш код инициализации может скопировать данные, а затем уничтожить суперглобальный.Возможно, умный деструктор мог бы сделать это возможным с помощью $ _SESSION (стереть $ _SESSION при загрузке, записать его обратно в деструктор), хотя я не пробовал.

Однако я обычно не использую эти методы принуждения.Привыкнув к этому, видеть $_SESSION в коде вне класса сеанса выглядит странно, и я в основном работаю в одиночку.

EDIT
Вот пример клиентского кода, на случайэто помогает кому-тоЯ уверен, что рассмотрение любой из основных платформ даст вам лучшие идеи ...

$post = Post::load ();  
$post->numeric ('member_age');  
$post->email ('member_email');
$post->match ('/regex/','member_field');
$post->required ('member_first_name','member_email');
$post->inSet ('member_status',array('unemployed','retired','part-time','full-time'));
$post->money ('member_salary');
$post->register ('member_last_name'); // no specific requirements, but we want access
if ($post->isValid())
{
  // do good stuff
  $firstName = $post->member_first_name;
}
else
{
  // do error stuff
}

Post и его друзья все происходят из базового класса, который реализует основной код проверки, добавляя свои собственные специфические функциикак токены формы, конфигурация файла cookie сеанса, что угодно.

Внутренне, класс содержит коллекцию допустимых данных, извлеченных из $_POST при вызове методов проверки, а затем возвращает их как свойства, используя магию __getметод.К ошибочным полям нельзя получить доступ таким образом.Мои методы проверки (кроме required) не заканчиваются на пустых полях, и многие из них используют func_get_args, чтобы позволить им работать с несколькими полями одновременно.Некоторые методы (например, money) автоматически переводят данные в пользовательские типы значений.

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

Одним из способов улучшить это было бы сохранение информации проверки в классе Form, который используется для визуализации формы и поддержки клиентской стороны.проверка, а также очистка данных после отправки.

2 голосов
/ 16 апреля 2012

Я знаю, что этот вопрос старый, но я бы хотел добавить ответ.

классы Марио для обработки входов - это круто.

Я предпочитаю каким-то образом обернуть суперглобалы. Это может сделать ваш код НАМНОГО проще для чтения и повысить удобство сопровождения.

Например, на моей нынешней работе есть какой-то код, который я ненавижу! Переменные сеанса используются настолько интенсивно, что вы не сможете реально изменить реализацию, не оказав существенного влияния на весь сайт.

Например,

Допустим, вы создали класс Session, специфичный для вашего приложения.

class Session
{
    //some nice code
}

Вы могли бы написать что-то вроде следующего

$session = new Session();
if( $session->isLoggedIn() )
{
   //do some stuff
}

В отличие от этого

if( $_SESSION['logged'] == true )
{
   //do some stuff
}

Это кажется немного тривиальным, но для меня это большое дело. Скажем, что когда-нибудь в будущем я решу изменить имя индекса с «logged» на «loggedIn».

Теперь мне нужно перейти в любое место в приложении, где переменная сеанса используется, чтобы изменить это. Или я могу оставить его и найти способ сохранить обе переменные.

Или что, если я хочу проверить, что этот пользователь является администратором и вошел в систему? Я мог бы в конечном итоге проверить две разные переменные в сеансе для этого. Но вместо этого я мог бы заключить его в один метод и сократить свой код.

Это помогает другим программистам смотреть на ваш код, потому что его становится легче читать, и им не нужно так много «думать» об этом, когда они смотрят на код. Они могут перейти к методу и увидеть, что есть только ОДИН способ зарегистрировать пользователя. Это также помогает вам, потому что, если вы хотите сделать «зарегистрированный» чек более сложным, вам нужно всего лишь перейти в одно место, чтобы изменить его, вместо того, чтобы пытаться выполнить глобальные поиски в вашей IDE и пытаться изменить его таким образом.

Опять же, это тривиальный пример, но в зависимости от того, как вы используете сеанс, этот способ использования методов и классов для защиты доступа может значительно облегчить вашу жизнь.

2 голосов
/ 17 августа 2010

Изменение содержимого суперглобалистов считается плохой практикой. Хотя в этом нет ничего особенного, особенно если код находится на 100% под вашим контролем, это может привести к неожиданным побочным эффектам, особенно когда вы рассматриваете смешанный исходный код. Например, если вы делаете что-то вроде этого:

$_POST['someval'] = mysql_real_escape_string($_POST['someval']);

Вы могли бы ожидать, что везде, где PHP делает доступным «someval», это тоже изменится, но это не так. Копия в $_REQUEST['someval'] останется неизменной и останется оригинальной «небезопасной» версией. Это может привести к непреднамеренной уязвимости внедрения, если вы выполняете все экранирование на $ _POST, но более поздняя библиотека использует $ _REQUEST и предполагает, что она уже экранирована.

Таким образом, даже если вы можете изменить их, лучше всего рассматривать суперглобальные переменные только для чтения. Если вам нужно связываться со значениями, сохраняйте свои собственные параллельные копии и применяйте любые методы упаковки / доступа, необходимые для поддержки этой копии.

0 голосов
/ 17 августа 2010

Я бы не советовал вообще передавать superglobal по ссылке. В вашем классе непонятно, что вы изменяете, это переменная сеанса. Также имейте в виду, что $ _SESSION доступен везде за пределами вашего класса. С объектно-ориентированной точки зрения так неправильно иметь возможность изменять переменную внутри класса вне этого класса, изменяя переменную, которая не связана с классом. Наличие публичного атрибута считается плохой практикой, а это даже хуже.

0 голосов
/ 17 августа 2010

Это не очень хорошее использование PHP.

получить переменные $ _SESSION напрямую:

$id   = $_SESSION['id'];
$hash = $_SESSION['hash'];

и т.д.

...