Чи є функція отримати об'єкт поточного користувача, який уникає доступу до глобальної змінної?


29

Я завжди з цим ходив global $user;. Однак я, мабуть, пам’ятаю, що бачив щось у наданому модулі, який повертав поточний об’єкт користувача без використання глобального $user.

Чи існує така функція в ядрі Drupal 7 або використовує глобальну змінну де-факто рекомендований спосіб отримати поточний об'єкт користувача?


чому б ти просто не користувався глобальним користувачем $?
saadlulu

5
Використання глобального користувача $ може створити потенційну небажану поведінку, якщо це буде необережно змінено згодом у коді.
Алекс Вебер

Відповіді:


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 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']слід використовувати, коли вона використовується лише один раз у коді функції; Друпал-код в цьому не є постійним. Існує випадок, коли global $user;це необхідно: коли об'єкт користувача передається drupal_alter()для того, щоб сторонні модулі могли змінювати поточного активного користувача (що не реально реалізовано в Drupal).
kiamlaluno

1
global $userце не те саме, що user_uid_optional_load (). Перший завантажується з сеансу і не є повністю завантаженим користувальницьким об'єктом (із полями та гачками, на які посилаються), а другий. Тому я б не перераховував це як варіант. Мета цієї функції - використовувати для названих аргументів меню, які необов'язково можуть приймати ідентифікатор користувача та в іншому випадку за замовчуванням для поточного користувача. / user / uid є основним прикладом.
Бердір

@Berdir Спасибі Я не знав, що global $userне був повністю завантажений за замовчуванням (хоча це має сенс і пояснює пару речей, про які я замислювався раніше). Я взяв це з відповіді.
Клайв

Дякую Клайву, я вважаю, що використання глобального користувача $ та копіювання його в змінну $ account account - це, мабуть, найбезпечніша альтернатива. Я насправді шукав user_uid_optional_load (), хоча :)
Alex Weber

3

Це так само просто, як оголосити (існуючий) глобальний об’єкт $ user у межах вашої функції:

global $user;

Майте на увазі, що зміни, внесені до цього об’єкта, впливають на нього глобально, тобто

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

щойно надав поточному користувачеві пільги uid 1. Ось чому, як правило, користувач $ присвоюється обліковому запису $, завдяки чому дані можна обробляти, не впливаючи на користувача, який у даний момент увійшов (якщо, звичайно, ви цього не хотіли).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.