Чи вважається поганою практикою наявність PHP у вашому JavaScript


55

Так багато разів на цьому сайті я бачу людей, які намагаються робити такі речі:

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

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

  });
</script>

Я не думаю, що це якась закономірність, до якої люди природно потрапляють. Там має бути якийсь підручник чи навчальний матеріал, який це показує, інакше ми б його не бачили так сильно. Що я запитую, чи я роблю занадто велику справу чи це справді погана практика?

EDIT: Розмовляв з моїм другом про це, який часто кладе рубін у свій 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

7
@ M.Babcock Це буде частиною файлу .php, щоб php-код був виконаний на стороні сервера, а клієнт побачив би лише результат відлуння.

8
Кожен, хто створює динамічно генерований JavaScript, повертається назад і з ним розбирається
Raynos

5
@Matt, то я поверну google назад і
розберуся

4
"Ви отримали свій JavaScript у моєму PHP!" "Ні, ви отримали ваш PHP в моєму javascript!"
Джош Дарнелл

Відповіді:


83

Як правило, це погана практика , щоб використовувати мову X , щоб генерувати код на мові Y.

Спробуйте роз’єднати дві мови, зробивши дані єдиним інтерфейсом - не змішуйте код .

У вашому прикладі ви можете вдосконалити код, використовуючи PHP для заповнення cfgструктури, доступної JavaScript:

<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 !!
Томас Боніні

13
"робить дані єдиним інтерфейсом - не змішуйте код." Я думаю, що це дійсно вирішує основу проблеми і є хорошим правилом при використанні БУДЬ-яких двох мов разом. Дякуємо за розуміння.
Грег Гуйда

6
Ви також можете включити цей JSON в data-атрибут у своєму HTML. Щось подібне <body data-cfg="{...}">.
капа

1
@bazmegakapa Я думаю, що це може бути найкращим варіантом. Зокрема, це дозволяє використовувати такі API, як HTML DOM, які значно знижують ризик ін'єкцій XSS.
luiscubal

1
+1 за пропозицію використовувати дані як інтерфейс і відштовхуючи код, що генерує код.
Брендон

21

Динамічно генерований JavaScript - жахлива, погана практика.

Що ви повинні зробити, це зрозуміти, що означає поділ занепокоєння та прогресивне підвищення.

Це в основному означає, що у вас є динамічний HTML і статичний JavaScript (що покращує HTML).

У вашому випадку, ймовірно, ви хочете клас у вашому div і виберіть його за допомогою селектора


10

Найбільша проблема у вашому фрагменті - це те, що ви не вистачаєте, #щоб зробити його дійсним селектором jQuery;).

Я б сказав, що вам слід спробувати уникати включення PHP у свій JavaScript, де це можливо. Що не в тому, щоб змінити перемикач вашого 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>

Там є обставини , коли вам необхідно включити PHP в вашому JavaScript; але мушу визнати, що їх небагато і далеко між ними.

Наприклад, коли у вас різні середовища; випробування, постановка і жити. Кожен з них має інше місце розташування ваших активів (переважно зображення). Найпростіший спосіб встановити шлях, щоб він міг використовувати JavaScript, - це щось на зразок;

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

У решті мого уявного php-коду я вже додав #=), але серйозно погоджуюся, що ти, наприклад, є кращим способом зробити це. Мені здається більш природним зробити це і так. То чому ми його так часто бачимо в місцях, де це не потрібно?
Грег Гуйда

Зауважте, що повторюваних статичних даних у конфігураційному файлі можна легко уникнути, якщо всі ваші середовища налаштовуються однаково.
Райнос

4
@GregGuida: Я гадаю, що програмісти рідко звикли мати справу з архітектурою клієнт / сервер, як ви отримуєте веб-розробки. Вони трактують DB <-> PHP <-> HTML / JS / CSS як єдине ціле і не повністю розуміють, що слід куди подіти і як слід розділяти шари.
Метт

@Matt Я думаю, що це, мабуть, найкраще пояснення
Грег Гуйда

2
$divID = '#' . $element_id_value;- жодних проблем із селекторним босом немає))
релем

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
Повністю згоден, btw Я НІКОЛИ не ставив PHP в моєму JS. Я просто бачу це на цьому сайті весь час.
Грег Гуйда

PHP-код ніколи не робить його для браузера! Просто оцінений код, який тепер повинен бути звичайним JavaScript. Тому розмір / стиснення файлів - це не проблема. Ще погана думка про думку!
Джеймс Андерсон

@JamesAnderson Я думаю, що alessioalex має на увазі мінімізацію (як Uglify). Можливо, можливо, запустити php, а потім виконати функцію після обробки php, щоб проаналізувати відповідь, ідентифікувати тег сценарію, запустити його через Uglify та замінити оригінально створений php JS на мінімізовану версію перед відправкою відповіді, але робити це на кожне прохання звучить як поступки! підхід.
jinglesthula

6

