Есть ли функция для получения текущего объекта пользователя, который избегает доступа к глобальной переменной?

29

Я всегда шел с этим global $user;. Тем не менее, я помню, что видел что-то в добавленном модуле, который возвращал текущий пользовательский объект без использования global $user.

Существует ли такая функция в ядре Drupal 7, или де-факто рекомендует использовать глобальную переменную для получения текущего объекта пользователя?

Алекс Вебер
источник
почему бы вам просто не использовать глобальный $ user?
saadlulu
5
Использование global $ user может создать потенциальное нежелательное поведение, если оно впоследствии будет небрежно изменено в коде.
Алекс Вебер

Ответы:

22

Функцией, которую вы можете использовать, является user_uid_optional_load () ; без аргументов возвращает объект пользователя для текущего пользователя, вошедшего в систему. Он по-прежнему использует глобальный $userобъект и загружает полный объект из базы данных, включая поля, связанные с пользователями, но он предотвращает случайное изменение вашего кода содержимым глобальной переменной $user, поскольку на него нет ссылок из вашего кода.

function user_uid_optional_load($uid = NULL) {
  if (!isset($uid)) {
    $uid = $GLOBALS['user']->uid;
  }
  return user_load($uid);
}

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

$account = $GLOBALS['user'];
// Use $account.

В Drupal 8 вы просто используете статический метод, \Drupal::currentUser()чтобы получить эквивалент Drupal 7 $GLOBALS['user']и \Drupal\user\Entity\User::load(\Drupal::currentUser()->id())получить полностью загруженный объект со всеми его полями API полей. Больше нет риска переопределения глобальной переменной со всеми вытекающими последствиями.
В случае, если вам нужно переключить текущего пользователя, например, с анонимным пользователем, код, который вы используете в Drupal 8, следующий.

$accountSwitcher = Drupal::service('account_switcher');
$accountSwitcher->switchTo(new Drupal\Core\Session\AnonymousUserSession());

// Your code here.

// Eventually, restore the user account.
$accountSwitcher->switchBack();
киамалуно
источник
20

$userОбъект объявлен как глобальная переменная, так что если вы хотите получить к нему доступ вам нужно использовать либо:

global $user;
$account = $user;

или

$account = $GLOBALS['user'];

На самом деле, в Drupal не существует стандартного способа сделать это. Если вы посмотрите на модуль узла, например, node_access_grants()функция использует этот код:

if (!isset($account)) {
  $account = $GLOBALS['user'];
}

Тогда как следующая функция в файле node_access_view_all_nodes()использует это:

global $user;
if (!$account) {
  $account = $user;
}

Простой ответ заключается в том, что оба действительны. Я думаю, что использование $GLOBALSтак, что именованная переменная $userне активна в текущей области и поэтому не может быть перезаписана небрежным вызовом, например, $user = NULLдалее в функции. Я не на все 100%, хотя.

Клайв
источник
это то, что я знаю и согласен в вашем последнем утверждении.
saadlulu
1
global $user;обычно используется, когда переменная упоминается более одного раза, и $GLOBALS['user']должна использоваться, когда она используется только один раз в коде функции; Код Drupal не является постоянным в этом. Существует случай, когда global $user;это необходимо: когда пользовательский объект передается drupal_alter()для разрешения сторонним модулям изменять текущего активного пользователя (что на самом деле не реализовано в Drupal).
kiamlaluno
1
global $userэто не то же самое, что user_uid_optional_load (). Первый загружается из сеанса и не является полностью загруженным пользовательским объектом (с вызываемыми полями и хуками), а второй -. Так что я бы не стал перечислять это как вариант. Назначение этой функции - использовать ее для именованных аргументов меню, которые могут по желанию принимать идентификатор пользователя и в противном случае использовать его по умолчанию для текущего пользователя. / user / uid является основным примером.
Бердир
@Berdir Спасибо, я не знал, что global $userон не был полностью загружен по умолчанию (хотя это имеет смысл и объясняет пару вещей, о которых я задумывался раньше). Я взял это из ответа.
Клайв
Благодаря Клайву, я полагаю, использование global $ user и копирование его в переменную $ account, вероятно, является самой безопасной альтернативой. Я действительно искал user_uid_optional_load (), хотя :)
Алекс Вебер
3

Это так же просто, как объявить (существующий) глобальный объект $ user в пределах вашей функции:

global $user;

Имейте в виду, что изменения, внесенные в этот объект, влияют на него глобально, т.е.

global $user;
$user->uid = 1;

только что дал текущему пользователю uid 1 привилегии. Вот почему, как правило, $ user назначается на $ account, чтобы данные можно было обрабатывать, фактически не затрагивая вошедшего в систему пользователя (если, конечно, вы этого не хотели).

Чарли Шлиссер
источник