在您的JavaScript中使用PHP是否被视为不良做法


55

在这个网站上,有很多次我看到有人试图做这样的事情:

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

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

  });
</script>

我认为这不是人们自然会陷入的某种模式。必须有某种形式的教程或学习材料来说明这一点,否则我们不会看到太多。我要问的是,我在这方面做得太大了吗,或者这真的是不好的做法吗?

编辑: 正在和我的一个朋友谈论这件事,他经常在他的JavaScript中放入红宝石,他提出了这一点。

是否可以在JavaScript中动态放置应用程序范围的常量,这样就不必编辑两个文件。例如...

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

还可以直接对计划在库中使用的数据进行编码

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

还是我们应该每次都拨打AJAX?


4
在我看来this question will likely solicit opinion, debate, arguments, polling, or extended discussion.……
DaveRandom 2011年

7
@ M.Babcock这将是.php文件的一部分,因此php代码将在服务器端执行,并且客户端只能看到回显的结果。

8
任何创建动态生成的JavaScript的人都会被撤回并受到处理
-Raynos

5
@马特然后我会拿谷歌退出回来,对付他们
Raynos

4
“您在我的PHP中获得了JavaScript!” “不,您在我的 JavaScript中获得了PHP !”
乔什·达内尔

Answers:


83

通常,使用X语言生成Y语言代码是一种不好的做法。

尝试通过使数据成为它们的唯一接口来分离这两种语言-不要混杂代码

在您的示例中,您可以通过使用PHP填充cfgJavaScript可用的结构来改进代码:

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

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

这样,PHP只关心填充数据结构,而JavaScript只关心消耗数据结构。

这种解耦还引导了将来异步加载数据(JSON)的方式。

更新:

要回答您在更新中提出的其他问题,可以的,应用DRY原理并让PHP和JavaScript共享同一配置对象是一个很好的做法:

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

  ...

像这样将配置的JSON表示直接插入到页面中没有什么害处。您不必一定要通过XHR来获取它。


21
记住不要将MySQL密码放在$ cfg中!!
Thomas Bonini 2011年

13
“将数据作为唯一的界面-不要混杂代码。” 我认为这确实切入了问题的核心,并且在同时使用任何两种语言时都是很好的经验法则。感谢您的见解。
格雷格·吉达

6
您还可以data-在HTML 的属性中包含该JSON 。有点像<body data-cfg="{...}">
卡帕

1
@bazmegakapa我认为这可能是最好的选择。特别是,它允许使用诸如HTML DOM之类的API,这些API可以大大降低XSS注入的风险。
luiscubal 2011年

1
+1,用于建议使用数据作为接口并阻止生成代码的代码。
布兰登

21

动态生成的JavaScript是一种糟糕的坏习惯。

您应该做的就是理解“关注分离和逐步增强”的含义。

这基本上意味着您拥有动态HTML和静态JavaScript(可增强HTML)。

在您的情况下,您可能希望在div上使用一个类,然后使用类选择器进行选择


10

您的代码段最大的问题是您缺少#使它成为有效的jQuery选择器的;)。

我会说,您应该尽可能避免在JavaScript中包含PHP。将click()处理程序中的选择器更改为一个类,然后将类添加到有问题的元素中,如果要触发该处理程序,如果不希望则不行,这是怎么回事?

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

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

  });
</script> 

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

某些情况下,您需要在JavaScript中包含PHP。但我必须承认,这些之间相距甚远。

一个例子是当您具有不同的环境时;测试,演出和现场直播。他们每个人都有不同的资产位置(主要是图片)。设置路径以使其可以被JavaScript使用的最简单方法是:

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

在我虚构的php代码的其余部分中,我已经添加了#=),但认真的我同意,您的榜样是做到这一点的更好方法。对我来说,这样做也是很自然的。那么,为什么我们在不必要的地方如此频繁地看到它呢?
格雷格·吉达

请注意,通过以相同的方式设置环境,可以轻松避免在配置文件中回显静态数据。
雷诺斯2011年

4
@GregGuida:我的猜测是程序员很少像处理Web开发那样习惯于处理客户机/服务器体系结构。他们将DB <-> PHP <-> HTML / JS / CSS视为一体,并且不完全了解应该去哪里以及如何分隔各层。
马特

@Matt我认为这可能是最好的解释
Greg Guida

2
$divID = '#' . $element_id_value;-选择器头没有问题;)
rlemon 2011年

8

在我看来,这是一个不好的做法,因为您需要将此文件命名为something.php,然后您无法对其进行压缩,例如,不提及将服务器中的内容与JavaScript混合是不行的。尽量限制PHP和JS之间的混合。

您可以始终这样做:

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

然后,您可以在php文件中调用此函数,以使这些混合内容尽可能小。

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

