Gibt es eine Funktion zum Abrufen des aktuellen Benutzerobjekts, die den Zugriff auf die globale Variable vermeidet?

29

Ich bin immer damit gegangen global $user;. Ich erinnere mich jedoch an etwas in einem Modul, das das aktuelle Benutzerobjekt zurückgegeben hat, ohne das globale zu verwenden $user.

Existiert eine solche Funktion in Drupal 7 Core oder ist die Verwendung der globalen Variablen de facto die empfohlene Methode, um das aktuelle Benutzerobjekt abzurufen?

Alex Weber
quelle
warum würdest du nicht einfach global $ user benutzen?
Saadlulu
5
Die Verwendung von global $ user kann zu potenziell unerwünschtem Verhalten führen, wenn es später im Code nachlässig geändert wird.
Alex Weber

Antworten:

22

Die Funktion, die Sie verwenden könnten, ist user_uid_optional_load () ; Ohne Argumente wird das Benutzerobjekt für den derzeit angemeldeten Benutzer zurückgegeben. Es verwendet weiterhin das globale $userObjekt und lädt das gesamte Objekt aus der Datenbank, einschließlich der den Benutzern zugeordneten Felder. Es verhindert jedoch, dass Ihr Code versehentlich den Inhalt der globalen Variablen ändert $user, da in Ihrem Code nicht darauf verwiesen wird.

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

Wenn Sie nicht das gesamte Objekt benötigen, können Sie den Code verwenden, der bereits in den anderen Antworten angegeben ist. Wenn Sie sicherstellen möchten, dass Sie das globale Objekt nicht ändern, können Sie die globale Variable in eine lokale Variable kopieren, wie im folgenden Snippet dargestellt.

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

In Drupal 8 verwenden Sie einfach die statische Methode \Drupal::currentUser(), um das Äquivalent von Drupal 7 abzurufen $GLOBALS['user']und \Drupal\user\Entity\User::load(\Drupal::currentUser()->id())ein vollständig geladenes Objekt mit allen Feld-API-Feldern abzurufen. Es besteht nicht mehr das Risiko, eine globale Variable mit allen Konsequenzen zu überschreiben.
Für den Fall, dass Sie den aktuellen Benutzer mit dem anonymen Benutzer tauschen müssen, ist der in Drupal 8 verwendete Code der folgende.

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

// Your code here.

// Eventually, restore the user account.
$accountSwitcher->switchBack();
kiamlaluno
quelle
20

Das $userObjekt ist als globale Variable deklariert. Wenn Sie darauf zugreifen möchten, müssen Sie Folgendes verwenden:

global $user;
$account = $user;

oder

$account = $GLOBALS['user'];

Tatsächlich scheint es in Drupal keine Standardmethode zu geben. Wenn Sie sich zum Beispiel das Knotenmodul ansehen, verwendet die node_access_grants()Funktion diesen Code:

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

Während die nächste Funktion in der Datei node_access_view_all_nodes(), verwendet dies:

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

Die einfache Antwort ist, dass beide gültig sind. Ich denke, die Verwendung von $GLOBALSist so, dass die Variable named $userim aktuellen Gültigkeitsbereich nicht aktiv ist und daher nicht durch einen unachtsamen Aufruf überschrieben werden kann, um beispielsweise $user = NULLin der Funktion weiterzumachen. Ich bin allerdings nicht zu 100% damit einverstanden.

Clive
quelle
Das weiß ich und stimme in deiner letzten Aussage zu.
Saadlulu
1
global $user;sollte im Allgemeinen verwendet werden, wenn auf die Variable mehr als einmal verwiesen wird, und $GLOBALS['user']sollte verwendet werden, wenn sie im Funktionscode nur einmal verwendet wird; Drupal-Code ist dabei nicht konstant. Es gibt einen Fall, in dem dies global $user;erforderlich ist: Wenn das Benutzerobjekt an übergeben wird, drupal_alter()damit Module von Drittanbietern den derzeit aktiven Benutzer ändern können (was in Drupal eigentlich nicht implementiert ist).
kiamlaluno
1
global $userist nicht dasselbe wie user_uid_optional_load (). Das erste Objekt wird aus der Sitzung geladen und ist kein vollständig geladenes Benutzerobjekt (mit Feldern und Hooks, auf die zugegriffen wird), während das zweite Objekt geladen ist. Daher würde ich dies nicht als Option auflisten. Der Zweck dieser Funktion ist, für benannte Menüargumente verwendet zu werden, die optional eine Benutzer-ID akzeptieren können und ansonsten standardmäßig den aktuellen Benutzer verwenden. / user / uid ist das primäre Beispiel.
Berdir
@Berdir Danke Ich wusste nicht, dass das global $usernicht standardmäßig voll geladen ist (obwohl es sinnvoll ist und ein paar Dinge erklärt, über die ich mich vorher gewundert hatte). Ich habe es aus der Antwort genommen.
Clive
Danke Clive, ich nehme an, dass die Verwendung von globalem $ user und das Kopieren in eine $ account-Variable wahrscheinlich die sicherste Alternative ist. Ich habe tatsächlich nach user_uid_optional_load () gesucht :)
Alex Weber
3

Es ist so einfach wie das Deklarieren des (vorhandenen) globalen $ user-Objekts im Rahmen Ihrer Funktion:

global $user;

Beachten Sie, dass Änderungen an diesem Objekt globale Auswirkungen haben, z

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

hat gerade dem aktuellen Benutzer die UID 1-Berechtigung erteilt. Dies ist der Grund, warum normalerweise $ user $ account zugewiesen wird, damit Daten bearbeitet werden können, ohne dass dies Auswirkungen auf den aktuell angemeldeten Benutzer hat (es sei denn, Sie wollten es natürlich).

Charlie Schliesser
quelle