É considerado uma prática ruim ter PHP no seu JavaScript

55

Muitas vezes neste site, vejo pessoas tentando fazer coisas assim:

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

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

  });
</script>

Eu não acho que esse seja algum tipo de padrão em que as pessoas naturalmente se enquadram. Deve haver algum tipo de tutorial ou material de aprendizagem por aí que mostre isso, caso contrário, não veríamos tanto. O que estou perguntando é: estou lidando muito com isso ou é uma prática muito ruim?

Edição: estava falando com um amigo meu sobre isso, que muitas vezes coloca ruby ​​em seu JavaScript e ele trouxe esse ponto.

Não há problema em colocar dinamicamente constantes amplas do aplicativo em seu JavaScript para que você não precise editar dois arquivos. por exemplo...

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

também é bom codificar diretamente os dados que você planeja usar em uma biblioteca

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

ou devemos fazer uma ligação AJAX sempre?

Greg Guida
fonte
4
Parece-me que this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom
7
@ M.Babcock Isso faria parte de um arquivo .php, para que o código php fosse executado no servidor, e o cliente veria apenas o resultado do eco.
8
Qualquer um que crie JavaScript gerado dinamicamente é retirado e tratado
Raynos
5
@ Matt, então eu vou tomar google para trás e lidar com eles
Raynos
4
"Você conseguiu seu javascript no meu PHP!" "Não, você tem seu PHP no meu javascript!"
Josh Darnell

Respostas:

83

Normalmente, é uma má prática usar o idioma X para gerar código no idioma Y.

Tente dissociar os dois idiomas, transformando os dados em sua única interface - não misture o código .

No seu exemplo, você pode melhorar o código usando o PHP para preencher uma cfgestrutura que está disponível para JavaScript:

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

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

Dessa forma, o PHP se preocupa apenas com o preenchimento da estrutura de dados e o JavaScript se preocupa apenas com o consumo da estrutura de dados.

Essa dissociação também abre caminho para carregar os dados de forma assíncrona (JSON) no futuro.

Atualizar:

Para responder às perguntas adicionais que você fez com sua atualização, sim, seria uma boa prática aplicar o princípio DRY e permitir que PHP e JavaScript compartilhem o mesmo objeto de configuração:

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

  ...

Não há mal nenhum em inserir a representação JSON de sua configuração diretamente em sua página como esta. Você não precisa necessariamente buscá-lo via XHR.

Ates Goral
fonte
21
Lembre-se de não colocar sua senha do MySQL em $ cfg!
Thomas Bonini
13
"transformando os dados em sua única interface - não misture o código." Eu acho que isso realmente vai ao cerne da questão e é uma boa regra geral ao usar QUALQUER dois idiomas juntos. Obrigado pela compreensão.
Greg Guida
6
Você também pode incluir esse JSON em um data-atributo no seu HTML. Algo como <body data-cfg="{...}">.
Kapa
11
@bazmegakapa Acho que essa pode ser a melhor opção. Em particular, ele permite o uso de APIs, como HTML DOM, que reduzem bastante o risco de injeções de XSS.
luiscubal
11
+1 por sugerir o uso de dados como interface e código desencorajador que gera código.
Brandon
21

JavaScript gerado dinamicamente é uma prática horrível e ruim.

O que você deve fazer é compreender o que significa Separação de preocupações e aprimoramento progressivo.

Isso basicamente significa que você tem HTML dinâmico e JavaScript estático (que aprimora o HTML).

No seu caso, você provavelmente deseja uma classe em sua div e seleciona-a com um seletor de classe

Raynos
fonte
10

O maior problema com seu snippet é que você está faltando #para torná-lo um seletor jQuery válido;).

Eu diria que você deve evitar incluir o PHP no seu JavaScript sempre que possível. O que há de errado em alterar o seletor em seu click()manipulador para uma classe e adicionar a classe ao elemento em questão se você deseja que o manipulador seja acionado, e não se não;

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

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

  });
</script> 

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

Não são as circunstâncias em que você precisa para incluir PHP em sua JavaScript; mas devo admitir que estes são poucos e distantes entre si.

