Được coi là thực hành xấu khi có PHP trong JavaScript của bạn


55

Vì vậy, nhiều lần trên trang web này, tôi thấy mọi người đang cố gắng làm những việc như thế này:

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

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

  });
</script>

Tôi không nghĩ rằng đây là một kiểu mẫu mà mọi người tự nhiên rơi vào. Phải có một số loại hướng dẫn hoặc tài liệu học tập ngoài kia đang thể hiện điều này, nếu không chúng ta sẽ không thấy nó nhiều. Những gì tôi đang hỏi là, tôi đang thực hiện quá nhiều vấn đề này hay đây là một thực tế tồi tệ?

EDIT: Đã nói chuyện với một người bạn của tôi về điều này, người thường đưa ruby ​​vào JavaScript của anh ấy và anh ấy đã đưa ra quan điểm này.

Bạn có thể tự động đặt các hằng số ứng dụng rộng rãi trong JavaScript của mình để bạn không phải chỉnh sửa hai tệp. ví dụ...

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

cũng có thể mã hóa trực tiếp dữ liệu bạn dự định sử dụng trong thư viện

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

hay chúng ta nên thực hiện cuộc gọi AJAX mỗi lần?


4
Dường như với tôi rằng this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom

7
@ M.Babcock Đây sẽ là một phần của tệp .php, do đó mã php sẽ được thực thi phía máy chủ và máy khách sẽ chỉ nhìn thấy kết quả của tiếng vang.

8
Bất cứ ai tạo JavaScript được tạo động đều bị gỡ bỏ và bị xử lý
Raynos

5
@Matt sau đó tôi sẽ lấy lại google và giao dịch với họ
Raynos

4
"Bạn đã có javascript của bạn trong PHP của tôi!" "Không, bạn đã có PHP của bạn trong javascript của tôi !"
Josh Darnell

Câu trả lời:


83

Thông thường, nó xấu thực hành để sử dụng ngôn ngữ X để tạo ra mã trong Y. ngôn ngữ

Hãy thử tách hai ngôn ngữ bằng cách tạo dữ liệu cho giao diện duy nhất của chúng - không trộn lẫn .

Trong ví dụ của bạn, bạn có thể cải thiện mã bằng cách sử dụng PHP để điền vào cfgcấu trúc có sẵn cho JavaScript:

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

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

Theo cách này, PHP chỉ quan tâm đến việc phổ biến cấu trúc dữ liệu và JavaScript chỉ quan tâm đến việc tiêu thụ cấu trúc dữ liệu.

Việc tách rời này cũng dẫn đến cách tải dữ liệu không đồng bộ (JSON) trong tương lai.

Cập nhật:

Để trả lời các câu hỏi bổ sung mà bạn đã hỏi với bản cập nhật của mình, vâng, sẽ là một cách thực hành tốt khi áp dụng nguyên tắc DRY và để PHP và JavaScript chia sẻ cùng một đối tượng cấu hình:

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

  ...

Không có hại trong việc chèn đại diện JSON của cấu hình của bạn trực tiếp vào trang của bạn như thế này. Bạn không nhất thiết phải tìm nạp nó qua XHR.


21
Hãy nhớ đừng đặt mật khẩu MySQL của bạn vào $ cfg !!
Thomas Bonini

13
"làm cho dữ liệu giao diện duy nhất của họ - không trộn lẫn mã." Tôi nghĩ rằng điều này thực sự cắt giảm cốt lõi của vấn đề và là một quy tắc tốt khi sử dụng BẤT K Two hai ngôn ngữ với nhau. Cảm ơn vì sự sáng suốt.
Greg Guida

6
Bạn cũng có thể bao gồm JSON đó trong một data-thuộc tính trong HTML của mình. Một cái gì đó như <body data-cfg="{...}">.
kapa

1
@bazmegakapa Tôi nghĩ rằng đó có thể là lựa chọn tốt nhất. Đặc biệt, nó cho phép sử dụng các API như HTML DOM giúp giảm đáng kể nguy cơ tiêm XSS.
luiscubal

