Is using superglobals directly good or bad in PHP?

So, I don't come from a huge PHP background—and I was wondering if in well formed code, one should use the 'superglobals' directly, e.g. in the middle of some function say $_SESSION['x'] = 'y'; or if, like I'd normally do with variables, it's better to send them as arguments that can be used from there, e.g:

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

$doer = new Doer($_SESSION);

and then use the Doer->sess version from within Doer and such. (The advantage of this method is that it makes clear that Doer uses $_SESSION.)

What's the accepted PHP design approach for this problem?

8
задан Aaron Yodaiken 16 August 2010 в 23:24
поделиться

4 ответа

Мне нравится заключать $ _ SESSION , $ _ POST , $ _ GET и $ _ COOKIE в структуры ООП.

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

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

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

РЕДАКТИРОВАТЬ
Вот пример клиентского кода на случай, если он кому-то поможет. Я уверен, что просмотр любой из основных фреймворков даст вам лучшие идеи ...

$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, который используется для рендеринга формы и обеспечения валидации на стороне клиента, а также очистки данных после отправки.

13
ответ дан 5 December 2019 в 11:21
поделиться

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

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

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

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

2
ответ дан 5 December 2019 в 11:21
поделиться

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

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

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

и т. Д.

-3
ответ дан 5 December 2019 в 11:21
поделиться

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

0
ответ дан 5 December 2019 в 11:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: