Apakah dianggap praktik buruk untuk memiliki PHP di JavaScript Anda

55

Berkali-kali di situs ini saya melihat orang-orang mencoba melakukan hal-hal seperti ini:

<script type="text/javascript">
  $(document).ready(function(){

     $('<?php echo $divID ?>').click(funtion(){
       alert('do something');
     });

  });
</script>

Saya tidak berpikir bahwa ini adalah semacam pola yang orang alami. Pasti ada semacam tutorial atau materi pembelajaran di luar sana yang menunjukkan ini, kalau tidak kita tidak akan terlalu banyak melihatnya. Yang saya tanyakan adalah, apakah saya terlalu mempermasalahkan hal ini atau apakah ini praktik yang benar-benar buruk?

EDIT: Apakah berbicara kepada seorang teman saya tentang ini yang sering menaruh ruby ​​dalam JavaScript-nya dan dia mengemukakan hal ini.

Apakah boleh untuk secara dinamis menempatkan konstanta lebar aplikasi dalam JavaScript Anda sehingga Anda tidak perlu mengedit dua file. sebagai contoh...

MYAPP.constants = <php echo json_encode($constants) ?>;

juga tidak apa-apa untuk secara langsung menyandikan data yang Anda rencanakan untuk digunakan di perpustakaan

ChartLibrary.datapoints = <php echo json_encode($chartData) ?>;   

atau haruskah kita melakukan panggilan AJAX setiap kali?

Greg Guida
sumber
4
Sepertinya saya bahwa this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom
7
@ M.Babcock Ini akan menjadi bagian dari file .php, sehingga kode php akan dieksekusi di sisi server, dan klien hanya akan melihat hasil dari gema.
8
Siapa pun yang membuat JavaScript yang dihasilkan secara dinamis, akan dikeluarkan kembali dan ditangani
Raynos
5
@Matt maka saya akan mengambil google kembali dan berurusan dengan mereka
Raynos
4
"Kamu punya javascript di PHP-ku!" "Tidak, kamu punya PHP di javascript saya !"
Josh Darnell

Jawaban:

83

Biasanya, itu adalah praktek buruk untuk menggunakan bahasa X untuk menghasilkan kode dalam bahasa Y.

Coba pisahkan kedua bahasa dengan membuat data sebagai satu-satunya antarmuka - jangan campur kode .

Dalam contoh Anda, Anda bisa meningkatkan kode dengan menggunakan PHP untuk mengisi cfgstruktur yang tersedia untuk JavaScript:

<script type="text/javascript">
  var cfg = {
    theId: "<?php echo $divID ?>",
    ...
  };

  $(document).ready(function(){
     $("#" + cfg.theId).click(funtion(){
       alert('do something');
     });
  });
</script>

Dengan cara ini, PHP hanya peduli tentang mengisi struktur data dan JavaScript hanya peduli tentang penggunaan struktur data.

Decoupling ini juga mengarah pada cara memuat data secara asinkron (JSON) di masa mendatang.

Memperbarui:

Untuk menjawab pertanyaan tambahan yang Anda tanyakan dengan pembaruan Anda, ya, itu akan menjadi praktik yang baik untuk menerapkan prinsip KERING dan biarkan PHP dan JavaScript berbagi objek konfigurasi yang sama:

<script type="text/javascript">
  var cfg = <?php echo json_encode($cfg) ?>;

  ...

Tidak ada salahnya memasukkan representasi JSON dari konfigurasi Anda langsung ke halaman Anda seperti ini. Anda tidak harus mengambilnya melalui XHR.

Makan Goral
sumber
21
Ingatlah untuk tidak memasukkan kata sandi MySQL Anda dalam $ cfg !!
Thomas Bonini
13
"Membuat data sebagai satu-satunya antarmuka - jangan campur kode." Saya pikir ini benar-benar memotong inti dari masalah ini dan merupakan aturan praktis yang baik ketika menggunakan dua bahasa APAPUN bersama. Terima kasih atas wawasannya.
Greg Guida
6
Anda juga bisa memasukkan JSON itu ke dalam data-atribut di HTML Anda. Sesuatu seperti <body data-cfg="{...}">.
kapa
1
@ bazmegakapa saya pikir itu mungkin pilihan terbaik. Secara khusus, ini memungkinkan penggunaan API seperti HTML DOM yang sangat mengurangi risiko injeksi XSS.
Luiscubal
1
+1 untuk menyarankan penggunaan data sebagai antarmuka dan kode yang tidak disarankan yang menghasilkan kode.
Brandon
21

JavaScript yang dihasilkan secara dinamis adalah praktik yang mengerikan dan buruk.

Apa yang seharusnya Anda lakukan adalah memahami apa artinya Pemisahan Masalah dan Peningkatan Progresif.

Ini pada dasarnya berarti Anda memiliki HTML dinamis dan JavaScript statis (yang meningkatkan HTML).

Dalam kasus Anda, Anda mungkin ingin kelas di div Anda dan pilih dengan pemilih kelas

Raynos
sumber
10

Masalah terbesar dengan cuplikan Anda adalah Anda melewatkannya #untuk menjadikannya pemilih jQuery yang valid;).

Saya akan mengatakan Anda harus mencoba menghindari memasukkan PHP dalam JavaScript Anda jika memungkinkan. Apa yang salah dengan mengubah pemilih di click()handler Anda ke kelas, dan menambahkan kelas ke elemen yang dimaksud jika Anda ingin handler dipecat, dan tidak jika Anda tidak;

<script type="text/javascript">
  $(document).ready(function(){

     $('.foo').click(funtion(){
       alert('do something');
     });

  });
</script> 

<div id="bar" class="<?php echo ($someCond ? 'foo' : ''); ?>">Hello</div>

Ada beberapa situasi di mana Anda perlu memasukkan PHP ke dalam JavaScript Anda; tetapi saya harus mengakui ini sedikit dan jarang.

Salah satu contohnya adalah ketika Anda memiliki lingkungan yang berbeda; uji, pementasan dan hidup. Masing-masing memiliki lokasi aset Anda yang berbeda (gambar, terutama). Cara termudah untuk mengatur jalur agar dapat digunakan oleh JavaScript adalah sesuatu seperti;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };
Mat
sumber
Di sisa kode php imajiner saya, saya sudah menambahkan #=) tapi serius saya setuju bahwa Anda contoh adalah cara yang lebih baik untuk melakukannya. Tampaknya lebih alami bagi saya untuk melakukannya juga. Jadi mengapa kita sering melihatnya di tempat-tempat yang tidak perlu?
Greg Guida
Perhatikan bahwa menggemakan data statis dalam file konfigurasi dapat dengan mudah dihindari dengan mengatur semua lingkungan Anda dengan cara yang sama.
Raynos
4
@GregGuida: Dugaan saya adalah bahwa pemrogram jarang digunakan untuk berurusan dengan arsitektur klien / server seperti yang Anda dapatkan dalam pengembangan web. Mereka memperlakukan DB <-> PHP <-> HTML / JS / CSS sebagai satu, dan tidak sepenuhnya mengerti apa yang harus pergi ke mana, dan bagaimana lapisan-lapisan harus dipisahkan.
Mat
@ Matt Saya pikir itu mungkin penjelasan terbaik
Greg Guida
2
$divID = '#' . $element_id_value;- tidak ada masalah dengan bos pemilih;)
rlemon
8

Ini adalah praktik yang buruk menurut saya, karena Anda perlu memanggil file ini something.php dan kemudian Anda tidak bisa mengompresnya misalnya, tidak menyebutkan itu tidak ok untuk mencampur barang server Anda dengan JavaScript Anda. Cobalah untuk membatasi pencampuran antara PHP dan JS sebanyak mungkin.

Anda selalu dapat melakukan ini sebagai gantinya:

function setOnClick(divid) {
 $(divid).click(funtion(){
   alert('do something');
 });
}

Dan kemudian Anda bisa memanggil fungsi ini dalam file php, untuk membuat pencampuran ini sekecil mungkin.

$(function() {
  setOnClick('<?php echo $divId; ?>');
});

Dengan melakukan ini (memiliki file JS lebih besar, bukan 2-3 baris di mana tidak masalah) Anda dapat mengambil keuntungan dari mengompresi file JS dan pengembang front-end merasa lebih nyaman bekerja hanya dengan JavaScript menurut saya (seperti yang Anda bisa tulis Python, Ruby, dll, tidak hanya PHP - dan kode bisa menjadi lebih besar dan lebih besar tergantung pada apa yang perlu Anda lakukan di sana).