1
+1 để đề xuất sử dụng dữ liệu làm giao diện và mã không khuyến khích tạo mã.
Brandon ngày

21

JavaScript được tạo động là một cách thực hành tồi tệ.

Những gì bạn cần làm là hiểu được ý nghĩa của các mối quan tâm và tăng cường tiến bộ có nghĩa là gì.

Điều này về cơ bản có nghĩa là bạn có HTML động và JavaScript tĩnh (giúp tăng cường HTML).

Trong trường hợp của bạn, bạn có thể muốn một lớp trên div của mình và chọn nó với bộ chọn lớp


10

Vấn đề lớn nhất với đoạn mã của bạn là bạn đang thiếu #để biến nó thành một bộ chọn jQuery hợp lệ;).

Tôi muốn nói rằng bạn nên cố gắng tránh đưa PHP vào JavaScript nếu có thể. Có gì sai khi thay đổi bộ chọn trong click()trình xử lý của bạn thành một lớp và thêm lớp vào thành phần được đề cập nếu bạn muốn trình xử lý bị loại bỏ, và nếu không thì không;

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

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

  });
</script> 

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

những trường hợp bạn cần đưa PHP vào JavaScript của mình; nhưng tôi phải thừa nhận những điều này là rất ít.

Một lần ví dụ là khi bạn có môi trường khác nhau; kiểm tra, dàn dựng và sống. Mỗi người trong số họ có một vị trí khác nhau của tài sản của bạn (hình ảnh, chủ yếu). Cách dễ nhất để đặt đường dẫn để JavaScript có thể sử dụng nó là một cái gì đó như;

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

Trong phần còn lại của mã php tưởng tượng của tôi, tôi đã thêm vào #=) nhưng nghiêm túc tôi đồng ý rằng ví dụ của bạn là cách tốt hơn để làm điều đó. Nó có vẻ tự nhiên hơn đối với tôi để làm điều đó quá. Vậy tại sao chúng ta lại thấy nó thường xuyên ở những nơi không cần thiết?
Greg Guida

Lưu ý rằng có thể tránh được việc lặp lại dữ liệu tĩnh trong tệp cấu hình bằng cách tất cả các môi trường của bạn được thiết lập theo cùng một cách.
Raynos

4
@GregGuida: Tôi đoán rằng các lập trình viên hiếm khi được sử dụng để xử lý các kiến ​​trúc máy khách / máy chủ như bạn có được trong quá trình phát triển web. Họ coi DB <-> PHP <-> HTML / JS / CSS là một và không hiểu đầy đủ những gì nên đi đâu và làm thế nào để tách các lớp.
Matt

@Matt Tôi nghĩ rằng đó có lẽ là lời giải thích tốt nhất
Greg Guida

2
$divID = '#' . $element_id_value;- không có vấn đề gì với ông chủ của bộ chọn;)
rlemon

8

Theo quan điểm của tôi, đây là một thực tiễn tồi, vì bạn sẽ cần phải gọi tệp này là.php. Sau đó, bạn không thể nén nó, không đề cập đến việc trộn lẫn nội dung máy chủ với JavaScript của bạn. Cố gắng hạn chế sự pha trộn giữa PHP và JS càng nhiều càng tốt.

Bạn luôn có thể làm điều này thay vào đó:

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

Và sau đó bạn có thể gọi hàm này trong tệp php, để làm cho những thứ trộn này càng nhỏ càng tốt.

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

Bằng cách thực hiện điều này (có các tệp JS lớn hơn, không phải 2-3 dòng không thành vấn đề), bạn có thể tận dụng việc nén tệp JS và các nhà phát triển giao diện người dùng cảm thấy thoải mái khi chỉ làm việc với JavaScript (theo cách bạn có thể viết Python, Ruby, v.v. không chỉ PHP - và mã có thể ngày càng lớn hơn tùy thuộc vào những gì bạn cần làm ở đó).


2
Totaly đồng ý, btw TÔI KHÔNG BAO GIỜ đưa PHP vào JS của tôi. Tôi chỉ nhìn thấy nó trên trang web này tất cả các thời gian.
Greg Guida

