如何将变量和数据从PHP传递到JavaScript?

我在PHP中有一个变量,我需要它的值在我的JavaScript代码中。如何将我的变量从PHP获取到JavaScript?

我有如下代码:

<?php
$val = $myService->getValue(); // Makes an API and database call

在同一页面上,我有JavaScript代码需要将$val变量的值作为参数传递:

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

实际上有几种方法可以做到这一点。有些比其他方法需要更多的开销,有些被认为比其他方法更好。

没有特别的顺序:

  1. 使用AJAX从服务器获取您需要的数据。
  2. 将数据回传到页面的某个地方,并使用JavaScript从DOM获取信息。
  3. 将数据直接回传到JavaScript。

在这篇文章中,我们将研究上述每种方法,并了解每种方法的优缺点,以及如何实现它们。

1.使用AJAX从服务器获取您需要的数据

这种方法被认为是最好的,因为您的服务器端和客户端脚本是完全独立的

优点

  • 更好的层间分离-如果明天您停止使用PHP,并希望迁移到servlet、REST API或其他服务,您不必更改太多JavaScript代码。
  • 更具可读性-JavaScript是JavaScript,PHP是PHP。在不混合两者的情况下,您可以在两种语言上获得更具可读性的代码。
  • 允许异步数据搬迁-从PHP获取信息可能会花费大量的时间和资源。有时您只是不想等待信息、加载页面并随时触达信息。
  • 数据不是直接在标记上找到的-这意味着您的标记不会包含任何其他数据,只有JavaScript才能看到它。

缺点

  • 延迟-AJAX创建一个HTTP请求,HTTP请求通过网络传输并具有网络延迟。
  • 国家-通过单独的HTTP请求获取的数据将不包括来自获取超文本标记语言文档的HTTP请求的任何信息。您可能需要此信息(例如,如果超文本标记语言文档是在响应表单提交时生成的),并且如果您需要此信息,则必须以某种方式将其传输。如果您排除了在页面中嵌入数据的可能性(如果您使用此技术,则可以使用cookie/会话),那么这可能会限制您受竞争条件的影响。

实现示例

使用AJAX,您需要两个页面,一个是PHP生成输出的地方,第二个是JavaScript获取输出的地方:

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 echo the result.
// All data should be json_encode()d.


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


index.php(或任何实际页面的名称)

<!-- 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 -->

当文件完成加载时,上述两个文件的组合将提醒42

更多阅读材料

2.将数据回声到页面的某个地方,并使用JavaScript从DOM获取信息

这种方法不如AJAX好,但它仍然有它的优点。从某种意义上说,JavaScript中没有直接的PHP,它仍然是PHP和JavaScript之间的相对分离。

优点

  • 快速-DOM操作通常很快,您可以相对快速地存储和访问大量数据。

缺点

  • 潜在非语义标记-通常情况下,发生的事情是您使用某种<input type=hidden>来存储信息,因为从inputNode.value中获取信息更容易,但这样做意味着您的超文本标记语言中有一个无意义的元素。超文本标记语言具有<meta>元素用于有关文档的数据,超文本标记语言5引入了data-*属性用于专门用于使用JavaScript读取的数据,这些数据可以与特定元素相关联。
  • 把源头弄脏-PHP生成的数据直接输出到超文本标记语言源,这意味着您可以获得更大、更少关注的超文本标记语言源。
  • 结构化数据必须是有效的超文本标记语言,否则你必须自己转义并转换字符串。
  • 将PHP与您的数据逻辑紧密耦合-因为PHP用于表示,所以您无法将两者完全分开。

实现示例

有了这个,我们的想法是创建某种不会显示给用户但对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.将数据直接回传到JavaScript

这可能是最容易理解的。

优点

  • 非常容易实现-实现和理解这一点需要很少的时间。
  • 不脏源-变量直接输出到JavaScript,因此DOM不受影响。

缺点

  • 将PHP与您的数据逻辑紧密耦合-因为PHP用于表示,所以您无法将两者完全分开。

实现示例

实现相对简单:

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

祝你好运!

我将尝试一个简单的答案:

问题的解释

首先,让我们了解从我们的服务器提供页面时的事件流程:

  • 首先运行PHP,它生成提供给客户端的超文本标记语言。
  • 然后,当超文本标记语言传递给客户端时,PHP“死亡”(即它实际上停止运行)。我想强调的是,一旦代码离开服务器,PHP就不再是页面负载的一部分,服务器再也无法访问它了。
  • 然后,当带有JavaScript的超文本标记语言到达客户端时,可以在该超文本标记语言上执行JavaScript,前提是它是有效的JavaScript。

