Saya gunakan hook_init()
untuk memeriksa waktu akses terakhir pengguna. Jika waktu akses terakhir kemarin, saya menambah penghitung dan menetapkan beberapa variabel.
Masalahnya adalah bahwa hook_init()
kadang-kadang dieksekusi lebih dari sekali (saya bisa melihat ini menggunakan dsm()
) untuk memuat halaman yang sama, jadi kode saya dieksekusi beberapa kali menghasilkan variabel yang salah.
Mengapa hook_init()
dieksekusi lebih dari satu kali?
Apa pendekatan terbaik untuk masalah saya? Haruskah saya menggunakan pengait lain?
Saya melakukan beberapa penggalian lebih lanjut tentang ini:
Saya mencari panggilan ke hook_init () (mencari string module_invoke_all('init');
) tetapi hanya menemukan panggilan inti). Saya tidak tahu apakah ini bisa disebut berbeda.
Ini adalah hook_init saya ()
function episkeptis_achievements_init(){
dsm('1st execution');
dsm('REQUEST_TIME: '.format_date(REQUEST_TIME, 'custom', 'd/m/Y H:i:s').' ('.REQUEST_TIME.')');
}
dan ini adalah output:
1st execution
REQUEST_TIME: 09/07/2012 11:20:32 (1341822032)
kemudian, ubah pesan dsm () menjadi dsm('2nd execution');
dan dieksekusi lagi, ini adalah output:
1st execution
REQUEST_TIME: 09/07/2012 11:20:34 (1341822034)
2nd execution
REQUEST_TIME: 09/07/2012 11:22:28 (1341822148)
Anda dapat melihat bahwa kode dieksekusi dua kali. Namun, pertama kali mengeksekusi salinan kode yang lama, dan yang kedua salinan yang diperbarui. Ada juga perbedaan waktu 2 detik.
Ini adalah versi d7 dengan php 5.3.10
REQUEST_TIME
untuknya akan sama.REQUEST_TIME
berasal dari permintaan halaman yang sama, nilainya sama; bahkan tidak ada perbedaan dua detik. Periksa tidak ada kode yang mengubah nilaiREQUEST_TIME
.Jawaban:
hook_init()
dipanggil oleh Drupal hanya sekali untuk setiap halaman yang diminta; itu adalah langkah terakhir yang dilakukan di _drupal_bootstrap_full () .Jika
hook_init()
dieksekusi lebih dari sekali, Anda harus mengetahui mengapa itu terjadi. Sejauh yang saya bisa lihat, tidak adahook_init()
implementasi dalam Drupal yang memeriksa dieksekusi dua kali (lihat misalnya system_init () , atau update_init () ). Jika itu adalah sesuatu yang biasanya dapat terjadi dengan Drupal, makaupdate_init()
pertama-tama akan memeriksa apakah sudah dijalankan.Jika penghitung adalah jumlah hari berturut-turut pengguna login, saya lebih suka mengimplementasikan
hook_init()
dengan kode yang mirip dengan yang berikut.Jika
hook_init()
dipanggil dua kali berturut-turut selama permintaan halaman yang sama,REQUEST_TIME
berisi nilai yang sama, dan fungsinya akan kembaliFALSE
.Kode dalam
mymodule_increase_counter()
tidak dioptimalkan; itu hanya untuk menunjukkan contoh. Dalam modul nyata, saya lebih suka menggunakan tabel database tempat penghitung, dan variabel lainnya disimpan. Alasannya adalah bahwa variabel Drupal semua dimuat dalam variabel global$conf
ketika Drupal bootstraps (lihat _drupal_bootstrap_variables () , dan variable_initialize () ); jika Anda menggunakan variabel Drupal untuk itu, Drupal akan memuat informasi memori tentang semua pengguna yang Anda simpan informasinya, ketika untuk setiap halaman yang diminta hanya ada satu akun pengguna yang disimpan dalam variabel global$user
.Jika Anda menghitung jumlah halaman yang dikunjungi dari pengguna dalam beberapa hari berturut-turut, maka saya akan menerapkan kode berikut.
Anda akan melihat bahwa dalam kode saya saya tidak menggunakan
$user->access
. Alasannya adalah bahwa$user->access
dapat diperbarui selama bootstrap Drupal, sebelumhook_init()
dipanggil. Pegangan menulis sesi yang digunakan dari Drupal berisi kode berikut. (Lihat _drupal_session_write () .)Adapun hook lain yang dapat Anda gunakan, dengan Drupal 7 Anda dapat menggunakan hook_page_alter () ; Anda hanya tidak mengubah konten
$page
, tetapi menambah penghitung Anda, dan mengubah variabel Anda.Pada Drupal 6, Anda bisa menggunakan hook_footer () , hook yang dipanggil dari template_preprocess_page () . Anda tidak mengembalikan apa pun, tetapi tingkatkan penghitung Anda, dan ubah variabel Anda.
Pada Drupal 6, dan Drupal 7, Anda bisa menggunakan hook_exit () . Ingatlah bahwa kait juga dipanggil saat bootstrap tidak lengkap; kode tidak dapat memiliki akses ke fungsi yang ditentukan dari modul, atau fungsi Drupal lainnya, dan Anda harus terlebih dahulu memeriksa fungsi-fungsi yang tersedia. Beberapa fungsi selalu tersedia
hook_exit()
, seperti yang didefinisikan di bootstrap.inc , dan cache.inc . Perbedaannya adalah yanghook_exit()
dipanggil juga untuk halaman yang di-cache, sementarahook_init()
itu tidak dipanggil untuk halaman yang di-cache.Akhirnya, sebagai contoh kode yang digunakan dari modul Drupal, lihat stats_exit () . Modul Statistik mencatat statistik akses untuk suatu situs, dan seperti yang Anda lihat, ia menggunakan
hook_exit()
, bukanhook_init()
. Agar dapat memanggil fungsi yang diperlukan, ia memanggil drupal_bootstrap () yang melewati parameter yang benar, seperti dalam kode berikut.Memperbarui
Mungkin ada beberapa kebingungan tentang kapan
hook_init()
dipanggil.hook_init()
dipanggil untuk setiap permintaan halaman, jika halaman tersebut tidak di-cache. Itu tidak dipanggil sekali untuk setiap permintaan halaman yang berasal dari pengguna yang sama. Jika Anda mengunjungi, misalnya, http://example.com/admin/appearance/update , lalu http://example.com/admin/reports/status ,hook_init()
akan dipanggil dua kali: satu untuk setiap halaman."Hook dipanggil dua kali" berarti ada modul yang mengeksekusi kode berikut, setelah Drupal menyelesaikan bootstrapnya.
Jika itu masalahnya, maka implementasi berikut
hook_init()
akan menunjukkan nilai yang sama, dua kali.Jika kode Anda ditampilkan untuk
REQUEST_TIME
dua nilai yang perbedaannya adalah 2 menit, seperti dalam kasus Anda, maka kail tidak dipanggil dua kali, tetapi dipanggil sekali untuk setiap halaman yang diminta, seperti yang seharusnya terjadi.REQUEST_TIME
didefinisikan dalam bootstrap.inc dengan baris berikut.Sampai halaman yang diminta saat ini tidak dikembalikan ke browser, nilai
REQUEST_TIME
tidak berubah. Jika Anda melihat nilai yang berbeda, maka Anda menonton nilai yang ditetapkan di halaman permintaan yang berbeda.sumber
Saya ingat ini sering terjadi di Drupal 6 (tidak yakin apakah masih di Drupal 7), tetapi saya tidak pernah tahu mengapa. Saya sepertinya ingat melihat suatu tempat bahwa inti Drupal tidak memanggil kait ini dua kali.
Saya selalu menemukan cara termudah untuk menggunakan variabel statis untuk melihat apakah kode tersebut sudah dijalankan:
Itu akan memastikan itu hanya dijalankan sekali dalam satu halaman memuat.
sumber
hook_init()
implementasinya, dan beberapa dari mereka akan dengan senang hati tidak dieksekusi dua kali berturut-turut. Mungkin juga OP inginhook_init()
dieksekusi sekali per hari, jika penghitung menghitung jumlah hari berturut-turut pengguna telah login di situs.hook_init
memeriksa untuk melihat apakah OP sudah berjalan sekali untuk hari itu dan menebusnya jika sudah. Kemudian semuanya menjadi non-masalahAnda mungkin menemukan hook_init () dipanggil beberapa kali jika ada AJAX yang terjadi pada halaman (atau Anda memuat gambar dari direktori pribadi - meskipun saya tidak begitu yakin tentang itu). Ada beberapa modul yang menggunakan AJAX untuk membantu memotong caching halaman untuk elemen tertentu misalnya - cara termudah untuk memeriksa adalah dengan membuka monitor bersih di debugger pilihan Anda (firefox atau inspektur web) dan melihat apakah ada permintaan dibuat yang bisa memicu proses bootstrap.
Anda hanya akan mendapatkan dpm () pada pemuatan halaman berikutnya jika itu adalah panggilan AJAX. Jadi misalkan Anda me-refresh halaman 5 menit kemudian, Anda akan mendapatkan panggilan AJAX dari 5 menit lalu dengan pesan init dan yang baru.
Alternatif untuk hook_init () adalah hook_boot () yang dipanggil sebelum caching dilakukan. Tidak ada modul yang dimuat, jadi Anda benar-benar tidak memiliki banyak daya di sini selain mengatur variabel global dan menjalankan beberapa fungsi Drupal. Ini berguna untuk melewati caching level reguler (tetapi tidak akan memotong caching agresif).
sumber
Dalam kasus saya, perilaku ini disebabkan oleh modul Menu Administrasi (admin_menu).
hook_init tidak dipanggil setiap permintaan tetapi menu admin akan menyebabkan / js / admin_menu / cache / 94614e34b017b19a78878d7b96ccab55 untuk dimuat oleh browser pengguna tidak lama setelah permintaan utama, memicu bootstrap drupal lainnya.
Akan ada modul lain yang melakukan hal serupa tetapi admin_menu mungkin salah satu yang lebih umum digunakan.
sumber