Mã php không bao giờ xuất hiện trên trình duyệt! Chỉ là mã được đánh giá mà bây giờ sẽ là javascript đơn giản. Vì vậy, kích thước tập tin / nén là một vấn đề không. Vẫn còn suy nghĩ thực hành xấu!
James Anderson

@JamesAnderson Tôi nghĩ alessioalex đang đề cập đến việc thu nhỏ (như Uglify). Có thể chạy php và sau đó có chức năng php hậu xử lý phân tích phản hồi, xác định thẻ script, chạy nó qua Uglify và thay thế JS được tạo bởi php ban đầu bằng phiên bản rút gọn trước khi gửi phản hồi, nhưng làm điều đó theo mọi yêu cầu nghe có vẻ như là một yike! tiếp cận.
jinglểula

6

Tôi không nghĩ rằng đây là thực hành xấu. Nếu ID được yêu cầu trong JavaScript của bạn là động thì không có cách nào khác để làm điều này.


5
Tại sao trong tên không lành mạnh của cuthulu, bạn sẽ không biết tên của một thẻ ID?
Ẩn danh

3
@Incognito, có nhiều lúc bạn không biết ID ... Nếu bạn đang sử dụng ajax để tạo các khối mã mới, bạn có thể tạo ID duy nhất cùng với JS mới ... trong những trường hợp này bạn cần phải đảm bảo rằng các ID là các tham chiếu giống nhau trong js vì chúng nằm trong khối mã kết quả. Có rất nhiều trường hợp như thế này và nó khá phổ biến khi ajax có liên quan hoặc có nhiều khối mã phụ thuộc vào câu lệnh if-other phía máy chủ, v.v.

7
@raynjamin Tôi thậm chí không hiểu cách bạn đặt mình vào tình huống bạn đang làm gì ... hoặc tại sao bạn chọn theo lớp, sau đó liệt kê các thẻ, sau đó các thuộc tính ID có giá trị css ẩn, người chọn đó ... Thật sự làm tôi đau lòng khi nhìn vào ... Tôi thậm chí không biết bắt đầu từ đâu với ... như ... cái gì? Bạn đang cắt + dán các khối mã lớn hoặc một cái gì đó để làm cho mọi thứ hoạt động trên nhiều ID? Tôi thậm chí không ... thích ... bộ não của mình. Nó đang phát nổ ở đây.
Ẩn danh

3
Hãy đọc về dom / html / bất cứ điều gì ... sử dụng công cụ tìm kiếm ... Tại sao tôi chưa bao giờ phải làm những thứ như thế này với HTML động?
Ẩn danh

5
Không. bạn không hiểu thẻ ID hoạt động như thế nào. Tôi hiểu chính xác những gì bạn đang nói.
Ẩn danh

6

Tôi sẽ xem xét thực hành xấu này. Khi đặt nội dung động bên trong các khối tập lệnh, bạn luôn phải nhận thức được thực tế rằng việc thoát bên trong bối cảnh javascript không đơn giản như bạn mong muốn. Nếu các giá trị được người dùng cung cấp, việc thoát khỏi chúng là không đủ.

Bảng cheat OWASP XSS có nhiều chi tiết hơn, nhưng về cơ bản, bạn nên áp dụng mẫu này:

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

Sau đó, trong một tệp .js riêng được liên kết từ html chính của bạn, hãy tải mã này:

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

Lý do sử dụng tệp .js riêng biệt là hai lần:

  • Nó được lưu trữ để hiệu suất tốt hơn
  • Trình phân tích cú pháp HTML không được kích hoạt, do đó không có nguy cơ xảy ra lỗi XSS do ai đó đặt thẻ <? Php nhanh ở đâu đó

+1 để giải thích đầy đủ góc XSS! Cách tiếp cận của bạn sẽ tải nhanh hơn vì json đã được tải trước khi có sẵn, nhưng tôi thích phân tích cú pháp json tự động từ việc sử dụng $.ajaxhoặc tương tự
roo2

5