alessioalex
sumber
2
Totaly setuju, tapi saya TIDAK PERNAH menaruh PHP di JS saya. Saya hanya melihatnya di situs ini sepanjang waktu.
Greg Guida
Kode php tidak pernah sampai ke browser! Hanya kode yang dievaluasi yang seharusnya menjadi javascript biasa. Jadi ukuran file / kompresi bukan masalah. Praktek pikiran masih buruk!
James Anderson
@ JamesAnderson Saya pikir alessioalex mengacu pada minifikasi (seperti Uglify). Dimungkinkan untuk menjalankan php, dan kemudian memiliki fungsi php pasca proses mengurai respons, mengidentifikasi tag skrip, menjalankannya melalui Uglify, dan mengganti JS yang dibuat php asli dengan versi yang diperkecil sebelum mengirim respons, tetapi melakukan itu pada setiap permintaan terdengar seperti Astaga! pendekatan.
jinglesthula
6

Saya pikir ini bukan praktik buruk. Jika ID yang diperlukan dalam JavaScript Anda dinamis, tidak ada cara lain untuk melakukan ini.

CodeZombie
sumber
5
Mengapa dengan nama suci Cuthulu Anda tidak tahu nama tag ID?
Incognito
3
@Incognito, ada banyak waktu ketika Anda tidak tahu ID ... Jika Anda menggunakan ajax untuk menghasilkan blok kode baru Anda mungkin menghasilkan ID unik bersama dengan JS baru ... dalam kasus ini Anda perlu pastikan bahwa ID yang menjadi referensi sama di js apakah mereka berada di blok kode yang dihasilkan. Ada lebih banyak contoh seperti ini dan itu cukup umum ketika ajax terlibat atau ada blok besar kode tergantung pada pernyataan sisi-server jika-lain dll
7
@raynjamin Saya bahkan tidak mengerti bagaimana Anda menempatkan diri Anda dalam situasi di mana itu yang Anda lakukan ... atau mengapa Anda memilih berdasarkan kelas, lalu daftar tag, lalu atribut ID yang memiliki nilai css tersembunyi, pemilih pria itu ... itu benar-benar membuatku sedih untuk melihat ... Aku bahkan tidak tahu harus mulai dari mana ... seperti ... apa? Apakah Anda memotong + menyisipkan blok kode yang sangat besar atau sesuatu untuk membuat berbagai hal berfungsi lebih dari beberapa ID? Aku bahkan tidak ... suka ... otakku. meledak di sini.
Incognito
3
Baca tentang dom / html / apa pun ... gunakan mesin pencari ... Mengapa saya tidak pernah melakukan hal seperti ini dengan HTML dinamis?
Incognito
5
tidak. Anda tidak mengerti cara kerja tag ID. Saya mengerti persis apa yang Anda katakan.
Incognito
6

Saya akan mempertimbangkan praktik buruk ini. Saat meletakkan konten dinamis di dalam blok skrip Anda harus selalu menyadari fakta bahwa melarikan diri dalam konteks javascript tidak semudah yang Anda harapkan. Jika nilai yang disediakan pengguna, tidak cukup untuk menghindarinya.

The OWASP XSS contekan memiliki rincian lebih lanjut, tetapi pada dasarnya Anda harus mengadopsi pola ini:

<script id="init_data" type="application/json">
    <?php echo htmlspecialchars(json_encode($yourdata)); ?>
</script>

Kemudian dalam file .js terpisah yang ditautkan dari html utama Anda, muat kode ini:

var dataElement = document.getElementById('init_data');
var jsonText = dataElement.textContent || dataElement.innerText  // unescapes the content of the span
var initData = JSON.parse(jsonText);

Alasan untuk menggunakan file .js terpisah adalah dua kali lipat:

  • Ini dapat disimpan dalam cache sehingga kinerjanya lebih baik
  • Parser HTML tidak dipicu, jadi tidak ada risiko bug XSS menyelinap melalui seseorang yang memasang tag <? Php cepat di sana di suatu tempat
Joeri Sebrechts
sumber
+1 untuk sepenuhnya menjelaskan sudut XSS! Pendekatan Anda akan memuat lebih cepat karena json dimuat sebelum domready, tapi saya lebih suka parsing json otomatis menggunakan $.ajaxatau serupa
roo2
5