Я не думаю, що це погана практика. Якщо ідентифікатор, необхідний у вашому JavaScript, динамічний, іншого способу це зробити не існує.


5
Чому в нечестивому імені cuthulu ти не знаєш імені ідентифікаційного тегу?
інкогніто

3
@ Incognito, є багато разів, коли ви не знаєте ідентифікатора ... Якщо ви використовуєте ajax для створення нових блоків коду, можливо, ви створюєте унікальні ідентифікатори разом з новими JS ... у цих випадках вам потрібно переконайтесь, що ідентифікатори, на які посилаються, однакові в js, вони знаходяться в результуючому кодовому блоці. Існує набагато більше таких випадків, і це досить часто, коли задіяний ajax або є великі блоки коду, залежні від заяви на стороні сервера if-else та інше

7
@raynjamin Я навіть не розумію, як ти ставиш себе в ситуації, коли ти це робиш ... або чому ти вибрав би за класом, потім перерахував теги, потім атрибути ID, які мають приховане значення css, цей селектор ... насправді боляче мене дивитись ... Я навіть не знаю, з чого почати ... як ... що? Ви вирізаєте + вставляєте масивні блоки коду чи щось, щоб змусити роботу працювати над кількома ідентифікаторами? Я навіть не люблю ... мій мозок. тут вибухає.
інкогніто

3
Почитайте про dom / html / що завгодно ... використовуйте пошукову систему ... Чому мені ніколи не доводилося робити подібні речі з динамічним HTML?
інкогніто

5
немає. ви не розумієте, як працюють теги ідентифікаторів. Я точно розумію, що ти кажеш.
інкогніто

6

Я вважав би це поганою практикою. Розміщуючи динамічний вміст всередині блоків скриптів, ви завжди повинні знати про те, що вийти з контексту javascript не так просто, як ви могли би сподіватися. Якщо значення були користувачем при умови, що це НЕ досить , щоб HTML-уникнути їх.

На шпаргалках OWASP XSS є більше деталей, але в основному вам слід прийняти цю схему:

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

Потім завантажте цей код у окремий .js файл, пов’язаний із вашим головним html:

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-аналізатор не спрацьовує, тому немає ризику проскочити помилку XSS, коли хтось помістить швидкий тег <? Php

+1 для повного пояснення кута XSS! Ваш підхід буде завантажуватися швидше, тому що json завантажується раніше, ніж раніше, але я віддаю перевагу автоматичному розбору json від використання $.ajaxабо подібного
roo2

5

Деякі люди стверджують, що це погана практика. Не тому, що це PHP всередині JS, а тому, що він є вбудованим JS і тому браузер не буде кешований для зручності завантаження наступного разу.

IMO, завжди краще використовувати JSON для передачі змінних між двома мовами, але я думаю, це залежить від вас.


5

Я б сказав, що взагалі цього не роблять. Однак якщо ви хочете передати дані з PHP -> Javascript, це не вразило б мене, як божевільний, щоб мати вбудований блок Javascript, де ви маєте код форми, показаної нижче. Тут код просто передає дані з php в javascript, не створюючи логіку на льоту або тому подібне. Хороша частина цього виклику проти ajax-дзвінка полягає в тому, що дані доступні, як тільки сторінка завантажується, і не вимагає додаткової поїздки на сервер.

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

Звичайно, іншим варіантом є побудова файлу конфігурації javascript з PHP через якусь форму сценарію побудови, який помістить його у файл .js.


4

Єдине, що я можу придумати, що може насправді викликати проблеми - це коли PHP встановлено відображення помилок, і це передає HTML-код, що відображає помилку PHP у вашому JavaScript.

Крім того, оскільки його це в сценарії, тому він не відображається, і іноді може знадобитися деякий час, щоб зрозуміти, чому ваш сценарій зламаний.


чудовий випадок, коли це викликає велику помилку
Грег Гуйда

3

Це залежить від кого, і якщо ви запитаєте мене, так, я вважаю, що це практика з кількох причин. Перш за все, я вважаю за краще мати код JavaScript у власному файлі JS, до якого PHP-аналізатор не міг би торкнутися.

По-друге, php виконується лише в серверний час, тому, якщо ви залежаєте від якоїсь змінної в php, щоб змінити свій JavaScript, це може не працювати дуже добре. Якщо є якесь налаштування завантаження сторінки, яким ви хочете керувати за допомогою JavaScript, я, як правило, вважаю за краще додавати це значення до DOM за допомогою php, щоб javascript міг досягти цього, коли і якщо він захоче (наприклад, у прихованому розділі).

Нарешті, лише з організаційних цілей це може стати дуже дратує. Досить погано змішувати 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 я ініціалізую свої об’єкти JavaScript з такими функціями php, як site_url (), тому що це єдиний спосіб впоратися з цим (можливо, ми могли б використати запит ajax, щоб отримати json, і так ... але це біль у попці).

Гарна практика:

новий javascriptObject ("");

Погана практика:

/ * деякий код * / document.get_element_by_id (); / * деякий код * /
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.