Một số người sẽ tranh luận rằng đó là thực tế xấu. Không phải vì nó là PHP bên trong JS, mà bởi vì nó là JS nội tuyến và do đó trình duyệt sẽ không được lưu vào bộ nhớ cache để dễ tải lần sau.

IMO luôn luôn tốt hơn khi sử dụng JSON để chuyển các biến giữa hai ngôn ngữ, nhưng tôi đoán nó tùy thuộc vào bạn.


5

Tôi sẽ nói rằng nói chung đừng làm điều đó. Tuy nhiên, nếu bạn muốn truyền dữ liệu từ PHP -> Javascript, sẽ không khiến tôi phát điên khi có một khối Javascript nội tuyến nơi bạn có mã dưới dạng được hiển thị dưới đây. Ở đây, mã chỉ chuyển dữ liệu từ php sang javascript, không tạo ra logic khi đang di chuyển hoặc tương tự. Phần tốt của việc thực hiện điều này so với cuộc gọi ajax là dữ liệu có sẵn ngay khi trang tải và không yêu cầu thêm một chuyến đi đến máy chủ.

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

Tất nhiên, một tùy chọn khác là xây dựng tệp cấu hình javascript từ PHP thông qua một số dạng tập lệnh xây dựng sẽ đưa tệp đó vào tệp .js.


4

Điều duy nhất tôi có thể nghĩ ra mà thực sự có thể gây ra vấn đề là khi các lỗi PHP được đặt thành hiển thị và do đó, nó sẽ tải một đoạn HTML hiển thị lỗi PHP vào JavaScript của bạn.

Ngoài ra, vì nó nằm trong kịch bản nên nó không hiển thị và đôi khi có thể mất một lúc để nhận ra lý do tại sao tập lệnh của bạn bị hỏng.


trường hợp tuyệt vời khi điều này gây ra một lỗi lớn
Greg Guida

3

Nó phụ thuộc vào ai, và nếu bạn hỏi tôi, vâng tôi xem xét nó trở lại thực hành vì một vài lý do. Trước hết, tôi muốn có mã javascript trong tệp JS của riêng mình mà trình phân tích cú pháp php sẽ không thể chạm vào.

Thứ hai, php chỉ thực thi tại máy chủ, vì vậy nếu bạn phụ thuộc vào một số biến trong php để thay đổi javascript của mình, điều đó có thể không hoạt động tốt. Nếu có một số cài đặt tải trang mà bạn muốn kiểm soát bằng javascript, tôi thường thích thêm giá trị đó vào DOM bằng php để javascript có thể tiếp cận nó khi và nếu nó muốn (ví dụ như trong một div ẩn).

Cuối cùng, chỉ cho mục đích tổ chức, điều này có thể rất khó chịu. Nó đủ tệ để trộn html và php (theo ý kiến ​​của tôi).


1

Chứa PHP vào một configđối tượng dữ liệu đi được 90% nhưng cách tốt nhất là tách biệt nó hoàn toàn. Bạn có thể sử dụng api RESTful để chỉ yêu cầu dữ liệu mà bạn cần, đó là một javascript hơn một chút nhưng với một vài lợi thế.

  • Script là tĩnh và có thể được lưu trữ vĩnh viễn
  • PHP không còn là Vector XSS
  • Hoàn thành tách biệt các mối quan tâm

Nhược điểm:

  • Yêu cầu thêm yêu cầu HTTP
  • javascript phức tạp hơn

Kịch bả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);
       }
    });
})

-3

Đó không phải là một thực hành xấu CHỈ nếu nó được sử dụng để khởi tạo mã javascript, (trong các chủ đề WordPress của tôi, tôi khởi tạo các đối tượng javascript của mình bằng các hàm php như site_url () vì đó là cách duy nhất để xử lý yêu cầu đó (có lẽ chúng ta có thể sử dụng yêu cầu ajax để nhận một json, và vì vậy ... nhưng đó là một nỗi đau ở mông).

Thực hành tốt:

javascriptObject mới ("");

Thực hành xấu:

/ * một số mã * / document.get_element_by_id (); / * một số mã * /
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.