通过这样做(拥有更大的JS文件,没有关系的2-3行),您可以利用压缩JS文件的优势,并且前端开发人员在我看来仅使用JavaScript感到非常自在(因为您可以编写Python,Ruby等不仅是PHP,而且代码可能会越来越大,具体取决于您在那做的事情。


2
完全同意,顺便说一句,我从未将PHP放入我的JS中。我一直在这个网站上看到它。
格雷格·吉达

php代码永远不会进入浏览器!只是评估的代码,现在应该是纯JavaScript。因此,文件大小/压缩不是问题。还是不好的练习思想!
James Anderson

@JamesAnderson我认为alessioalex指的是缩小(如Uglify)。可能需要运行php,然后让后处理php函数解析响应,识别脚本标签,通过Uglify运行它,并在发送响应之前用最小化版本替换原始php生成的JS,但是,在每个请求上执行此操作听起来都像是在说!方法。
jinglesthula

6

我认为这不是坏习惯。如果您的JavaScript中所需的ID是动态的,则没有其他方法可以执行此操作。


5
为什么用鬼怪的名字不知道ID标签的名称?
隐身

3
@Incognito,很多时候您都不知道ID ...如果您使用Ajax生成新的代码块,则可能会生成唯一的ID和新的JS ...在这种情况下,您需要确保在引用中的ID在js中是相同的,因为它们在结果代码块中。还有更多这样的实例,当涉及到ajax或有大量依赖于服务器端if-else语句等的代码块时,这很常见

7
@raynjamin我什至不了解您如何将自己置于正在做的事情中……或者为什么要按类别进行选择,然后列出标签,然后选择具有隐藏css值的ID属性,那个选择器人……实际上让我痛苦的是……我什至不知道从哪里开始……像什么?您是要剪切+粘贴大量代码块还是要使事情在多个ID上起作用?我什至不...喜欢...我的大脑。它在这里爆炸。
隐身

3
阅读有关dom / html /任何内容的信息...使用搜索引擎...为什么我从来没有用动态HTML做过这样的事情?
隐身

5
没有。您不了解ID标签的工作原理。我完全理解您的意思。
隐身

6

我会认为这是不好的做法。将动态内容放入脚本块中时,您始终必须意识到以下事实:在javascript上下文中转义并不像您希望的那么简单。如果值分别为用户提供的,它是足够的HTML转义它们。

OWASP XSS的小抄有更多的细节,但基本上你应该采取这种模式:

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

然后在与您的主要html链接的单独的.js文件中,加载以下代码:

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

使用单独的.js文件的原因有两个:

  • 它是可缓存的,因此性能更好
  • HTML解析器不会被触发,因此没有人将快速<?php标记放在某处的情况下会漏掉XSS错误的风险

+1可充分说明XSS角度!您的方法将加载得更快,因为json是在domready之前加载的,但是我更喜欢使用$.ajax或类似方法进行自动json解析
roo2 2014年

5

有人会认为这是不好的做法。不是因为它是JS内的PHP,而是因为它是内联JS,因此不会被浏览器缓存以方便下次加载。

IMO总是最好使用JSON在两种语言之间传递变量,但是我想这取决于您。


5

我会说一般不要这样做。但是,如果您想从PHP-> Javascript传递数据,那么拥有一个内联Javascript块(其中的代码格式如下)不会令我发疯。这里的代码只是将数据从php传递到javascript,而不是即时创建逻辑等。与ajax调用相比,这样做的好处在于,页面加载后即可立即使用数据,并且不需要进行额外的服务器访问。

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

当然,另一个选择是通过某种形式的构建脚本从PHP构建javascript配置文件,该脚本会将其放入.js文件中。


4

我能想到的唯一真正会导致问题的事情是,何时设置要显示PHP错误,因此它将大量的HTML错误显示为JavaScript错误。

同样因为它在脚本中没有显示,所以有时可能需要一段时间才能意识到脚本为什么损坏。


这会导致很大的错误的好例子
Greg Guida

3

这取决于谁,如果您问我,是的,出于某些原因,我确实考虑将其重新使用。首先,我更希望在自己的JS文件中包含javascript分析器无法触摸的javascript代码。

其次,php仅在服务器时间执行,因此,如果您依靠php中的某个变量来更改JavaScript,则可能效果不佳。如果要使用javascript控制某些页面加载设置,我通常更喜欢使用php将其添加到DOM中,以便javascript可以在需要时(例如在一个隐藏的div中)到达它。

最后,仅出于组织目的,这可能会很烦人。混合html和php已经很糟糕了(在我看来)。


1

将PHP包含到config数据对象中的方式有​​90%的使用方法,但是最佳实践是将其完全分离。您可以使用RESTful api仅请求所需的数据,它是使用JavaScript编写的,但具有一些优点。

  • 脚本是静态的,可以永久缓存
  • PHP不再是XSS向量
  • 完全分离关注点

缺点:

  • 需要额外的HTTP请求
  • 更复杂的javascript

脚本

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

仅当用于JavaScript代码初始化时,这不是一个坏习惯,(在我的WordPress主题中,我使用php_site(url)这样的php函数初始化了我的javascript对象,因为这是处理该问题的唯一方法(也许我们可以使用ajax请求来获取一个json,等等……但这实在是太痛苦了)。

良好做法:

新的javascriptObject(“”);

不良做法:

/ *一些代码* / document.get_element_by_id(); / *一些代码* /
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.