È considerato una cattiva pratica avere PHP nel tuo JavaScript


55

Tante volte su questo sito vedo persone che cercano di fare cose del genere:

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

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

  });
</script>

Non penso che questo sia un tipo di modello in cui le persone cadono naturalmente. Ci deve essere una sorta di tutorial o materiale didattico là fuori che sta mostrando questo, altrimenti non lo vedremmo così tanto. Quello che sto chiedendo è: sto facendo un affare troppo grande o è davvero una brutta pratica?

EDIT: Stavo parlando con un mio amico di questo che spesso inserisce ruby ​​nel suo JavaScript e ha sollevato questo punto.

Va bene posizionare dinamicamente le costanti ampie dell'applicazione nel tuo JavaScript in modo da non dover modificare due file. per esempio...

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

inoltre è OK codificare direttamente i dati che si prevede di utilizzare in una libreria

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

o dovremmo effettuare una chiamata AJAX ogni volta?


4
Mi sembra che this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom il

7
@ M.Babcock Questo farebbe parte di un file .php, quindi il codice php verrebbe eseguito sul lato server e il client vedrebbe solo il risultato dell'eco.

8
Chiunque crei JavaScript generato dinamicamente viene
ritirato

5
@Matt poi porterò google indietro e mi occuperò di loro
Raynos

4
"Hai il tuo javascript nel mio PHP!" "No, hai il tuo PHP nel mio javascript!"
Josh Darnell,

Risposte:


83

In genere, è una cattiva pratica utilizzare la lingua X per generare il codice nella lingua Y.

Prova a disaccoppiare le due lingue rendendo i dati la loro unica interfaccia - non mescolare il codice .

Nel tuo esempio, potresti migliorare il codice usando PHP per popolare una cfgstruttura disponibile per JavaScript:

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

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

In questo modo, PHP si preoccupa solo di popolare la struttura dei dati e JavaScript si preoccupa solo di consumare la struttura dei dati.

Questo disaccoppiamento apre anche la strada al caricamento asincrono dei dati (JSON) in futuro.

Aggiornare:

Per rispondere alle domande aggiuntive che hai posto con il tuo aggiornamento, sì, sarebbe buona norma applicare il principio DRY e lasciare che PHP e JavaScript condividano lo stesso oggetto di configurazione:

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

  ...

Non vi è alcun danno nell'inserimento della rappresentazione JSON della configurazione direttamente nella pagina in questo modo. Non è necessario recuperarlo tramite XHR.


21
Ricorda però di non mettere la tua password MySQL in $ cfg !!
Thomas Bonini,

13
"Rendere i dati la loro unica interfaccia - non mescolare il codice." Penso che questo tagli davvero al nocciolo della questione ed è una buona regola empirica quando si usano QUALSIASI due lingue insieme. Grazie per la comprensione.
Greg Guida,

6
Potresti anche includere quel JSON in un data-attributo nel tuo HTML. Qualcosa del genere <body data-cfg="{...}">.
Kapa,

1
@bazmegakapa Penso che potrebbe essere l'opzione migliore. In particolare, consente l'uso di API come DOM HTML che riducono notevolmente il rischio di iniezioni XSS.
luiscubal,

1
+1 per suggerire di utilizzare i dati come interfaccia e scoraggiare il codice che genera codice.
Brandon

21

JavaScript generato dinamicamente è una brutta pratica orribile.

Quello che dovresti fare è capire cosa significano Separazione delle preoccupazioni e Miglioramento progressivo.

Questo in pratica significa che hai HTML dinamico e JavaScript statico (che migliora l'HTML).

Nel tuo caso probabilmente desideri una classe sul tuo div e selezionala con un selettore di classe


10

Il problema più grande con lo snippet è che ti manca il #renderlo un selettore jQuery valido;).

Direi che dovresti cercare di evitare di includere PHP nel tuo JavaScript ove possibile. Cosa c'è di sbagliato nel cambiare il selettore nel tuo click()gestore in una classe e nell'aggiungere la classe all'elemento in questione se vuoi che il gestore venga licenziato e non se non lo fai;

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

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

  });
</script> 

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

Ci sono circostanze in cui devi includere PHP nel tuo JavaScript; ma devo ammettere che questi sono pochi e rari.

