Czy uważanie PHP za JavaScript jest uważane za złą praktykę?

55

Tak wiele razy na tej stronie widzę ludzi próbujących robić takie rzeczy:

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

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

  });
</script>

Nie sądzę, że jest to jakiś wzór, w który ludzie naturalnie wpadają. Musi istnieć jakiś samouczek lub materiał do nauki, który to pokazuje, w przeciwnym razie nie zobaczylibyśmy go tak często. Pytam, czy robię z tego zbyt duży interes, czy jest to naprawdę zła praktyka?

EDYCJA: Rozmawiałem z moim przyjacielem na ten temat, który często umieszcza rubryka w swoim JavaScript i poruszył tę kwestię.

Czy można dynamicznie umieszczać stałe w aplikacji w JavaScript, aby nie trzeba było edytować dwóch plików? na przykład...

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

jest również OK, aby bezpośrednio kodować dane, których planujesz użyć w bibliotece

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

czy powinniśmy za każdym razem wykonywać połączenia AJAX?

Greg Guida
źródło
4
Wydaje mi się, że this question will likely solicit opinion, debate, arguments, polling, or extended discussion....
DaveRandom
7
@ M.Babcock Byłby to część pliku .php, aby kod php był wykonywany po stronie serwera, a klient widziałby tylko wynik echa.
8
Każdy, kto tworzy dynamicznie generowany JavaScript, zostaje usunięty i zostaje załatwiony
Raynos
5
@Matt to zabiorę google z powrotem i zajmę się nimi
Raynos,
4
„Masz skrypt JavaScript w moim PHP!” „Nie, masz PHP w moim javascript!”
Josh Darnell,

Odpowiedzi:

83

Zazwyczaj to jest złą praktyką do używania języka X do generowania kodu w języku Y.

Spróbuj oddzielić dwa języki, ustawiając dane jako jedyny interfejs - nie mieszaj kodu .

W twoim przykładzie możesz ulepszyć kod, używając PHP do wypełnienia cfgstruktury dostępnej dla JavaScript:

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

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

W ten sposób PHP dba tylko o wypełnienie struktury danych, a JavaScript dba tylko o wykorzystanie struktury danych.

To oddzielenie prowadzi również do asynchronicznego ładowania danych (JSON) w przyszłości.

Aktualizacja:

Aby odpowiedzieć na dodatkowe pytania zadane podczas aktualizacji, tak, dobrą praktyką byłoby zastosowanie zasady DRY i umożliwienie PHP i JavaScript współdzielenia tego samego obiektu konfiguracji:

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

  ...

Wstawianie reprezentacji JSON konfiguracji bezpośrednio na twojej stronie nie jest szkodliwe. Nie musisz pobierać go za pośrednictwem XHR.

Ates Goral
źródło
21
Pamiętaj jednak, aby nie umieszczać hasła MySQL w $ cfg !!
Thomas Bonini,
13
„uczynienie danych ich jedynym interfejsem - nie mieszaj kodu”. Myślę, że to naprawdę przenika do sedna problemu i jest dobrą zasadą, gdy używa się KAŻDEGO dwóch języków razem. Dzięki za wgląd.
Greg Guida,
6
Możesz także dołączyć ten JSON do data-atrybutu w swoim HTML. Coś jak <body data-cfg="{...}">.
kapa
1
@bazmegakapa Myślę, że to może być najlepsza opcja. W szczególności umożliwia stosowanie interfejsów API, takich jak HTML DOM, które znacznie zmniejszają ryzyko wstrzyknięć XSS.
luiscubal
1
+1 za sugerowanie używania danych jako interfejsu i zniechęcanie kodu, który generuje kod.
Brandon
21

Dynamicznie generowany JavaScript to okropna, zła praktyka.

To, co powinieneś zrobić, to zrozumieć, co oznacza Seperation of Concerns and Progressive Enhancement.

Zasadniczo oznacza to, że masz dynamiczny HTML i statyczny JavaScript (co poprawia HTML).

W twoim przypadku prawdopodobnie chcesz klasę na div i wybierz ją za pomocą selektora klas

Raynos
źródło
10

Największym problemem z twoim fragmentem jest to, że nie możesz go ustawić #jako prawidłowego selektora jQuery;).

Powiedziałbym, że powinieneś starać się unikać włączania PHP w JavaScript, jeśli to możliwe. Co jest złego w zmianie selektora w click()module obsługi na klasę i dodaniu klasy do danego elementu, jeśli chcesz, aby moduł obsługi był uruchamiany, a nie jeśli nie;

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

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

  });
</script> 

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

Tam sytuacje, w których trzeba podać PHP w JavaScript; ale muszę przyznać, że jest ich niewiele.

Przykładem może być sytuacja w różnych środowiskach; test, inscenizacja i na żywo. Każdy z nich ma inną lokalizację twoich zasobów (głównie zdjęć). Najłatwiejszym sposobem ustawienia ścieżki tak, aby mogła być używana przez JavaScript, jest coś w rodzaju;

