高效传递变量从PHP到JavaScript的方法

24

有时我需要从PHP传递一些变量到JS脚本中。 目前我是这样做的:

var js-variable = "<?php echo $php-variable; ?>";

但这很丑陋,我也无法将我的JS脚本隐藏在.js文件中,因为它必须由PHP解析。处理这个问题的最佳方案是什么?


1
我希望这只是一个例子,var js-variable会生成语法错误,同样$php-variable也会。 - MaxArt
在 PHP 变量中使用双引号时要小心。 - Jeroen
8个回答

35

如果你不想使用PHP来生成你的JavaScript(并且不介意对web服务器进行额外调用),则使用AJAX获取数据。

如果你想要使用PHP,则在输出之前始终使用json_encode进行编码。

<script>
    var myvar = <?php echo json_encode($myVarValue); ?>;
</script>

+1 JSON是使用PHP脚本中的数据的最佳方式,无论是通过ajax还是与页面同时编译。 - Joseph
7
警告:这可能会破坏你的网站。例如:<?php $myVarValue = '<!--<script>'; ?>。请参考此问题以获取详细信息。解决方案:使用JSON_HEX_TAG来转义<>(需要PHP 5.3.0)。 - Pang
另一个缺点是它会影响初始页面加载时间。 - biplav
@Pang和biplav,你们能否更具体一些呢?https://dev59.com/xYHba4cB1Zd3GeqPUrPa - Yatko
@biplav - 这会对性能产生什么影响?在什么情况下?谢谢! - Yatko
@Yatko:在 Apache 将页面提供给浏览器之前,此输出将被计算。假设 $myVarValue 是通过执行需要 500 毫秒的查询来计算的。这将使初始页面加载延迟 500 毫秒。另一个缺点是,与 API/REST 驱动方法相比,测试此查询将更加困难。从可测试性和用户体验的角度来看,REST 驱动方法更好。可以轻松地加载整个页面并显示使用此变量的页面部分的加载符号,然后进行 AJAX 调用以加载该部分并构建页面。 - biplav

8
<?php
// filename: output-json.php
header('content-type:application/json;charset=utf-8');
printf('var foo = %s;', json_encode($foo, JSON_PRETTY_PRINT));
json_encode是一个强大的函数,可以确保输出以有效的Javascript/JSON编码和格式化。内容类型标头告诉浏览器如何解释响应。
如果您的响应确实是JSON,例如:
{"foo": 5}

然后将其声明为content-type:application/json;charset=utf-8。与JavaScript相比,JSON更容易解析,并且被XSS攻击的可能性要小得多。但是,如果您需要在响应中使用真正的JavaScript,例如:

var obj = {foo: 5};

然后将其声明为content-type:text/javascript;charset=utf-8

您可以像链接文件一样链接它:

<script src="output-json.php"></script>

作为替代,将值直接嵌入你的HTML中而不是进行独立的HTTP请求可能更加方便。可以这样做:

<script>
    <?php printf('var foo = %s;', json_encode($foo, JSON_HEX_TAG | JSON_PRETTY_PRINT)) ?>
</script>

请确保在通过<script>标签嵌入html时使用JSON_HEX_TAG,否则会存在xss注入攻击的风险。根据您使用的上下文,还可能需要使用其他标志以获得更多安全性:JSON_HEX_AMP, JSON_HEX_QUOT, JSON_HEX_APOS。这些标志使响应不太易读,但通常对安全性和兼容性有好处,因此您应该尽量使用它们。
我真的想强调声明内容类型和可能使用JSON_HEX_TAG标志的重要性,因为它们都可以帮助减轻xss注入的影响。
除非您希望引发xss攻击,请不要这样做:
<script>
    var myvar = <?php echo json_encode($myVarValue); ?>;
</script>

8
请使用rest/rpc api并将json传递给您的js。如果您正在使用jquery,可以按以下方式完成:
rest.php
<?php echo "{name:biplav}" ?>

然后在你的js中进行如下get请求:
var js_var;
$.get("rest.php", function(data) {
         js_var=data;
});

这是我能想到的最简单的例子。

+1 从服务器检索变量最好使用服务调用来表示。 - RustyTheBoyRobot

3
在我看来,如果你需要直接在JS中传递变量,那么你的Web应用程序可能不是很好设计。
所以,我有两个建议: * 使用JSON文件进行常规配置,例如/js/conf/userprefs.json
{
    "avatar": "/img/users/123/avatar.jpg",
    "preferred_color": "blue"
    // ...
}
  • 或者(更好的方法)您可以通过AJAX调用检索JSON配置文件。

使用像Symfony2这样的PHP框架,您可以在路由配置中决定格式,并将变量的输出留给模板引擎(如Twig)。

我为Symfony2用户提供一个示例,但任何程序员都可以使用:

routing.yml

userprefs:
    pattern: /js/confs/userprefs.{_format}
    defaults: { _controller: CoreBundle:JsonPrefs:User, _format: json }
    requirements:
        _format: json
        _method: GET

在控制器内部,您可以执行所有需要检索变量的查询,并将其放入视图中:

资源/视图/JsonPrefs/User.json

{
    "avatar": "{{ user.avatar }}",
    "preferred_color": "{{ user.preferred_color }}"
    // ...
}

现在你可以通过简单的 AJAX 调用在 JS 中检索 JSON。为了提高性能,你可以使用 Varnish 缓存 JSON(例如)。这样,每次读取用户偏好时,你的服务器就不需要进行查询。


2
如果您修改了您的`.htaccess`文件以包含以下内容:
 AddType application/x-httpd-php .js

您可以使用 .js 文件,并且它将由 PHP 处理,这是您需要的一半。

就该解决方案有多难看而言,我会说这是最不难看的机制。您可以尝试将整个 JS 脚本作为字符串通过 PHP 脚本传递,并进行搜索和替换以插入所需的变量,但我认为您会同意这比您目前正在使用的解决方案更加丑陋。


2
将所有的.js文件放在一个文件夹中,并配置您的HTTP服务器将所有请求重定向到这些文件,以便一个PHP文件可以加载这些文件并输出它们。
假设您使用的是Apache服务器,您的.js文件位于/js目录下:
RewriteRule /js   /getjs.php

getjs.php:

<?php
header('Content-Type: text/javascript');
include_once($_SERVER['SCRIPT_NAME']);
?>

1

就避免将 .js 文件通过 PHP 解析器运行而言,除了可能通过 AJAX 调用获取 js-variable 的值之外,你几乎无能为力。

此外,你可以考虑这样输出该值:

var js_variable = <?php echo json_encode ($php_variable); ?>

为了避免所有可能破坏你的JavaScript的事情。


0

至少,您可以使用PHP短代码使您的“丑陋”解决方案更加清晰:

var js-variable = "<?= $php-variable ?>";

1
我不是那个给你点踩的人,但短代码存在可移植性问题,因此应该避免使用。 - Stephane Gosselin
当你把PHP看作是模板引擎时,它并不难看。然而,如果他能用Ajax解决这个问题,那就更好了,我同意。 - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接