Un esempio è quando si hanno ambienti diversi; test, messa in scena e live. Ognuno di essi ha una posizione diversa delle risorse (principalmente immagini). Il modo più semplice per impostare il percorso in modo che possa essere utilizzato da JavaScript è qualcosa di simile;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };

Nel resto del mio immaginario codice php ho già aggiunto il #=) ma sono seriamente d'accordo sul fatto che il tuo esempio sia il modo migliore per farlo. Mi sembra più naturale farlo anche in questo modo. Quindi perché lo vediamo così spesso in luoghi dove non è necessario?
Greg Guida,

Si noti che l'eco dei dati statici in un file di configurazione può essere facilmente evitato facendo in modo che tutti gli ambienti siano configurati allo stesso modo.
Raynos,

4
@GregGuida: La mia ipotesi sarebbe che i programmatori sono raramente abituati a gestire architetture client / server come te nello sviluppo web. Trattano DB <-> PHP <-> HTML / JS / CSS come uno e non comprendono appieno cosa dovrebbe andare dove e come i livelli devono essere separati.
Matt,

@Matt Penso che questa sia probabilmente la migliore spiegazione
Greg Guida

2
$divID = '#' . $element_id_value;- nessun problema con il capo selettore;)
rlemon

8

Questa è una cattiva pratica secondo me, dato che dovresti chiamare questo file qualcosa.php e quindi non puoi comprimerlo per esempio, senza menzionare che non va bene mescolare le cose del tuo server con il tuo JavaScript. Cerca di limitare il più possibile la miscelazione tra PHP e JS.

Puoi sempre farlo invece:

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

E poi potresti chiamare questa funzione in un file php, per rendere queste cose di missaggio il più piccole possibili.

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

In questo modo (avendo file JS più grandi, non 2-3 righe dove non importa) puoi trarre vantaggio dalla compressione del file JS e gli sviluppatori front-end si sentono molto a loro agio lavorando solo con JavaScript secondo me (come potresti scrivere Python, Ruby ecc. Non solo PHP - e il codice potrebbe diventare sempre più grande a seconda di cosa devi fare lì).


2
Totalmente d'accordo, tra l'altro non ho mai messo PHP nel mio JS. Lo vedo sempre su questo sito.
Greg Guida,

Il codice php non arriva mai al browser! Solo il codice valutato che ora dovrebbe essere javascript semplice. Quindi la dimensione / compressione del file non è un problema. Ancora cattiva pratica pensata!
James Anderson,

@JamesAnderson Penso che alessioalex si riferisca alla minificazione (come Uglify). Potrebbe essere possibile eseguire php, quindi fare in modo che una funzione php post-elaborazione analizzi la risposta, identifichi il tag di script, lo esegua tramite Uglify e sostituisca il JS originariamente generato da php con la versione minimizzata prima di inviare la risposta, ma farlo su ogni richiesta suona come un yikes! approccio.
jinglesthula,

6

Non credo sia una cattiva pratica. Se l'ID richiesto nel tuo JavaScript è dinamico, non c'è altro modo per farlo.


5
Perché nel cattivo nome di cuthulu non dovresti conoscere il nome di un tag ID?
Incognito,

3
@Incognito, ci sono molte volte in cui non conosci l'ID ... Se stai usando Ajax per generare nuovi blocchi di codice, potresti generare ID univoci insieme a nuovi JS ... in questi casi devi assicurarsi che gli ID che fanno riferimento siano gli stessi in js se si trovano nel blocco di codice risultante. Ci sono molti più casi come questo ed è abbastanza comune quando è coinvolto ajax o ci sono grandi blocchi di codice che dipendono da un'istruzione if-else sul lato server ecc.

7
@raynjamin Non capisco nemmeno come ti metti in situazioni in cui è quello che stai facendo ... o perché dovresti selezionare per classe, quindi elencare i tag, quindi gli attributi ID che hanno un valore css nascosto, quell'uomo selettore ... mi fa davvero male guardare ... Non so nemmeno da dove cominciare ... come ... cosa? Stai tagliando + incollando enormi blocchi di codice o qualcosa per far funzionare le cose su più ID? Non mi piace nemmeno ... il mio cervello. sta esplodendo qui.
Incognito,

3
Vai a leggere su dom / html / qualunque cosa ... usa un motore di ricerca ... Perché non ho mai dovuto fare cose del genere con HTML dinamico?
Incognito,