Um exemplo é quando você tem ambientes diferentes; testar, encenar e viver. Cada um deles tem um local diferente de seus ativos (imagens, principalmente). A maneira mais fácil de definir o caminho para que possa ser usado pelo JavaScript é algo como;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };
Matt
fonte
No restante do meu código php imaginário, eu já adicionei o #=), mas sério, eu concordo que seu exemplo é a melhor maneira de fazê-lo. Parece-me mais natural fazê-lo dessa maneira também. Então, por que o vemos com tanta frequência em lugares onde não é necessário?
Greg Guida
Observe que o eco de dados estáticos em um arquivo de configuração pode ser facilmente evitado fazendo com que todos os seus ambientes sejam configurados da mesma maneira.
Raynos
4
@GregGuida: Meu palpite seria que os programadores raramente estão acostumados a lidar com arquiteturas de cliente / servidor como você desenvolve no desenvolvimento da web. Eles tratam o DB <-> PHP <-> HTML / JS / CSS como um e não entendem completamente o que deve ir para onde e como as camadas devem ser separadas.
22411 Matt
@ Matt Eu acho que essa é provavelmente a melhor explicação
Greg Guida
2
$divID = '#' . $element_id_value;- sem problemas com o chefe do seletor;)
rlemon
8

Essa é uma prática ruim, na minha opinião, pois você precisaria chamar esse arquivo de algo.php e não poderá compactá-lo, por exemplo, sem mencionar que não é bom misturar as coisas do servidor com o JavaScript. Tente limitar a mistura entre PHP e JS, tanto quanto possível.

Você sempre pode fazer isso:

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

E então você poderia chamar essa função em um arquivo php, para tornar essas coisas de mistura o mais pequenas possível.

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

Ao fazer isso (com arquivos JS maiores, e não de duas a três linhas onde isso não importa), você pode aproveitar a compactação do arquivo JS e os desenvolvedores de front-end se sentem muito confortáveis ​​trabalhando apenas com JavaScript na minha opinião (como você poderia escrever Python, Ruby, etc., não apenas o PHP - e o código pode ficar cada vez maior, dependendo do que você precisa fazer lá).

alessioalex
fonte
2
Totalmente de acordo, btw NUNCA coloquei PHP no meu JS. Eu apenas o vejo neste site o tempo todo.
Greg Guida
O código php nunca chega ao navegador! Apenas o código avaliado que agora deve ser javascript simples. Portanto, o tamanho / compactação do arquivo não é um problema. Ainda é uma prática ruim!
James Anderson
@ JamesAnderson Acho que alessioalex está se referindo à minificação (como o Uglify). Pode ser possível executar o php e, em seguida, ter uma função php pós-processo para analisar a resposta, identificar a tag de script, executá-la no Uglify e substituir o JS originalmente gerado por php pela versão minificada antes de enviar a resposta, mas fazer isso em todos os pedidos parece uma merda! aproximação.
Jinglesthula 03/07
6

Eu não acho que isso seja uma prática ruim. Se o ID necessário no seu JavaScript for dinâmico, não há outra maneira de fazer isso.

CodeZombie
fonte
5
Por que no nome profano de cuthulu você não saberia o nome de uma etiqueta de identificação?
Incognito
3
@Incognito, há muitas vezes em que você não conhece o ID ... Se você estiver usando o ajax para gerar novos blocos de código, poderá estar gerando IDs exclusivos junto com o novo JS ... nesses casos, será necessário certifique-se de que os IDs sendo referências sejam os mesmos nos js ou no bloco de código resultante. Existem muitos mais casos como este e é muito comum quando ajax está envolvido ou existem grandes blocos de código dependentes um do lado do servidor if-else etc
7
@raynjamin Eu nem entendo como você se coloca em situações em que é isso que você está fazendo ... ou por que você seleciona por classe, depois lista tags e atributos de ID que têm um valor css oculto, aquele homem seletor ... está realmente me doendo olhar ... Eu nem sei por onde começar ... como ... o quê? Você está cortando + colando blocos maciços de código ou algo assim para fazer as coisas funcionarem com vários IDs? Eu nem ... gosto ... do meu cérebro. está explodindo aqui.
Incognito
3
Leia sobre o dom / html / qualquer coisa ... use um mecanismo de pesquisa ... Por que nunca tive que fazer coisas assim com HTML dinâmico?
Incognito
5
não. você não entende como as tags de ID funcionam. Eu entendo exatamente o que você está dizendo.
Incognito
6

