Apakah ada fungsi untuk mendapatkan objek pengguna saat ini yang menghindari mengakses variabel global?

29

Saya selalu pergi dengan ini global $user;. Namun, saya ingat untuk melihat sesuatu dalam modul kontribusi yang mengembalikan objek pengguna saat ini tanpa menggunakan global $user.

Apakah fungsi seperti itu ada di inti Drupal 7, atau menggunakan variabel global cara yang direkomendasikan secara de-facto untuk mendapatkan objek pengguna saat ini?

Alex Weber
sumber
mengapa Anda tidak menggunakan pengguna global $ saja?
saadlulu
5
Menggunakan global $ user dapat menciptakan potensi perilaku yang tidak diinginkan jika nanti diubah dengan ceroboh dalam kode.
Alex Weber

Jawaban:

22

Fungsi yang dapat Anda gunakan adalah user_uid_optional_load () ; tanpa argumen, ia mengembalikan objek pengguna untuk pengguna yang saat ini masuk. Itu masih menggunakan global $user, dan memuat objek penuh dari database, termasuk bidang yang terkait dengan pengguna, tetapi itu menghindari kode Anda secara tidak sengaja mengubah konten variabel global $user, karena tidak dirujuk dari kode Anda.

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

Jika Anda tidak memerlukan objek lengkap, maka Anda dapat menggunakan kode yang sudah dilaporkan dalam jawaban lain. Jika Anda ingin memastikan Anda tidak mengubah objek global, Anda dapat menyalin variabel global menjadi variabel lokal, seperti dalam cuplikan berikut.

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

Di Drupal 8, Anda cukup menggunakan metode statis \Drupal::currentUser()untuk mendapatkan yang setara dengan Drupal 7 $GLOBALS['user']dan \Drupal\user\Entity\User::load(\Drupal::currentUser()->id())untuk mendapatkan objek yang dimuat penuh dengan semua bidang API bidangnya. Tidak ada lagi risiko mengesampingkan variabel global dengan semua konsekuensinya.
Jika Anda perlu mengganti pengguna saat ini dengan, misalnya, pengguna anonim, kode yang Anda gunakan di Drupal 8 adalah yang berikut.

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

// Your code here.

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

The $userobjek dinyatakan sebagai variabel global, jadi jika Anda ingin mengaksesnya Anda perlu untuk menggunakan:

global $user;
$account = $user;

atau

$account = $GLOBALS['user'];

Sebenarnya tidak ada cara standar untuk melakukan ini di Drupal. Misalnya, jika Anda melihat modul simpul, node_access_grants()fungsinya menggunakan kode ini:

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

Sedangkan fungsi selanjutnya dalam file node_access_view_all_nodes(),, menggunakan ini:

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

Jawaban sederhananya adalah keduanya valid. Saya pikir penggunaannya $GLOBALSadalah agar variabel bernama $usertidak aktif dalam lingkup saat ini dan oleh karena itu tidak dapat ditimpa oleh panggilan ceroboh ke, misalnya, $user = NULLlebih lanjut dalam fungsi. Saya tidak 100% tentang itu.

Clive
sumber
Itulah yang saya tahu dan setujui dalam pernyataan terakhir Anda.
saadlulu
1
global $user;harus secara umum digunakan ketika variabel dirujuk lebih dari satu kali, dan $GLOBALS['user']harus digunakan ketika digunakan hanya sekali dalam kode fungsi; Kode Drupal tidak konstan dalam hal itu. Ada kasus di mana global $user;diperlukan: ketika objek pengguna dilewatkan ke drupal_alter()untuk memungkinkan modul pihak ketiga untuk mengubah pengguna yang sedang aktif (yang bukan sesuatu yang benar-benar diimplementasikan dalam Drupal).
kiamlaluno
1
global $usertidak sama dengan user_uid_optional_load (). Yang pertama dimuat dari sesi dan bukan objek pengguna yang terisi penuh (dengan bidang dan kait dilibatkan) sedangkan yang kedua adalah. Jadi saya tidak akan mencantumkan ini sebagai opsi. Tujuan dari fungsi itu adalah untuk digunakan untuk argumen menu bernama yang secara opsional dapat menerima id pengguna dan jika tidak default untuk pengguna saat ini. / user / uid adalah contoh utama.
Berdir
@Berdir Terima kasih, saya tidak tahu global $useritu tidak sepenuhnya dimuat secara default (meskipun masuk akal dan menjelaskan beberapa hal yang saya bertanya-tanya sebelumnya). Saya sudah mengeluarkannya dari jawabannya.
Clive
Terima kasih Clive, saya kira menggunakan pengguna $ global dan menyalinnya ke variabel $ akun mungkin merupakan alternatif paling aman. Saya benar-benar mencari user_uid_optional_load () :) :)
Alex Weber
3

Ini sesederhana mendeklarasikan objek $ global pengguna (yang ada) dalam lingkup fungsi Anda:

global $user;

Perlu diingat bahwa perubahan yang dilakukan pada objek ini memengaruhinya secara global, yaitu

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

baru saja memberi pengguna saat ini 1 hak istimewa. Inilah sebabnya biasanya $ user ditugaskan ke $ akun sehingga data dapat diutak-atik tanpa benar-benar memengaruhi pengguna yang saat ini masuk (kecuali, tentu saja, Anda ingin).

Charlie Schliesser
sumber