所以真的,这里要记住的核心是HTTP是无状态的。一旦请求离开服务器,服务器就不能接触它。所以,这让我们的选择是:

  1. 从客户端发送更多请求之后初始请求完成。
  2. 编码服务器在初始请求中必须说的话。

解决方案

你应该问自己的核心问题是:

我是在写一个网站还是一个应用程序?

网站主要是基于页面的,页面加载时间需要尽可能快(例如-Wikipedia)。Web应用程序更重于AJAX,并执行大量往返以快速获取客户端信息(例如-股票仪表板)。

网站

在初始请求完成后从客户端发送更多请求是缓慢,因为它需要更多具有显着开销的HTTP请求。此外,它需要异步,因为发出AJAX请求需要处理程序来完成它。

我建议没有再次请求除非您的网站是应用程序从服务器获取该信息。

您想要快速的响应时间,这对转换和加载时间有巨大影响。在这种情况下,发出Ajax请求的初始正常运行时间很慢,并且不需要。

你有两种方法来解决这个问题

  • 设置cookie-cookie是在HTTP请求中发送的标头,服务器和客户端都可以读取。
  • 将变量编码为JSON-JSON看起来非常接近JavaScript对象,大多数 JSON对象是有效的JavaScript变量。

设置cookie真的不是很难,你只需给它赋值:

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

然后,您可以使用document.cookie用JavaScript阅读

这是一个简短的手滚解析器,但我在上面链接的答案有更好的测试:

var cookies = document.cookie.split(";").
map(function(el){ return el.split("="); }).
reduce(function(prev,cur){ prev[cur[0]] = cur[1]; return prev },{});
alert(cookies["MyCookie"]); // Value set with PHP.

Cookie对少量数据有好处。这就是跟踪服务经常做的事情。

一旦我们有了更多的数据,我们可以在JavaScript变量中使用JSON对其进行编码:

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

假设$value在PHP端是json_encodeable(通常是)。例如,这种技术就是Stack Overflow对其聊天所做的(仅使用. NET而不是PHP)。

申请方式

如果您正在编写应用程序-突然之间,初始加载时间并不总是与应用程序的持续性能一样重要,并且开始单独加载数据和代码。

我的答案这里解释了如何在JavaScript中使用AJAX加载数据:

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();

或者使用jQuery:

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

现在,服务器只需要包含一个/your/url路由/文件,其中包含获取数据并对其执行某些操作的代码,在您的情况下:

<?php
$val = myService->getValue(); // Makes an API and database call
header("Content-Type: application/json"); // Advise client of response type
echo json_encode($val); // Write it to the output

通过这种方式,我们的JavaScript文件要求数据并显示它,而不是要求代码或布局。这更干净,并且随着应用程序变得更高而开始获得回报。它也更好地分离了关注点,并且它允许测试客户端代码,而不涉及任何服务器端技术,这是另一个优点。

后记:当您注入从PHP到JavaScript的任何内容时,您必须非常知道XSS攻击向量。非常很难正确转义值,并且它是上下文敏感的。如果您不确定如何处理XSS,或者不知道它-请阅读这篇OWASP文章这一个这个问题

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

它不起作用,因为就JavaScript而言,$val是未定义的,即PHP代码没有为$val输出任何内容。尝试在浏览器中查看源代码,以下是您将看到的:

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

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

这不起作用,因为PHP将尝试将myPlugin视为常量,当失败时,它将尝试将其视为字符串'myPlugin',它将尝试与PHP函数start()的输出连接,因为这是未定义的,它将产生致命错误。

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

虽然这很可能有效,但由于PHP代码正在生成具有预期参数的有效JavaScript,如果失败,很可能是因为myPlugin还没有准备好。检查您的执行顺序。

您还应该注意PHP代码输出是不安全的,应该使用json_encode()过滤。

编辑

因为我没有注意到myPlugin.start(<?=$val?>中缺少括号:-\

正如@Two Rikudo所指出的,为了使其正常工作,$val需要包含右括号,例如:$val="42);"

这意味着PHP现在将生成myPlugin.start(42);,并在JavaScript代码执行时按预期工作。

我通常在超文本标记语言中使用data-*属性。

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


</div>


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


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

此示例使用jQuery,但它可以适用于其他库或vanilla JavaScript。

您可以在此处阅读有关数据集属性的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset

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

json_encode()要求:

  • PHP 5.2.0或更高版本
  • $PHPVar编码为UTF-8,Unicode。

试试这个:

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

--

-在尝试了一段时间之后

虽然它可以工作,但它会减慢性能。因为PHP是服务器端脚本,而JavaScript是用户端。

我非常喜欢WordPress的入队本地化函数的工作方式,因此遵循该模型,我编写了一个简单的类,用于根据脚本依赖项将脚本放入页面,并为脚本提供额外的数据。

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;
}
}
}

