Czy istnieje funkcja pobierania bieżącego obiektu użytkownika, która unika dostępu do zmiennej globalnej?

29

Zawsze z tym poszedłem global $user;. Wydaje mi się jednak, że pamiętam, że widziałem coś w wniesionym module, który zwrócił obiekt bieżącego użytkownika bez użycia globalnego $user.

Czy taka funkcja istnieje w rdzeniu Drupala 7, czy też użycie zmiennej globalnej jest de facto zalecanym sposobem uzyskania bieżącego obiektu użytkownika?

Alex Weber
źródło
dlaczego po prostu nie używałbyś globalnego użytkownika $?
saadlulu,
5
Użycie globalnego użytkownika $ może stworzyć potencjalne niepożądane zachowanie, jeśli zostanie ono niedbale zmienione później w kodzie.
Alex Weber,

Odpowiedzi:

22

Można użyć funkcji user_uid_optional_load () ; bez argumentów zwraca obiekt użytkownika dla aktualnie zalogowanego użytkownika. Nadal korzysta z globalnego $useri ładuje pełny obiekt z bazy danych, w tym pól powiązanych z użytkownikami, ale pozwala uniknąć przypadkowej zmiany zawartości zmiennej globalnej w kodzie $user, ponieważ nie jest przywoływany z kodu.

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

Jeśli nie potrzebujesz pełnego obiektu, możesz użyć kodu podanego już w innych odpowiedziach. Jeśli chcesz mieć pewność, że nie zmienisz obiektu globalnego, możesz skopiować zmienną globalną do zmiennej lokalnej, jak w poniższym fragmencie.

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

W Drupal 8 wystarczy użyć metody statycznej, \Drupal::currentUser()aby uzyskać odpowiednik Drupal 7 $GLOBALS['user']i \Drupal\user\Entity\User::load(\Drupal::currentUser()->id())uzyskać w pełni załadowany obiekt ze wszystkimi polami API pola. Nie ma już ryzyka zastąpienia zmiennej globalnej wszystkimi konsekwencjami.
W przypadku, gdy musisz zmienić bieżącego użytkownika, na przykład na anonimowego użytkownika, kod użyty w Drupal 8 jest następujący.

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

// Your code here.

// Eventually, restore the user account.
$accountSwitcher->switchBack();
kiamlaluno
źródło
20

$userObiekt jest zadeklarowana jako zmienną globalną, więc jeśli chcesz uzyskać do niego dostęp należy użyć albo:

global $user;
$account = $user;

lub

$account = $GLOBALS['user'];

Wydaje się, że w Drupal nie ma standardowego sposobu na zrobienie tego. Jeśli na przykład spojrzysz na moduł węzła, node_access_grants()funkcja używa tego kodu:

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

Podczas gdy następna funkcja w pliku node_access_view_all_nodes()używa tego:

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

Prosta odpowiedź brzmi: oba są poprawne. Myślę, że użycie $GLOBALSjest takie, że wymieniona zmienna $usernie jest aktywna w bieżącym zakresie i dlatego nie może zostać zastąpiona przez nieostrożne wywołanie, na przykład w $user = NULLdalszej części funkcji. Nie jestem jednak w 100% na tym.

Clive
źródło
to wiem i zgadzam się w twoim ostatnim oświadczeniu.
saadlulu,
1
global $user;powinien być generalnie używany, gdy zmienna jest odwoływana więcej niż jeden raz, i $GLOBALS['user']powinien być stosowany, gdy jest używany tylko raz w kodzie funkcji; Kod Drupala nie jest w tym stały. Jest taki przypadek, w którym global $user;jest to konieczne: kiedy obiekt użytkownika jest przekazywany w drupal_alter()celu umożliwienia modułom zewnętrznym zmiany aktualnie aktywnego użytkownika (co nie jest tak naprawdę zaimplementowane w Drupal).
kiamlaluno
1
global $userto nie to samo, co user_uid_optional_load (). Pierwszy jest ładowany z sesji i nie jest w pełni załadowanym obiektem użytkownika (z wywoływanymi polami i zaczepami), podczas gdy drugi jest. Więc nie wymieniałbym tego jako opcji. Celem tej funkcji jest użycie nazwanych argumentów menu, które mogą opcjonalnie zaakceptować identyfikator użytkownika, a w innym przypadku domyślny dla bieżącego użytkownika. / user / uid jest podstawowym przykładem.
Berdir
@Berdir Dzięki Nie wiedziałem, że global $userdomyślnie nie jest w pełni załadowany (chociaż ma to sens i wyjaśnia kilka rzeczy, o których wcześniej myślałem). Wyjąłem to z odpowiedzi.
Clive
Dzięki Clive, przypuszczam, że użycie globalnego użytkownika $ i skopiowanie go do zmiennej $ konto jest prawdopodobnie najbezpieczniejszą alternatywą. Rzeczywiście szukałem user_uid_optional_load () chociaż :)
Alex Weber
3

Jest to tak proste, jak zadeklarowanie (istniejącego) globalnego obiektu użytkownika $ w zakresie funkcji:

global $user;

Pamiętaj, że zmiany dokonane w tym obiekcie wpływają na niego globalnie, tj

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

właśnie nadałem bieżącemu użytkownikowi uprawnienia do 1. Dlatego zazwyczaj $ user jest przypisany do konta $, aby można było majstrować przy danych bez faktycznego wpływu na aktualnie zalogowanego użytkownika (chyba że oczywiście chciałeś).

Charlie Schliesser
źródło