¿Se considera una mala práctica tener PHP en tu JavaScript?

55

Muchas veces en este sitio veo personas tratando de hacer cosas como esta:

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

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

  });
</script>

No creo que este sea algún tipo de patrón en el que las personas caigan naturalmente. Debe haber algún tipo de tutorial o material de aprendizaje que muestre esto, de lo contrario no lo veríamos tanto. Lo que pregunto es: ¿estoy haciendo un gran problema o es una práctica realmente mala?

EDITAR: Estaba hablando con un amigo mío sobre esto, que a menudo pone rubí en su JavaScript y mencionó este punto.

¿Está bien colocar dinámicamente constantes de aplicación amplia en su JavaScript para que no tenga que editar dos archivos? por ejemplo...

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

también está bien codificar directamente los datos que planea usar en una biblioteca

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

o deberíamos hacer una llamada AJAX cada vez?

Greg Guida
fuente
44
Me parece que this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom
77
@ M.Babcock Esto sería parte de un archivo .php, para que el código php se ejecute en el lado del servidor y el cliente solo vea el resultado del eco.
8
Quien crea JavaScript generado dinámicamente es retirado y se le trata
Raynos
55
@ Matt, luego retiraré google y me ocuparé de ellos
Raynos
44
"¡Tienes tu javascript en mi PHP!" "No, ¡tienes tu PHP en mi javascript!"
Josh Darnell

Respuestas:

83

Por lo general, es una mala práctica usar el lenguaje X para generar código en el lenguaje Y.

Intente desacoplar los dos idiomas haciendo de los datos su única interfaz, no mezcle el código .

En su ejemplo, podría mejorar el código utilizando PHP para completar una cfgestructura que está disponible para JavaScript:

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

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

De esta manera, PHP solo se preocupa por poblar la estructura de datos y JavaScript solo se preocupa por consumir la estructura de datos.

Este desacoplamiento también abre el camino para cargar los datos de forma asincrónica (JSON) en el futuro.

Actualizar:

Para responder las preguntas adicionales que hizo con su actualización, sí, sería una buena práctica aplicar el principio DRY y dejar que PHP y JavaScript compartan el mismo objeto de configuración:

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

  ...

No hay ningún daño en insertar la representación JSON de su configuración directamente en su página de esta manera. No necesariamente tiene que buscarlo a través de XHR.

Ates Goral
fuente
21
¡Recuerde no poner su contraseña de MySQL en $ cfg!
Thomas Bonini
13
"haciendo de los datos su única interfaz, no mezcle el código". Creo que esto realmente va al centro del problema y es una buena regla general cuando se usan CUALQUIER dos idiomas juntos. Gracias por la perspicacia.
Greg Guida
66
También podría incluir ese JSON en un data-atributo en su HTML. Algo así como <body data-cfg="{...}">.
kapa
1
@bazmegakapa Creo que esa podría ser la mejor opción. En particular, permite el uso de API como HTML DOM que reducen en gran medida el riesgo de inyecciones de XSS.
luiscubal
1
+1 por sugerir el uso de datos como interfaz y el código desalentador que genera código.
Brandon
21

JavaScript generado dinámicamente es una práctica horrible y mala.

Lo que se supone que debes hacer es comprender lo que significa Separación de preocupaciones y Mejora progresiva.

Esto básicamente significa que tiene HTML dinámico y JavaScript estático (que mejora el HTML).

En su caso, probablemente desee una clase en su div y selecciónela con un selector de clase

Raynos
fuente
10

El mayor problema con su fragmento es que le falta el #para convertirlo en un selector jQuery válido;).

Yo diría que debería intentar evitar incluir PHP en su JavaScript cuando sea posible. ¿Qué hay de malo en cambiar el selector en su click()controlador a una clase y agregar la clase al elemento en cuestión si desea que se active el controlador y no si no lo hace;

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

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

  });
</script> 

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

No hay circunstancias en las que hay que incluir en su PHP JavaScript; pero debo admitir que estos son pocos y distantes entre sí.