var config = { assets: "<?php echo $yourConfig['asset_url']; ?>" };
Matt
źródło
W pozostałej części mojego wyobrażonego kodu php już dodałem #=), ale poważnie zgadzam się, że twój przykład jest lepszym sposobem na zrobienie tego. Wydaje mi się to bardziej naturalne, aby robić to w ten sposób. Dlaczego więc widzimy to tak często w miejscach, gdzie nie jest to konieczne?
Greg Guida,
Pamiętaj, że echa danych statycznych w pliku konfiguracyjnym można łatwo uniknąć, konfigurując wszystkie środowiska w ten sam sposób.
Raynos,
4
@GregGuida: Domyślam się, że programiści rzadko są przyzwyczajeni do radzenia sobie z architekturami klient / serwer, tak jak robisz to przy tworzeniu stron internetowych. Traktują DB <-> PHP <-> HTML / JS / CSS jako jeden i nie do końca rozumieją, co powinno iść gdzie i jak należy rozdzielić warstwy.
Matt
@Matt Myślę, że to chyba najlepsze wytłumaczenie
Greg Guida,
2
$divID = '#' . $element_id_value;- żadnych problemów z bossem selektora;)
rlemon
8

Moim zdaniem jest to zła praktyka, ponieważ trzeba nazwać ten plik czymś. Php, a następnie nie można go na przykład skompresować, nie wspominając, że mieszanie zawartości serwera z JavaScriptem nie jest w porządku. Spróbuj maksymalnie ograniczyć miksowanie między PHP a JS.

Zawsze możesz to zrobić zamiast tego:

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

A potem możesz wywołać tę funkcję w pliku php, aby zmiksować rzeczy tak małe, jak to możliwe.

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

Robiąc to (mając większe pliki JS, a nie 2-3 wiersze, gdzie to nie ma znaczenia) możesz skorzystać z kompresji pliku JS, a programiści front-end czują się komfortowo pracując tylko z JavaScriptem (moim zdaniem) Python, Ruby itp. Nie tylko PHP - a kod może być coraz większy w zależności od tego, co musisz tam zrobić).

alessioalex
źródło
2
Całkowicie się zgadzam, ale NIGDY nie umieszczam PHP w moim JS. Cały czas widzę to na tej stronie.
Greg Guida,
Kod php nigdy nie trafia do przeglądarki! Tylko sprawdzony kod, który powinien być teraz zwykłym javascript. Dlatego rozmiar pliku / kompresja nie stanowią problemu. Ciągle zła praktyka!
James Anderson
@JamesAnderson Myślę, że alessioalex odnosi się do minimalizacji (jak Uglify). Możliwe, że uruchomi się php, a następnie postprocesowa funkcja php przeanalizuje odpowiedź, zidentyfikuje znacznik skryptu, uruchom go przez Uglify i zamieni pierwotnie wygenerowany JS na wersję zminimalizowaną przed wysłaniem odpowiedzi, ale robienie tego na każde żądanie brzmi jak yike! podejście.
jinglesthula
6

Nie sądzę, że to zła praktyka. Jeśli identyfikator wymagany w JavaScript jest dynamiczny, nie ma innego sposobu, aby to zrobić.

CodeZombie
źródło
5
Dlaczego w przeklętej nazwie cuthulu nie miałbyś nazwy identyfikatora?
Incognito,
3
@Incognito, wiele razy nie znasz identyfikatora ... Jeśli używasz ajax do generowania nowych bloków kodu, możesz generować unikalne identyfikatory wraz z nowym JS ... w tych przypadkach musisz upewnij się, że identyfikatory będące odwołaniami są takie same w js, ponieważ znajdują się w wynikowym bloku kodu. Jest o wiele więcej takich przypadków i jest to dość powszechne, gdy jest zaangażowany ajax lub są duże bloki kodu zależne od instrukcji if-else po stronie serwera
7
@raynjamin Nie rozumiem nawet, jak stawiasz się w sytuacjach, w których to robisz ... lub dlaczego wybierasz według klasy, a następnie wyświetlasz tagi, a następnie atrybuty ID, które mają ukrytą wartość css, tego selektora ... to naprawdę boli mnie patrzeć ... Nie wiem nawet, od czego zacząć ... na przykład ... od czego? Czy wycinasz + wklejasz ogromne bloki kodu, czy coś, co pozwala na pracę z wieloma identyfikatorami? Nawet nie ... lubię ... mojego mózgu. tutaj eksploduje.
Incognito,
3
Przeczytaj o dom / html / cokolwiek ... użyj wyszukiwarki ... Dlaczego nigdy nie musiałem robić takich rzeczy z dynamicznym HTML?
Incognito,
5
Nie. nie rozumiesz, jak działają identyfikatory. Rozumiem dokładnie to, co mówisz.
Incognito,
6

