Считается ли плохой практикой иметь PHP в вашем JavaScript

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
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 и выберите его с помощью селектора класса

Raynos
источник
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']; ?>" };
Matt
источник
В остальной части моего воображаемого php-кода я уже добавил #=), но серьезно я согласен, что ваш пример - лучший способ сделать это. Мне кажется более естественным делать это и так. Так почему же мы видим это так часто в тех местах, где это не нужно?
Грег Гуида
Обратите внимание, что эхо статических данных в файле конфигурации можно легко избежать, если все ваши среды будут настроены одинаково.
Рейнос
4
@GregGuida: Я полагаю, что программисты редко привыкли иметь дело с архитектурами клиент / сервер, как в веб-разработке. Они рассматривают DB <-> PHP <-> HTML / JS / CSS как единое целое и не до конца понимают, что и куда должно идти и как следует разделять слои.
Мэтт
@ Matt Я думаю, что это, вероятно, лучшее объяснение
Грег Гида
2
$divID = '#' . $element_id_value;- нет проблем с боссом селектора;)
rlemon
8

На мой взгляд, это плохая практика, так как вам нужно было бы назвать этот файл нечто.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 - и код может становиться все больше и больше в зависимости от того, что вам нужно там делать).

alessioalex
источник
2
Полностью согласен, кстати, я НИКОГДА не помещал PHP в мой JS. Я просто вижу это на этом сайте все время.
Грег Гуида
PHP-код никогда не попадает в браузер! Просто проверенный код, который теперь должен быть простым javascript. Таким образом, размер файла / сжатие не проблема. Все еще плохая практика мысли!
Джеймс Андерсон
@JamesAnderson Я думаю, что alessioalex имеет в виду минификацию (например, Uglify). Может быть возможно запустить php, а затем иметь функцию php после обработки, которая анализирует ответ, идентифицирует тег сценария, запускает его через Uglify и заменяет первоначально сгенерированный php JS на минимизированную версию перед отправкой ответа, но делать это при каждом запросе - это похоже на yikes! подход.
jinglesthula
6

Я не думаю, что это плохая практика. Если идентификатор, требуемый в вашем JavaScript, является динамическим, другого способа сделать это не существует.

CodeZombie
источник
5
Почему из-за нечестивого имени Катхулу вы не знаете имя идентификационной метки?
Инкогнито
3
@Incognito, есть много раз, когда вы не знаете идентификатор ... Если вы используете ajax для генерации новых блоков кода, вы можете генерировать уникальные идентификаторы вместе с новым JS ... в этих случаях вам нужно убедитесь, что идентификаторы, являющиеся ссылками, одинаковы в js, если они находятся в результирующем блоке кода. Подобных примеров гораздо больше, и это довольно часто, когда задействован Ajax, или когда большие блоки кода зависят от серверной инструкции if-else и т. Д.
7
@ raynjamin Я даже не понимаю, как вы попадаете в ситуации, когда это то, что вы делаете ... или почему вы выбираете по классу, затем перечисляете теги, затем атрибуты ID, которые имеют скрытое значение CSS, этот селектор ... на самом деле мне больно смотреть на ... Я даже не знаю, с чего начать ... как ... что? Вы вырезаете или вставляете массивные блоки кода или что-то, чтобы заставить работать несколько идентификаторов? Я даже не ... как ... мой мозг. это взрывается здесь.
Инкогнито
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>

Затем в отдельном файле .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 мог достичь его, когда и если захочет (например, в скрытом 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);
       }
    });
})
roo2
источник
-3

ТОЛЬКО это не плохая практика, если он используется для инициализации кода javascript (в моих темах WordPress я инициализирую свои объекты javascript с помощью функций php, таких как site_url (), потому что это единственный способ справиться с этим (возможно, мы могли бы использовать запрос ajax для получения JSON, и так ... но это боль в заднице).

Хорошая практика:

новый javascriptObject ("");

Плохая практика:

/ * некоторый код * / document.get_element_by_id (); / * некоторый код * /
Junius Rendel
источник