Pregunta ¿Cómo pasar variables y datos de PHP a JavaScript?


Tengo una variable en PHP, y necesito su valor en mi código JavaScript. ¿Cómo puedo obtener mi variable de PHP a JavaScript?

Tengo un código que se ve así:

<?php
     ...
     $val = $myService->getValue(); // makes an api and db call
?>

Tengo un código de JavaScript que necesita val y se ve en la línea de:

<script>
    myPlugin.start($val); // tried this, didn't work
    <?php myPlugin.start($val); ?> // this didn't work either
    myPlugin.start(<?=$val?> // this works sometimes, but sometimes it fails
</script>

546
2018-05-19 14:37


origen


Respuestas:


En realidad, hay varios enfoques para hacer esto. Algunos requieren más sobrecarga que otros, y algunos se consideran mejores que otros.

Sin ningún orden en particular:

  1. Use AJAX para obtener los datos que necesita del servidor.
  2. Haga eco de los datos en la página en algún lugar, y use JavaScript para obtener la información del DOM.
  3. Echo los datos directamente a JavaScript.

En esta publicación, examinaremos cada uno de los métodos anteriores y veremos los pros y los contras de cada uno, así como también la forma de implementarlos.

1. Usa AJAX para obtener los datos que necesitas del servidor

Este método se considera el mejor, porque las secuencias de comandos del lado del servidor y del lado del cliente están completamente separadas.

Pros

  • Mejor separación entre capas - Si mañana dejas de usar PHP y quieres cambiar a un servlet, una API REST o algún otro servicio, no tienes que cambiar gran parte del código JavaScript.
  • Más legible - JavaScript es JavaScript, PHP es PHP. Sin mezclar los dos, obtienes un código más legible en ambos idiomas.
  • Permite la transferencia de datos asíncrona - Obtener la información de PHP puede ser costoso en tiempo / recursos. A veces simplemente no desea esperar la información, cargar la página y hacer que la información llegue siempre que lo desee.
  • Los datos no se encuentran directamente en el marcado - Esto significa que su marcado se mantiene limpio de cualquier información adicional, y solo JavaScript lo ve.

Contras

  • Estado latente - AJAX crea una solicitud HTTP y las solicitudes HTTP se transfieren a la red y tienen latencias de red.
  • Estado - Los datos obtenidos a través de una solicitud HTTP separada no incluirán ninguna información de la solicitud HTTP que haya obtenido el documento HTML. Es posible que necesite esta información (por ejemplo, si el documento HTML se genera en respuesta a un envío de formulario) y, si lo hace, tendrá que transferirlo de alguna manera. Si ha descartado incrustar los datos en la página (que tiene si está utilizando esta técnica), eso lo limita a cookies / sesiones que pueden estar sujetas a condiciones de carrera.

Ejemplo de implementación

Con AJAX, necesita dos páginas, una es donde PHP genera la salida, y la segunda es donde JavaScript obtiene ese resultado:

get-data.php

/* Do some operation here, like talk to the database, the file-session
 * The world beyond, limbo, the city of shimmers, and Canada.
 * 
 * AJAX generally uses strings, but you can output JSON, HTML and XML as well. 
 * It all depends on the Content-type header that you send with your AJAX
 * request. */

echo json_encode(42); //In the end, you need to eco the result. 
                      //All data should be json_encode ()d.

                      //You can json_encode() any value in PHP, arrays, strings,
                      //even objects.

index.php (o como se llame la página)

<!-- snip -->
<script>
    function reqListener () {
      console.log(this.responseText);
    }

    var oReq = new XMLHttpRequest(); //New request object
    oReq.onload = function() {
        //This is where you handle what to do with the response.
        //The actual data is found on this.responseText
        alert(this.responseText); //Will alert: 42
    };
    oReq.open("get", "get-data.php", true);
    //                               ^ Don't block the rest of the execution.
    //                                 Don't wait until the request finishes to 
    //                                 continue.
    oReq.send();
</script>
<!-- snip -->

La combinación anterior de los dos archivos alertará 42 cuando el archivo termine de cargarse

Un poco más de material de lectura

2. Haga eco de los datos en la página en algún lugar, y use JavaScript para obtener la información del DOM

Este método es menos preferible a AJAX, pero aún tiene sus ventajas. Todavía relativamente separados entre PHP y JavaScript en un sentido que no hay PHP directamente en el JavaScript.

Pros

  • Rápido - Las operaciones DOM a menudo son rápidas, y puede almacenar y acceder a una gran cantidad de datos de forma relativamente rápida.

Contras

  • Marcado potencialmente no semántico - Usualmente, lo que sucede es que usas algún tipo de <input type=hidden> para almacenar la información, porque es más fácil obtener la información de inputNode.value, pero hacerlo significa que tienes un elemento sin sentido en tu HTML. HTML tiene el <meta> elemento para datos sobre el documento, y HTML 5 introduce data-* atributos para datos específicamente para leer con JS que pueden asociarse con elementos particulares.
  • Sucios hasta la fuente - Los datos que PHP genera se envían directamente a la fuente HTML, lo que significa que obtiene una fuente HTML más grande y menos enfocada.
  • Más difícil obtener datos estructurados - Los datos estructurados tendrán que ser HTML válidos; de lo contrario, tendrá que escapar y convertir cadenas usted mismo.
  • Apreta bien PHP a su lógica de datos - Debido a que PHP se utiliza en la presentación, no se pueden separar los dos limpiamente.

Ejemplo de implementación

Con esto, la idea es crear algún tipo de elemento que no se muestre al usuario, pero que sea visible para JavaScript.

index.php

<!-- snip -->
<div id="dom-target" style="display: none;">
    <?php 
        $output = "42"; //Again, do some operation, get the output.
        echo htmlspecialchars($output); /* You have to escape because the result
                                           will not be valid HTML otherwise. */
    ?>
</div>
<script>
    var div = document.getElementById("dom-target");
    var myData = div.textContent;
</script>
<!-- snip -->

3. Echo los datos directamente a JavaScript

Esta es probablemente la más fácil de entender, y la más horrible de usar. No hagas esto a menos que sepas lo que estás haciendo.

Pros

  • Muy fácil de implementar - Se necesita muy poco para implementar esto, y entender.
  • No ensucia la fuente - Las variables se envían directamente a JavaScript, por lo que el DOM no se ve afectado.

Contras

  • Inseguro - PHP no tiene funciones triviales de escape de JavaScript, y no son triviales de implementar. Especialmente cuando se utilizan entradas de usuario, estás extremadamente vulnerable a las inyecciones de segundo nivel. Cuestionado ver comentarios
  • Apreta bien PHP a su lógica de datos - Debido a que PHP se utiliza en la presentación, no se pueden separar los dos limpiamente.
  • Los datos estructurados son difíciles - Probablemente puedas hacer JSON ... un poco. Pero XML y HTML requerirán atención especial.

Ejemplo de implementación

La implementación es relativamente sencilla:

<!-- snip -->
<script>
    var data = <?php echo json_encode("42", JSON_HEX_TAG); ?>; //Don't forget the extra semicolon!
</script>
<!-- snip -->

¡Buena suerte!


738
2018-05-19 14:37



Voy a intentar una respuesta más simple:

Explicación del problema

Primero, comprendamos el flujo de eventos cuando se sirve una página desde nuestro servidor:

  • Primero se ejecuta PHP, genera el HTML que se sirve al cliente.
  • Luego, el HTML se entrega al cliente, luego de que PHP haya terminado, me gustaría enfatizar que una vez que el código abandona el servidor, PHP termina y ya no puede acceder a él.
  • Luego, el HTML con JavaScript llega al cliente, que puede ejecutar JS en ese html.

Entonces, en realidad, lo más importante que hay que recordar aquí es que HTTP es sin estado. Una vez que una solicitud salió del servidor, el servidor no puede tocarla. Entonces, eso deja nuestras opciones para:

  1. Enviar más solicitudes del cliente después la solicitud inicial está hecha.
  2. Codifique lo que el servidor tuvo que decir en la solicitud inicial.

Soluciones

Esa es la pregunta principal que debería hacerse:

¿Estoy escribiendo un sitio web o una aplicación?

Los sitios web se basan principalmente en páginas, y los tiempos de carga de la página deben ser lo más rápidos posible (por ejemplo, Wikipedia). Las aplicaciones web son más pesadas en AJAX y realizan muchos viajes de ida y vuelta para obtener información rápida del cliente (por ejemplo, un tablero de stock).

Sitio web

El envío de más solicitudes del cliente una vez que se realiza la solicitud inicial es lento ya que requiere más solicitudes HTTP que tienen una sobrecarga significativa. Además, requiere asincronismo como hacer una solicitud AJAX requiere un controlador para cuando esté completo.

me gustaría no recomendar hacer otra solicitud a menos que su sitio sea una aplicación para obtener esa información del servidor.

Desea tiempos de respuesta rápidos que tienen un enorme impacto en la conversión y tiempos de carga. Hacer solicitudes ajax es lento para el tiempo de actividad inicial en este caso y no es necesario.

Tienes dos formas de abordar el problema

  • Establecer una cookie - Las cookies son encabezados enviados en solicitudes HTTP que el servidor y el cliente pueden leer.
  • Codifica la variable como JSON - JSON se ve muy cerca de los objetos de JavaScript y más Los objetos JSON son variables de JavaScript válidas.

Configurando una cookie realmente no es muy difícil, solo le asigna un valor:

setcookie("MyCookie", $value); // sets the cookie to the value, remember, do not
                               // set it with HTTP only to true.

Entonces tú puedes léelo con JavaScript utilizando document.cookie:

Aquí hay un pequeño analizador de rollo manual, pero la respuesta a la que se vinculó justo arriba tiene mejores pruebas:

var cookies = document.cookie.split(";").
    map(function(el){ return el.split("="); }).
    reduce(function(prev,cur){ prev[cur[0]] = cur[1];return prev },{});

cookies["MyCookie"] // value set with php.

Las cookies son buenas para un poco de información. Esto es lo que a menudo hacen los servicios de seguimiento.

Una vez que tenemos más datos, podemos codificarlo con JSON dentro de una variable JS en su lugar:

<script>
    var myServerData = <?=json_encode($value)?>; // don't forget to sanitize 
                                                 //server data
</script>

Asumiendo $value es json_encodecapaz en el lado de PHP (generalmente lo es). Esta técnica es lo que StackOverflow hace con su chat, por ejemplo (solo usa .net en lugar de php).

Solicitud

Si está escribiendo una aplicación, de repente, el tiempo de carga inicial no siempre es tan importante como el rendimiento continuo de la aplicación y comienza a pagar para cargar datos y códigos por separado.

Mi respuesta aquí explica cómo cargar datos usando AJAX en JavaScript:

function callback(data){
    // what do I do with the response?
}

var httpRequest = new XMLHttpRequest;
httpRequest.onreadystatechange = function(){
    if (httpRequest.readyState === 4) {// request is done
        if (httpRequest.status === 200) {// successfully
            callback(httpRequest.responseText);// we're calling our method
        }
    }
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();

O con jQuery:

$.get("/your/url").done(function(data){
    // what do I do with the data?
});

Ahora, el servidor solo necesita contener un /your/url ruta / archivo que contiene código que toma los datos y hace algo con ellos, en su caso:

<$php
 ...
 $val = myService->getValue(); // makes an api and db call
 echo json_encode($val); // write it to the output
 $>

De esta forma, nuestro archivo JS solicita los datos y los muestra en lugar de solicitar código o diseño. Esto es más limpio y comienza a pagar a medida que la aplicación aumenta. También es mejor separar las preocupaciones y permite probar el código del lado del cliente sin ninguna tecnología involucrada en el servidor, que es otra ventaja.

Posdata: Tienes que ser muy consciente de los vectores de ataque XSS cuando se inyecta algo desde PHP a JavaScript. Sus muy Es difícil escapar de los valores correctamente y es sensible al contexto. Si no está seguro de cómo lidiar con XSS o no lo sabe, lea este artículo de OWASP, éste y esta pregunta.


79
2018-05-19 15:02



Usualmente uso los atributos data- * en html.

<div class="service-container" data-service="<?php echo $myService->getValue(); ?>">

</div>

<script>
$(document).ready(function() {
    $('.service-container').each(function() {
        var container = $(this);
        var service = container.data('service');

        // service variable now contains the value of $myService->getValue();
    });
});
</script>

Este ejemplo usa jQuery pero puede ser adaptado para otra biblioteca o Javascript vainilla.

Puede leer más sobre la propiedad del conjunto de datos aquí: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset


69
2018-05-22 17:14



<script>
  var jsvar = <?php echo json_encode($PHPVar); ?>;
</script>

json_encode () requiere:

  • PHP 5.2.0 o más
  • $PHPVar codificado como UTF-8, Unicode.

32
2017-07-18 22:00



Simplemente use uno de los siguientes métodos.

<script type="text/javascript">
var js_variable  = '<?php echo $php_variable;?>';
<script>

O 

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

12
2018-04-13 18:59



Me gusta bastante la forma en que Wordpress funciona con su enqueue y localizar funciones, así que siguiendo ese modelo, escribí una clase simple para poner scripts en la página de acuerdo con las dependencias del script, y para hacer que los datos adicionales estén disponibles para el script.

class mHeader {

    private $scripts = array();

    /**
     * @param string $id        unique script identifier
     * @param string $src   script src attribute
     * @param array  $deps      an array of dependencies ( script identifiers ).
     * @param array  $data      an array, data that will be json_encoded and available to the script.
     */
    function enqueue_script( $id, $src, $deps = array(), $data = array() ) {
        $this->scripts[$id] = array( 'src' => $src, 'deps' => $deps, 'data' => $data );
    }

    private function dependencies( $script ) {
        if ( $script['deps'] ) {
            return array_map( array( $this, 'dependencies' ), array_intersect_key( $this->scripts, array_flip( $script['deps'] ) ) );
        }
    }

    private function _unset( $key, &$deps, &$out ) {
        $out[$key] = $this->scripts[$key];
        unset( $deps[$key] );
    }

    private function flattern( &$deps, &$out = array() ) {

        foreach( $deps as $key => $value ) {            
            empty($value) ? $this->_unset( $key, $deps, $out ) : $this->flattern( $deps[$key], $out );
        }
    }   

    function print_scripts() {

        if ( !$this->scripts ) return;

        $deps = array_map( array( $this, 'dependencies' ), $this->scripts );
        while ( $deps ) 
            $this->flattern( $deps, $js );

        foreach( $js as $key => $script ) {
            $script['data'] && printf( "<script> var %s = %s; </script>" . PHP_EOL, key( $script['data'] ), json_encode( current( $script['data'] ) ) );
            echo "<script id=\"$key-js\" src=\"$script[src]\" type=\"text/javascript\"></script>" . PHP_EOL;
        }
    }
}

Llamar a enqueue_script() La función es para agregar secuencias de comandos, establecer las fuentes y dependencias en otras secuencias de comandos y datos adicionales necesarios para la secuencia de comandos.

$header = new mHeader();

$header->enqueue_script( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js', array( 'jquery' ) );
$header->enqueue_script( 'jquery', '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js' );
$header->enqueue_script( 'custom-script', '//custom-script.min.js', array( 'jquery-ui' ), array( 'mydata' => array( 'value' => 20 ) ) );

$header->print_scripts();

Y, print_scripts() método del ejemplo anterior enviará este resultado:

<script id="jquery-js" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script id="jquery-ui-js" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js" type="text/javascript"></script>
<script> var mydata = {"value":20}; </script>
<script id="custom-script-js" src="//custom-script.min.js" type="text/javascript"></script>

Independientemente del hecho de que el guión 'jquery' esté en cola después de 'jquery-ui', se imprime antes porque está definido en 'jquery-ui' que depende de 'jquery'. Los datos adicionales para el 'script personalizado' están dentro de un nuevo bloque de script y se colocan delante de él, contiene mydata objeto que contiene datos adicionales, ahora disponible para 'custom-script'.


9
2017-10-29 20:24



myPlugin.start($val); // tried this, didn't work    

No funciona porque $val no está definido en lo que se refiere a javascript, es decir. el php no dio salida a nada por $val. Intenta ver la fuente en tu navegador y esto es lo que verás:

myPlugin.start(); // tried this, didn't work    

Y

<?php myPlugin.start($val); ?> // this didn't work either

Esto no funciona porque php intentará tratar myPlugin como una constante y cuando eso falla, tratará de tratarlo como la cadena 'myPlugin' que tratará de concatenar con el resultado de la función php start() y como eso no está definido, producirá un error fatal

Y

 myPlugin.start(<?=$val?> // this works sometimes, but sometimes it fails

Si bien esto es más probable que funcione, dado que el php está produciendo javascript válido con los argumentos esperados, si falla, es probable que sea porque myPlugin no está listo todavía Verifica tu orden de ejecución.

También debe tener en cuenta que el php out put es inseguro y debe ser filtrado con json_encode()

EDITAR 

Porque no noté el paréntesis faltante en myPlugin.start(<?=$val?> : - \

Como lo señala @Second Rikudo, para que funcione correctamente $val necesitaría contener el paréntesis de cierre, por ejemplo: $val="42);" 

Lo que significa que el php ahora producirá myPlugin.start(42); y funcionará como se esperaba cuando sea ejecutado por el javascript


7
2018-05-19 15:20



prueba esto

<?php
    echo "<script> var x = ". json_encode($phpVariable)."</script>";
?>

-

-Después de probar esto por un tiempo Aunque funciona, sin embargo, ralentiza el rendimiento. como php es un script del lado del servidor, mientras que javascript es del lado del usuario.


7
2017-09-02 10:04