Un ejemplo es cuando tienes diferentes entornos; prueba, puesta en escena y en vivo. Cada uno de ellos tiene una ubicación diferente de sus activos (imágenes, principalmente). La forma más fácil de establecer la ruta para que JavaScript pueda usarla es algo así como;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };
Mate
fuente
En el resto de mi código php imaginario ya he agregado el #=) pero en serio estoy de acuerdo en que su ejemplo es la mejor manera de hacerlo. Me parece más natural hacerlo de esa manera también. Entonces, ¿por qué lo vemos tan a menudo en lugares donde no es necesario?
Greg Guida
Tenga en cuenta que hacer eco de los datos estáticos en un archivo de configuración se puede evitar fácilmente haciendo que todos sus entornos se configuren de la misma manera.
Raynos
44
@GregGuida: Supongo que los programadores rara vez están acostumbrados a tratar con arquitecturas cliente / servidor como las que obtienes en el desarrollo web. Tratan DB <-> PHP <-> HTML / JS / CSS como uno, y no entienden completamente qué debe ir a dónde y cómo se deben separar las capas.
Matt
@ Matt Creo que esa es probablemente la mejor explicación
Greg Guida
2
$divID = '#' . $element_id_value;- sin problemas con el jefe de selección;)
rlemon
8

Esta es una mala práctica en mi opinión, ya que necesitaría llamar a este archivo algo.php y luego no podría comprimirlo, por ejemplo, sin mencionar que no está bien mezclar las cosas de su servidor con su JavaScript. Intente limitar la mezcla entre PHP y JS tanto como sea posible.

Siempre puedes hacer esto en su lugar:

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

Y luego podría llamar a esta función en un archivo php, para que estas mezclas sean lo más pequeñas posible.

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

Al hacer esto (tener archivos JS más grandes, no 2-3 líneas donde no importa), puede aprovechar la compresión del archivo JS y los desarrolladores front-end se sienten mucho más cómodos trabajando solo con JavaScript en mi opinión (como podría escribir) Python, Ruby, etc., no solo PHP, y el código podría hacerse más y más grande dependiendo de lo que necesite hacer allí).

alessioalex
fuente
2
Totalmente de acuerdo, por cierto, NUNCA puse PHP en mi JS. Solo lo veo en este sitio todo el tiempo.
Greg Guida
¡El código php nunca llega al navegador! Solo el código evaluado que ahora debería ser JavaScript simple. Por lo tanto, el tamaño / compresión del archivo no es un problema. Todavía es una mala práctica pensada!
James Anderson
@JamesAnderson Creo que alessioalex se refiere a la minificación (como Uglify). Puede ser posible ejecutar el php y luego tener una función de php posterior al proceso que analice la respuesta, identifique la etiqueta del script, la ejecute a través de Uglify y reemplace el JS generado originalmente por php con la versión reducida antes de enviar la respuesta, ¡pero hacer eso en cada solicitud suena como un asco! acercarse a, aproximarse.
jinglesthula
6

No creo que esta sea una mala práctica. Si la identificación requerida en su JavaScript es dinámica, no hay otra forma de hacerlo.

CodeZombie
fuente
55
¿Por qué en el impío nombre de cuthulu no sabrías el nombre de una etiqueta de identificación?
Incógnito
3
@Incognito, hay muchas veces que no conoce la ID ... Si está utilizando ajax para generar nuevos bloques de código, puede estar generando ID únicas junto con un nuevo JS ... en estos casos necesita asegúrese de que las ID que son referencias son las mismas en js si están en el bloque de código resultante. Hay muchos más casos como este y es bastante común cuando ajax está involucrado o hay grandes bloques de código que dependen de un lado del servidor if-else etc
77
@raynjamin Ni siquiera entiendo cómo te pones en situaciones donde eso es lo que estás haciendo ... o por qué seleccionarías por clase, luego enumerarías las etiquetas, luego los atributos de ID que tienen un valor css oculto, ese hombre selector ... en realidad me duele mirar ... Ni siquiera sé por dónde empezar ... como ... ¿qué? ¿Estás cortando + pegando bloques masivos de código o algo para que las cosas funcionen en múltiples ID? Ni siquiera ... me gusta ... mi cerebro. Está explotando aquí.
Incógnito
3
Vaya a leer sobre dom / html / lo que sea ... use un motor de búsqueda ... ¿Por qué nunca he tenido que hacer cosas como esta con HTML dinámico?
Incógnito
55
No. no entiendes cómo funcionan las etiquetas de identificación. Entiendo exactamente lo que estás diciendo.
Incógnito
6