Rozważałbym tę złą praktykę. Umieszczając zawartość dynamiczną w blokach skryptów, zawsze musisz mieć świadomość, że ucieczka w kontekście javascript nie jest tak prosta, jak można się spodziewać. Jeśli wartości zostały podane przez użytkownika, nie wystarczy ich uciec z HTML.

OWASP XSS Ściągawka ma więcej szczegółów, ale w zasadzie należy przyjąć tego wzoru:

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

Następnie w osobnym pliku .js połączonym z głównym plikiem HTML załaduj ten kod:

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

Powód używania osobnego pliku .js jest dwojaki:

  • Jest buforowalny, więc wydajność jest lepsza
  • Parser HTML nie jest uruchamiany, więc nie ma ryzyka, że ​​ktoś prześlizgnie się przez błąd XSS przez kogoś, kto umieści gdzieś szybki znacznik <? Php
Joeri Sebrechts
źródło
+1 za pełne wyjaśnienie kąta XSS! Twoje podejście ładuje się szybciej, ponieważ json jest ładowany przed domeną, ale wolę automatyczne parsowanie $.ajax
jsona
5

Niektórzy twierdzą, że to zła praktyka. Nie dlatego, że jest PHP wewnątrz JS, ale dlatego, że jest wbudowany JS, więc przeglądarka nie będzie go buforować, aby ułatwić ładowanie następnym razem.

IMO zawsze lepiej jest używać JSON do przekazywania zmiennych między 2 językami, ale myślę, że to zależy od ciebie.

Nacięcie
źródło
5

Powiedziałbym, że generalnie nie rób tego. Jednak jeśli chcesz przekazać dane z PHP -> JavaScript, nie byłoby dla mnie szaleństwem mieć wbudowany blok JavaScript, w którym poniżej znajduje się kod postaci. Tutaj kod po prostu przekazuje dane z php do javascript, nie tworząc logiki w locie ani tym podobnych. Zaletą tego działania w porównaniu z wywołaniem ajax jest to, że dane są dostępne, gdy tylko strona się załaduje i nie wymaga dodatkowej podróży na serwer.

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

Oczywiście inną opcją jest zbudowanie pliku konfiguracyjnego javascript z PHP za pomocą jakiejś formy skryptu kompilacji, który umieści go w pliku .js.

Zachary K.
źródło
4

Jedyną rzeczą, o której mogę pomyśleć, która naprawdę może powodować problemy, jest to, że błędy PHP są ustawione na wyświetlanie, więc przesuwa ładunek HTML pokazujący błąd PHP do twojego JavaScript.

Również dlatego, że jest w skrypcie, dlatego się nie wyświetla i czasem może minąć trochę czasu, zanim zrozumiesz, dlaczego twój skrypt jest uszkodzony.

Alex Coplan
źródło
świetny przypadek, w którym powoduje to duży błąd
Greg Guida,
3

To zależy od kogo, a jeśli mnie zapytacie, tak, uważam to za praktykę z kilku powodów. Po pierwsze wolałbym mieć kod javascript we własnym pliku JS, którego parser php nie byłby w stanie dotknąć.

Po drugie, php działa tylko na serwerze, więc jeśli zmieniasz javascript w zależności od zmiennej w php, może to nie działać zbyt dobrze. Jeśli istnieje jakieś ustawienie ładowania strony, które chcesz kontrolować za pomocą javascript, zazwyczaj wolę dodawać tę wartość do DOM za pomocą php, aby javascript mógł do niej dotrzeć, kiedy i jeśli chce (na przykład w ukrytym div).

Wreszcie, ze względów organizacyjnych może to być bardzo denerwujące. Wystarczająco źle jest mieszanie html i php (moim zdaniem).

Pigułki przeciwwybuchowe
źródło
1

Zawieranie PHP w configobiekcie danych przebiega w 90%, ale najlepszą praktyką jest oddzielenie go całkowicie. Możesz użyć interfejsu API RESTful, aby zażądać tylko potrzebnych danych, jest to nieco więcej javascript, ale z kilkoma zaletami.

  • Skrypt jest statyczny i może być trwale buforowany
  • PHP nie jest już wektorem XSS
  • Całkowite rozdzielenie obaw

Wady:

  • Wymaga dodatkowego żądania HTTP
  • bardziej złożony javascript

Scenariusz

//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
źródło
-3

Nie jest to zła praktyka TYLKO, jeśli jest używana do inicjalizacji kodu javascript (w moich motywach WordPress inicjuję moje obiekty javascript za pomocą funkcji php takich jak site_url (), ponieważ jest to jedyny sposób, aby sobie z tym poradzić (być może moglibyśmy użyć żądania ajax, aby uzyskać json, i tak ... ale to boli w tyłek).

Dobra praktyka:

new javascriptObject („”);

Zła praktyka:

/ * jakiś kod * / document.get_element_by_id (); / * jakiś kod * /
junius rendel
źródło