5
no. non capisci come funzionano i tag ID. Capisco esattamente cosa stai dicendo.
Incognito,

6

Considererei questa cattiva pratica. Quando si inseriscono contenuti dinamici all'interno di blocchi di script, è sempre necessario essere consapevoli del fatto che fuggire all'interno di un contesto javascript non è così semplice come si spera. Se i valori sono fornite dall'utente, è non sufficiente a conferire loro html fuggire.

Il cheat sheet di OWASP XSS ha maggiori dettagli, ma in sostanza dovresti adottare questo schema:

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

Quindi, in un file .js separato collegato dal tuo html principale, carica questo codice:

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

Il motivo per l'utilizzo di un file .js separato è duplice:

  • È memorizzabile nella cache, quindi le prestazioni sono migliori
  • Il parser HTML non viene attivato, quindi non vi è alcun rischio che un bug XSS scivoli da parte di qualcuno che inserisce un tag <? Php rapido da qualche parte

+1 per spiegare completamente l'angolo XSS! Il tuo approccio si caricherà più velocemente perché il json viene caricato prima di domready, ma preferisco il json automatico che analizza dall'uso $.ajaxo simile
roo2

5

Alcune persone sostengono che è una cattiva pratica. Non perché è PHP all'interno di JS, ma perché è in linea JS e quindi non verrà memorizzato nella cache dal browser per facilitare il caricamento la volta successiva.

IMO è sempre meglio usare JSON per passare variabili tra le 2 lingue, ma immagino dipenda da te.


5

Direi che in generale non farlo. Tuttavia, se vuoi passare i dati da PHP -> Javascript, non mi farebbe impazzire avere un blocco Javascript in linea in cui hai il codice del modulo mostrato sotto. Qui il codice sta semplicemente passando i dati da php a javascript, non creando logica al volo o simili. La parte buona di questo rispetto a una chiamata Ajax è che i dati sono disponibili non appena la pagina viene caricata e non richiede un viaggio aggiuntivo al server.

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

Naturalmente un'altra opzione è quella di creare un file di configurazione javascript da PHP tramite una qualche forma di script di compilazione che lo inserirà in un file .js.


4

L'unica cosa a cui posso pensare che può davvero causare problemi è quando gli errori PHP sono impostati per essere visualizzati e quindi inserisce un carico di HTML che mostra l'errore PHP nel tuo JavaScript.

Anche perché è nello script, quindi non viene mostrato e talvolta può richiedere del tempo per capire perché il tuo script è rotto.


ottimo caso in cui ciò causa un grosso errore
Greg Guida,

3

Dipende da chi, e se me lo chiedi, sì, lo considero una pratica precedente per alcuni motivi. Prima di tutto, preferirei avere un codice javascript nel suo file JS che il parser php non sarebbe in grado di toccare.

In secondo luogo, php viene eseguito solo al momento del server, quindi se si dipende da alcune variabili in php per modificare il proprio javascript, potrebbe non funzionare molto bene. Se c'è qualche impostazione di caricamento della pagina che vuoi controllare con javascript, in genere preferisco aggiungere quel valore al DOM con php in modo che javascript possa raggiungerlo quando e se lo desidera (in un div nascosto, ad esempio).

Infine, solo per scopi organizzativi, questo può diventare molto fastidioso. È abbastanza brutto mescolare html e php (secondo me).


1

Il contenimento del PHP in un configoggetto dati è del 90%, ma la migliore pratica è separarlo completamente. Puoi usare un'API RESTful per richiedere solo i dati di cui hai bisogno, è un po 'più javascript ma con alcuni vantaggi.

  • Lo script è statico e può essere memorizzato nella cache in modo permanente
  • PHP non è più un vettore XSS
  • Completa separazione delle preoccupazioni

Svantaggi:

  • Richiede una richiesta HTTP aggiuntiva
  • JavaScript più complesso

copione

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

-3

Non è una cattiva pratica SOLO se viene utilizzato per l'inizializzazione del codice javascript (nei miei temi WordPress, inizializzo i miei oggetti javascript con funzioni php come site_url () perché è l'unico modo per gestirlo (forse potremmo usare una richiesta Ajax per ottenere un json, e così ... ma è un dolore nel culo).

Buona pratica:

nuovo javascriptObject ("");

Cattiva pratica:

/ * un po 'di codice * / document.get_element_by_id (); / * un po 'di codice * /
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.