enqueue_script()函数的调用用于添加脚本、设置其他脚本的源和依赖关系以及脚本所需的其他数据。

$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();

并且,上面示例的print_scripts()方法将发送以下输出:

<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>

不管脚本'jQuery'在'jquery-用户界面'之后排队,它被打印之前,因为它在'jQuery-用户界面'中定义它依赖于'jQuery'。 “自定义脚本”的附加数据位于新脚本块中并放置在其前面,它包含mydata对象,该对象包含附加数据,现在可用于“自定义脚本”。

我想出了一个简单的方法来使用PHP分配JavaScript变量。

它使用HTML5数据属性来存储PHP变量,然后在页面加载时将其分配给JavaScript。

示例:

<?php
$variable_1 = "QNimate";
$variable_2 = "QScutter";
?>
<span id="storage" data-variable-one="<?php echo $variable_1; ?>" data-variable-two="<?php echo $variable_2; ?>"></span>
<?php

这是JavaScript代码

var variable_1 = undefined;
var variable_2 = undefined;


window.onload = function(){
variable_1 = document.getElementById("storage").getAttribute("data-variable-one");
variable_2 = document.getElementById("storage").getAttribute("data-variable-two");
}

只需使用以下方法之一。

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

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

根据你的代码

<$php
$val = $myService->getValue(); // Makes an API and database call
echo '<span id="value">'.$val.'</span>';
$>

现在您可以使用DOM获取值,使用跨度id的innerHTML,在这种情况下,您不需要对服务器、Ajax或其他东西进行任何调用。

您的页面将使用PHP打印它,您的JavaScript将使用DOM获取值。

我假设要传输的数据是一个字符串。

正如其他评论者所说,AJAX是一种可能的解决方案,但弊大于利:它有延迟,并且更难编程(它需要代码来检索服务器端和客户端的值),当一个更简单的转义函数就足够了。

所以,我们回到转义。json_encode($string) works如果你首先将源字符串编码为UTF-8,以防它还没有,因为json_encode需要UTF-8数据。如果字符串是ISO-8859-1,那么你可以简单地使用json_encode(utf8_encode($string));否则你可以始终使用iconv先进行转换。

但是有一个很大的问题。如果你在事件中使用它,你需要对结果运行htmlspecialchars()才能使其成为正确的代码。然后你必须小心使用双引号来括住事件,或者总是将ENT_QUOTES添加到html特别字符中。例如:

<?php
$myvar = "I'm in \"UTF-8\" encoding and I have <script>script tags</script> & ampersand!";
// Fails:
//echo '<body onload="alert(', json_encode($myvar), ');">';
// Fails:
//echo "<body onload='alert(", json_encode($myvar), ");'>";
// Fails:
//echo "<body onload='alert(", htmlspecialchars(json_encode($myvar)), ");'>";


// Works:
//echo "<body onload='alert(", htmlspecialchars(json_encode($myvar), ENT_QUOTES), ");'>";
// Works:
echo '<body onload="alert(', htmlspecialchars(json_encode($myvar)), ');">';


echo "</body>";

但是,您不能在常规JavaScript代码(包含在<script></script>标签中的代码)上使用htmlspecialchars。这使得使用此函数容易出错,因为在编写事件代码时忘记了htmlspecialchars结果。

可以编写一个没有这个问题的函数,并且可以在事件和常规JavaScript代码中使用,只要您始终将事件用单引号括起来,或者始终用双引号。这是我的建议,要求它们用双引号(我更喜欢):

<?php
// Optionally pass the encoding of the source string, if not UTF-8
function escapeJSString($string, $encoding = 'UTF-8')
{
if ($encoding != 'UTF-8')
$string = iconv($encoding, 'UTF-8', $string);
$flags = JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_UNESCAPED_SLASHES;
$string = substr(json_encode($string, $flags), 1, -1);
return "'$string'";
}

该函数需要PHP 5.4+。示例用法:

<?php
$myvar = "I'm in \"UTF-8\" encoding and I have <script>script tags</script> & ampersand!";
// Note use of double quotes to enclose the event definition!
echo '<body onload="alert(', escapeJSString($myvar), ');">';
// Example with regular code:
echo '<script>alert(', escapeJSString($myvar), ');</script>';
echo '</body>';