Beberapa orang akan berpendapat bahwa ini adalah praktik yang buruk. Bukan karena itu PHP di dalam JS, tetapi karena itu JS inline dan karenanya tidak akan di-cache oleh browser untuk kemudahan memuat di lain waktu.

IMO selalu lebih baik menggunakan JSON untuk mengirimkan variabel antara 2 bahasa, tapi saya rasa itu terserah Anda.

Nick
sumber
5

Saya akan mengatakan bahwa secara umum jangan lakukan itu. Namun, jika Anda ingin meneruskan data dari PHP -> Javascript, saya tidak akan tergila-gila memiliki blok Javascript inline di mana Anda memiliki kode formulir yang ditunjukkan di bawah ini. Di sini kodenya hanya meneruskan data dari php ke javascript, tidak membuat logika dengan cepat atau sejenisnya. Bagian terbaik dari melakukan ini vs panggilan ajax adalah bahwa data tersedia segera setelah halaman dimuat dan tidak memerlukan perjalanan tambahan ke server.

<script>
window.config = <?php echo json_encode($config);?>;
</script>

Tentu saja pilihan lain adalah membangun file konfigurasi javascript dari PHP melalui beberapa bentuk skrip build yang akan memasukkannya ke dalam file .js.

Zachary K
sumber
4

Satu-satunya hal yang dapat saya pikirkan yang benar-benar dapat menyebabkan masalah adalah ketika kesalahan PHP diatur untuk ditampilkan dan karena itu mendorong beban HTML yang menunjukkan kesalahan PHP ke dalam JavaScript Anda.

Juga karena itu dalam naskah itu karena itu tidak muncul dan kadang-kadang perlu waktu untuk menyadari mengapa skrip Anda rusak.

Alex Coplan
sumber
Kasus hebat di mana ini menyebabkan kesalahan besar
Greg Guida
3

Itu tergantung oleh siapa, dan jika Anda bertanya kepada saya, ya saya mempertimbangkannya kembali berlatih karena beberapa alasan. Pertama-tama, saya lebih suka memiliki kode javascript di file JS sendiri yang tidak dapat disentuh oleh parser php.

Kedua, php dijalankan hanya pada waktu server, jadi jika Anda bergantung pada beberapa variabel dalam php untuk mengubah javascript Anda, itu mungkin tidak berfungsi dengan baik. Jika ada beberapa pengaturan pemuatan halaman yang ingin Anda kontrol dengan javascript, saya biasanya lebih suka menambahkan nilai itu ke DOM dengan php sehingga javascript dapat mencapainya kapan dan jika ia menginginkannya (dalam div tersembunyi, misalnya).

Akhirnya, hanya untuk tujuan organisasi, ini bisa sangat menjengkelkan. Sudah cukup buruk untuk mencampur html dan php (menurut saya).

Pil Ledakan
sumber
1

Mengandung PHP menjadi configobjek data berjalan 90%, tetapi praktik terbaik adalah memisahkannya sepenuhnya. Anda dapat menggunakan api yang tenang untuk hanya meminta data yang Anda butuhkan, ini sedikit lebih javascript tetapi dengan beberapa keuntungan.

  • Script bersifat statis dan dapat di-cache secara permanen
  • PHP bukan lagi vektor XSS
  • Pemisahan yang lengkap dari keprihatinan

Kerugian:

  • Membutuhkan permintaan HTTP tambahan
  • javascript yang lebih kompleks

Naskah

//pure javascript
$.on('domready',function({
    //load the data
    $.get({
       url:'/charts/3D1A2E', 
       success: function(data){
           //now use the chart data here
           ChartModule.init(data);
       }
    });
})
roo2
sumber
-3

Ini bukan praktik yang buruk HANYA jika digunakan untuk inisialisasi kode javascript, (dalam tema WordPress saya, saya menginisialisasi objek javascript saya dengan fungsi php seperti site_url () karena itu satu-satunya cara untuk mengatasinya (mungkin kita bisa menggunakan permintaan ajax untuk mendapatkan json, dan sebagainya ... tapi itu menyebalkan).

Praktek yang baik:

javascriptObject baru ("");

Praktik buruk:

/ * beberapa kode * / document.get_element_by_id (); / * beberapa kode * /
junius rendel
sumber