Eu consideraria essa má prática. Ao colocar conteúdo dinâmico dentro de blocos de script, você sempre deve estar ciente do fato de que escapar dentro de um contexto javascript não é tão simples quanto você esperaria. Se os valores foram fornecidos pelo usuário, é não suficiente para html-escapar deles.

A folha de dicas do OWASP XSS tem mais detalhes, mas basicamente você deve adotar este padrão:

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

Em um arquivo .js separado, vinculado a partir do html principal, carregue este código:

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

O motivo do uso de um arquivo .js separado é duplo:

  • É armazenável em cache para que o desempenho seja melhor
  • O analisador HTML não é acionado; portanto, não há risco de um bug do XSS passar por alguém colocando uma rápida tag <? Php lá em algum lugar
Joeri Sebrechts
fonte
+1 para explicar completamente o ângulo XSS! Sua abordagem irá carregar mais rápido porque o JSON é carregado antes domready, mas eu prefiro o JSON análise automática de usar $.ajaxou similar
roo2
5

Algumas pessoas argumentam que é uma má prática. Não porque é PHP dentro de JS, mas porque é JS embutido e, portanto, não será armazenado em cache pelo navegador para facilitar o carregamento da próxima vez.

Na IMO, é sempre melhor usar JSON para passar variáveis ​​entre os dois idiomas, mas acho que depende de você.

usuario
fonte
5

Eu diria que, em geral, não faça isso. No entanto, se você deseja passar dados do PHP -> Javascript, não seria uma loucura ter um bloco Javascript embutido, onde você tem o código do formulário mostrado abaixo. Aqui o código está apenas passando dados do php para o javascript, não criando lógica em tempo real ou algo semelhante. A parte boa de fazer isso x uma chamada ajax é que os dados estão disponíveis assim que a página é carregada e não exigem uma viagem extra ao servidor.

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

Obviamente, uma outra opção é criar um arquivo de configuração javascript do PHP por meio de alguma forma de script de construção que o colocará em um arquivo .js.

Zachary K
fonte
4

A única coisa em que consigo pensar que pode realmente causar problemas é quando os erros do PHP são definidos para serem exibidos e, portanto, empurra uma carga de HTML mostrando o erro do PHP no seu JavaScript.

Também porque é no script, portanto, não é exibido e, às vezes, pode demorar um pouco para perceber por que seu script está quebrado.

Alex Coplan
fonte
ótimo caso em que isso causa um grande erro #
Greg Guida
3

Depende de quem, e se você me perguntar, sim, considero a prática de volta por alguns motivos. Primeiro de tudo, eu preferiria ter o código javascript em seu próprio arquivo JS que o analisador php não seria capaz de tocar.

Em segundo lugar, o php é executado apenas no horário do servidor; portanto, se você estiver dependendo de alguma variável do php para alterar seu javascript, isso pode não funcionar muito bem. Se houver alguma configuração de carregamento de página que você deseja controlar com javascript, normalmente prefiro adicionar esse valor ao DOM com php para que o javascript possa alcançá-lo quando e se desejar (em uma div oculta, por exemplo).

Finalmente, apenas para fins organizacionais, isso pode ser muito irritante. Já é ruim o suficiente misturar html e php (na minha opinião).

Comprimidos de explosão
fonte
1

A contenção do PHP em um configobjeto de dados ocorre 90%, mas a melhor prática é separá-lo completamente. Você pode usar uma API RESTful para solicitar apenas os dados necessários, é um pouco mais javascript, mas com algumas vantagens.

  • O script é estático e pode ser armazenado em cache permanentemente
  • PHP não é mais um vetor XSS
  • Separação completa de preocupações

Desvantagens:

  • Requer uma solicitação HTTP extra
  • javascript mais complexo

Roteiro

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

Não é uma prática ruim SOMENTE se for usado para a inicialização do código javascript (nos meus temas do WordPress, inicializo meus objetos javascript com funções php como site_url () porque é a única maneira de lidar com isso (talvez possamos usar uma solicitação ajax para obter um json, e assim ... mas é um pé no saco).

Boa prática:

novo javascriptObject ("");

Má prática:

/ * algum código * / document.get_element_by_id (); / * algum código * /
junius rendel
fonte