这就是诀窍:

  1. 这是使用该变量的“PHP”

    <?php
    $name = 'PHP variable';
    echo '<script>';
    echo 'var name = ' . json_encode($name) . ';';
    echo '</script>';
    ?>
    
  2. Now you have a JavaScript variable called 'name', and here is your JavaScript code to use that variable:

    <script>
    console.log("I am everywhere " + name);
    </script>
    

假设您的变量始终是整数。在这种情况下,这更容易:

<?PHP
$number = 4;


echo '<script>';
echo 'var number = ' . $number . ';';
echo 'alert(number);';
echo '</script>';
?>

产出

<script>var number = 4;alert(number);</script>

假设你的变量不是整数,但如果你尝试上面的方法,你会得到这样的东西:

<script>var number = abcd;alert(number);</script>

但在JavaScript中,这是一个语法错误。

所以在PHP中,我们有一个函数调用json_encode,它将字符串编码为JSON对象。

<?PHP
$number = 'abcd';


echo '<script>';
echo 'var number = ' . json_encode($number) . ';';
echo 'alert(number);';
echo '</script>';
?>

由于JSON中的abcd"abcd",它看起来像这样:

<script>var number = "abcd";alert(number);</script>

您可以对数组使用相同的方法:

<?PHP
$details = [
'name' => 'supun',
'age' => 456,
'weight' => '55'
];


echo '<script>';
echo 'var details = ' . json_encode($details) . ';';
echo 'alert(details);';
echo 'console.log(details);';
echo '</script>';
?>

你的JavaScript代码看起来像这样:

<script>var details = {"name":"supun","age":456,"weight":"55"};alert(details);console.log(details);</script>

控制台输出

在此输入图片描述

  1. 将数据转换为JSON
  2. 调用AJAX接收JSON文件
  3. JSON转换为javascript对象

示例:

STEP 1

<?php


$servername = "localhost";
$username = "";
$password = "";
$dbname = "";
$conn = new mysqli($servername, $username, $password, $dbname);


if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}


$sql = "SELECT id, name, image FROM phone";
$result = $conn->query($sql);


while($row = $result->fetch_assoc()){
$v[] = $row;
}


echo json_encode($v);


$conn->close();
?>

STEP 2

function showUser(fnc) {
var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// STEP 3
var p = JSON.parse(this.responseText);
}
}
}

经过大量研究,我发现最简单的方法是轻松传递各种变量。

在服务器脚本中,您有两个变量,您正在尝试将它们发送到客户端脚本:

$php_var1 ="Hello world";
$php_var2 ="Helloow";
echo '<script>';
echo 'var js_variable1= ' . json_encode($php_var1) . ';';
echo 'var js_variable2= ' . json_encode($php_var2) . ';';
echo '</script>';

在页面上调用的任何JavaScript代码中,只需调用这些变量。

<?php


$val = $myService->getValue(); // Makes an API and database call


echo "
<script>
myPlugin.start({$val});
</script> ";


?>

php

$fruits = array("apple" => "yellow", "strawberry" => "red", "kiwi" => "green");
<script>
var color = <?php echo json_encode($fruits) ?>;
</script>
<script src="../yourexternal.js"></script>

JS(yourexternal.js)

alert("The apple color is" + color['apple'] + ", the strawberry color is " + color['strawberry'] + " and the kiwi color is " + color['kiwi'] + ".");

输出

苹果的颜色是黄色的,草莓的颜色是红色的,猕猴桃 颜色是绿色的。

我们可以使用phpheldoc

<?php
    

$inPhpVar = "i am php var";


$ScriptInline = <<<JS
<script>
alert('{$inPhpVar} that used in js code');
</script>
JS;


echo $ScriptInline;


?>

如果您需要在脚本中获取一些重要数据,这些数据在php中可用,您可以在需要数据的脚本之前自动回显一个完整的脚本,并使用一些包含该信息的全局变量。

在您的html上的scurpt导入中:

<?php
echo "<script>
const importantData = ".$php_data.";
</script>";
?>
<script src="../assets/js/your_script.js"></script>

因此,您可以通过名为“重要数据”的const从your_script.js访问该信息

这是我在2022年的工作方式,我使用此解决方案获取当前用户的电子邮件

我使用PHP创建了一个短代码并将其添加到PHP. function:

function my_get_current_user_email(){
$current_user = wp_get_current_user();
$email = $current_user->user_email;
return $email;
}
add_shortcode( 'get_email', 'my_get_current_user_email');

然后使用div包装短代码:

 <div id="target-content" style="display: none;">
[get_email]
</div>

最后,使用JavaScript访问Div的内容:

const databox = document.getElementById("target-content");
const dataContent = databox.textContent;
console.log(dataContent)

这完全符合我想要的,我希望它也能为你工作。