Consideraría esta mala práctica. Al colocar contenido dinámico dentro de bloques de script, siempre debe tener en cuenta el hecho de que escapar dentro de un contexto de JavaScript no es tan simple como cabría esperar. Si los valores eran proporcionada por el usuario, es no suficiente para html-escapar de ellos.

La hoja de trucos OWASP XSS tiene más detalles, pero básicamente debes adoptar este patrón:

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

Luego, en un archivo .js separado vinculado desde su html principal, cargue este código:

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

La razón para usar un archivo .js separado es doble:

  • Se puede almacenar en caché para que el rendimiento sea mejor
  • El analizador HTML no se activa, por lo que no existe el riesgo de que un error XSS se deslice por alguien que coloca una etiqueta rápida <? Php en alguna parte
Joeri Sebrechts
fuente
¡+1 para explicar completamente el ángulo XSS! Su enfoque se cargará más rápido porque el json se carga antes de domready, pero prefiero el análisis automático de json usando $.ajaxo similar
roo2
5

Algunas personas argumentan que es una mala práctica. No porque sea PHP dentro de JS, sino porque es JS en línea y, por lo tanto, el navegador no lo almacenará en caché para facilitar la carga la próxima vez.

En mi opinión, siempre es mejor usar JSON para pasar variables entre los 2 idiomas, pero supongo que depende de usted.

Mella
fuente
5

Yo diría que en general no lo hagas. Sin embargo, si desea pasar datos de PHP -> Javascript, no me parecería una locura tener un bloque Javascript en línea donde tenga el código de la forma que se muestra a continuación. Aquí el código solo pasa datos de php a javascript, no crea lógica sobre la marcha o similares. La buena parte de hacer esto frente a una llamada ajax es que los datos están disponibles tan pronto como se carga la página y no requieren un viaje adicional al servidor.

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

Por supuesto, otra opción es construir un archivo de configuración de JavaScript desde PHP a través de alguna forma de script de compilación que lo colocará en un archivo .js.

Zachary K
fuente
4

Lo único que puedo pensar que realmente puede causar problemas es cuando los errores de PHP están configurados para mostrarse y, por lo tanto, empuja una carga de HTML que muestra el error de PHP en su JavaScript.

También porque está en el script, por lo tanto, no se muestra y, a veces, puede tomar un tiempo darse cuenta de por qué su script está roto.

Alex Coplan
fuente
gran caso donde esto causa un gran error
Greg Guida
3

Depende de quién, y si me preguntas, sí, lo considero práctica por varias razones. En primer lugar, preferiría tener código javascript en su propio archivo JS que el analizador de php no podría tocar.

En segundo lugar, php se ejecuta solo en el momento del servidor, por lo que si depende de alguna variable en php para cambiar su javascript, puede que no funcione muy bien. Si hay alguna configuración de carga de página que desea controlar con javascript, generalmente prefiero agregar ese valor al DOM con php para que javascript pueda alcanzarlo cuando y si lo desea (en un div oculto, por ejemplo).

Finalmente, solo para fines organizativos, esto puede ser muy molesto. Es lo suficientemente malo mezclar html y php (en mi opinión).

Píldoras de explosión
fuente
1

Contener el PHP en un configobjeto de datos va el 90% del camino, pero la mejor práctica es separarlo por completo. Puede usar una API RESTful para solicitar solo los datos que necesita, es un poco más javascript pero con algunas ventajas.

  • El script es estático y se puede almacenar en caché de forma permanente.
  • PHP ya no es un vector XSS
  • Separación completa de preocupaciones

Desventajas:

  • Requiere una solicitud HTTP adicional
  • javascript más complejo

Guión

//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
fuente
-3

No es una mala práctica SOLO si se usa para la inicialización del código javascript (en mis temas de WordPress, inicializo mis objetos javascript con funciones php como site_url () porque es la única forma de manejar eso (tal vez podríamos usar una solicitud ajax para obtener un json, y así ... pero es un dolor en el culo).

Buena práctica:

nuevo javascriptObject ("");

Mala práctica:

/ * algún código * / document.get_element_by_id (); / * algún código * /
junius rendel
fuente