มีฟังก์ชั่นเพื่อรับวัตถุผู้ใช้ปัจจุบันที่หลีกเลี่ยงการเข้าถึงตัวแปรทั่วโลกหรือไม่?


29

ฉันเคยไปกับสิ่งนี้มาglobal $user;ตลอด $userแต่ฉันดูเหมือนจะจำได้ว่าเห็นบางสิ่งบางอย่างในโมดูลที่มีส่วนที่ส่งคืนวัตถุผู้ใช้ในปัจจุบันโดยไม่ต้องใช้ทั่วโลก

ฟังก์ชั่นดังกล่าวมีอยู่ในแกนกลาง Drupal 7 หรือใช้ตัวแปรทั่วโลกซึ่งเป็นวิธีที่แนะนำโดยไม่ได้ตั้งใจเพื่อรับวัตถุผู้ใช้ปัจจุบันหรือไม่?


ทำไมคุณไม่ลองใช้ผู้ใช้ $ ทั่วโลก?
saadlulu

5
การใช้ผู้ใช้ทั่วโลก $ สามารถสร้างพฤติกรรมที่ไม่พึงประสงค์ที่อาจเกิดขึ้นหากมีการเปลี่ยนแปลงอย่างไม่ระมัดระวังในภายหลังในรหัส
Alex Weber

คำตอบ:


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 () ครั้งแรกจะถูกโหลดจากเซสชั่นและไม่ได้เป็นวัตถุผู้ใช้ที่โหลดเต็ม (มีการเรียกเขตข้อมูลและ hooks) ในขณะที่สองคือ ดังนั้นฉันจะไม่แสดงรายการนี้เป็นตัวเลือก วัตถุประสงค์ของฟังก์ชั่นนั้นจะใช้สำหรับการโต้แย้งเมนูที่ตั้งชื่อซึ่งสามารถเลือกที่จะยอมรับ ID ผู้ใช้และมิฉะนั้นจะเป็นค่าเริ่มต้นสำหรับผู้ใช้ปัจจุบัน / user / uid เป็นตัวอย่างหลัก
Berdir

@Berdir ขอบคุณฉันไม่ทราบว่าglobal $userไม่เต็มโหลดโดยค่าเริ่มต้น (แม้ว่าจะทำให้รู้สึกและอธิบายสองสิ่งที่ฉันสงสัยเกี่ยวกับก่อน) ฉันเอามันออกมาจากคำตอบ
ไคลฟ์

ขอบคุณไคลฟ์ฉันคิดว่าการใช้ผู้ใช้ $ ทั่วโลกและคัดลอกไปยังตัวแปรบัญชี $ อาจเป็นทางเลือกที่ปลอดภัยที่สุด จริง ๆ แล้วฉันกำลังมองหา user_uid_optional_load () แม้ว่า :)
อเล็กซ์ Weber

3

มันง่ายพอ ๆ กับการประกาศออบเจกต์ user $ global (ที่มีอยู่) ภายในขอบเขตของฟังก์ชันของคุณ:

global $user;

โปรดทราบว่าการเปลี่ยนแปลงที่เกิดขึ้นกับวัตถุนี้มีผลกระทบกับวัตถุเช่น

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

เพิ่งให้สิทธิ์ผู้ใช้ปัจจุบันกับ uid 1 นี่คือเหตุผลที่โดยทั่วไปจะมีการกำหนด $ user ให้กับบัญชี $ เพื่อให้สามารถแก้ไขข้อมูลได้โดยไม่กระทบต่อผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน (ยกเว้นแน่นอนว่าคุณต้องการ)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.