Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dziwny problem z include, sesjami i echo
Forum PHP.pl > Forum > PHP
Cod
Nieczęsto proszę kogoś na forum o pomoc, bo zawsze staram się rozwiązywać problemy sam. Z tym jednak nie mogę sobie poradzić. Nie mam zupełnie pojęcia o co chodzi.

Zacząłem tworzyć stronę, która będzie dostępna w kilku językach. Gość już na stronie głównej może wybrać sobie, w jakim języku witryna ma być wyświetlana. Klikając w odpowiedni link, tworzy zmienną $HTTP_SESSION_VARS["lang"], zawierającą wiadomość, o tym, jaki gość wybrał język. W skrypcie strony, na samym początku sprawdzane jest, czy zmienna istnieje. Jeśli nie, to przypisana jest jej wartość języka angielskiego. Następnie includowany jest plik, zawierający deklarację tablicy $lang, w której pod odpowiednimi indeksami zawarte będą przetłumaczone na dany język teksty.

To tyle tytułem wstępu. Poniżej wklejam fragment kodu, który ma wyświetlić różne tytuły dla różnych języków:

header.php
  1. <?php
  2. if(isset($HTTP_GET_VARS[&#092;"lang\"])) $HTTP_SESSION_VARS[\"lang\"]=$HTTP_GET_VARS[\"lang\"];
  3. else $HTTP_SESSION_VARS[&#092;"lang\"]=\"english\";
  4. $langdir=&#092;"lang/\".$HTTP_SESSION_VARS[\"lang\"].\"/lang_main.php\";
  5. include($langdir);
  6. // .....
  7. echo &#092;"<title>footbagnews.com :: \".$lang[\"title\"].\"</title>\";
  8. ?>


lang/polski/lang_main.php
  1. <?php
  2. $lang[&#092;"title\"]=\"zo&para;ka, footbag, newsy, informacje, wydarzenia, triki, gracze, filmy\";
  3. ?>


lang/english/lang_main.php
  1. <?php
  2. $lang[&#092;"title\"]=\"footbag, hacky sack, news, events, tricks, moves, players, videos\";
  3. ?>


Przy pierwszym uruchomieniu strony, kiedy jeszcze sesja nie jest ustawiona, skrypt działa poprawnie i wyświetla angielski tekst tytułu. Kiedy jednak ktoś kliknie w link jakiegoś języka, wyświetlana jest tylko pierwsza litera tekstu z zaincludowanej zmiennej. Nie mam pojęcia, o co w tym chodzi.

Głupi problem i zapewne prosty w rozwiązaniu, ale nie pozwala mi się ruszyć dalej. Proszę o pomoc.

Link do tej stronki: http://www.footbag.p2.pl/footbagnews
scanner
Aż mnie zaskoczyło te pytanie...
Może coś po drodze modyfikuje tablicę z językami?
Cod
  1. <?php
  2. if(isset($HTTP_GET_VARS[&#092;"lang\"])) $HTTP_SESSION_VARS[\"lang\"]=$HTTP_GET_VARS[\"lang\"];
  3. else $HTTP_SESSION_VARS[&#092;"lang\"]=\"english\";
  4. $langdir=&#092;"lang/\".$HTTP_SESSION_VARS[\"lang\"].\"/lang_main.php\";
  5. include($langdir);
  6. ?>
  7. <html>
  8. <head>
  9. <script language=\"JavaScript\" type=\"text/javascript\"> 
  10. <!-- 
  11. if (self.parent.frames.length != 0) self.parent.location=document.location; 
  12. --> 
  13. </script>
  14. <meta http-equiv=\"Pragma\" content=\"NoCache\">
  15. <meta http-equiv=\"Expires\" content=\"0\">
  16. <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-2\">
  17. <?php
  18. echo &#092;"<title>footbagnews.com :: \".$lang[\"title\"].\"</title>\";
  19. ?>

Między includem a echo jest czysty HTML i JS. Nic niczego nie modyfikuje...

PS. Mnie też to bardzo zaskoczyło...
scanner
może na próbę zmień zawartość plików jezykowych i zamiast słow kluczowych wpisz tam po prostu "PL" i "EN" ?
...coś mi tu śmierdzi... tylko jeszcze nie wiem co...

BTW:
$_GET
$_SESSION
$_POST
...
bo mi się od $HTTP_*_VARS oczy męczą smile.gif
DeyV
Nie wchodząc w problem odczytywania tablicy lang, wydaje mi się, że sam mechanizm przehowywania języka jest błędny.
  1. <? if(isset($HTTP_GET_VARS[&#092;"lang\"])) $HTTP_SESSION_VARS[\"lang\"]=$HTTP_GET_VARS[\"lang\"];
  2. else $HTTP_SESSION_VARS[&#092;"lang\"]=\"english\"; ?>

W ten sposób nigdyy nie sprawdzasz, czy czasem już nie jest w sesji informacja na temat języka.

Ja to robię zazwyczaj tak:
1. sprawdzam czy jest info o języku w get
2. jeśli 1 tak, sprawdzam czy istnieje taki język
3. jeśli 2 tak - zapisuje do sesji
4. jeśli 1 nie - sprawdzam czy jest język w sesji
5. jeśli 4 nie - przypisuje domyślny język do sesji
scanner
Po konsultacjach na GG dotarliśmy do tego, że zaczęlo działać po zmianie nazy tanblicy z $lang na inną..
Jestem zdumiony...
DeyV
a ja chyba rozumiem.
Jest to efekt połaczenia pracy na zmiennych superglobalnych z register_globals=on
Już dawno temu raportowałem, że takie połaczenie może być bardzo niebezpieczne, z uwagi na to, że dla skryptu zmienne
$lang i $HTTP_GET_VARS["lang"] są w takim przypadku równoznaczne (to tak, jakby skorzystać z session_register()

Na szczęscie w przypadku korzystania z $_SESSION w nowych wersjach php nie spotykamy się (chyba) z tym problemem.
scanner
DeyV, ale to nie tłumaczy pokazywania tylko pierwszego znaku. nadpisywać ok, może. Ale sprawdzaliśmy var_exportem i to co on pokazuje normaklnie w <title> jest wstawianie jako $...[0] - a takiej konstrukcji w kodzie nie ma nawet.
Zamiana na $_* też niewiele dała.
Pomaga jedynie zmiana nazwy tablicy.
Kod widziałem, jest na moje oko cały poprawny.
tsharek
mogę dokładnie potwierdzić że to co pisał DeyV jest prawdą. pare razy już zdażała mi się taka sytuacja jak właśnie był register globals na on. wydaje mi się że php wtedy miesza coś z typami. wtedy dokładnie pojawia się 1 litera danego stringu.
DeyV
1. zmiana register_globals = off od razu rozwiązuje problem
2. użycie $_SESSION samo w sobie nie pomaga

A przyczyna takiego zachowania jest taka:
z uwagi na to, że według variables_order Session jest wyżej, niż zwykłe zmienne, więc tablica $langs zostaje nadpisane stringiem $_SESSION["lang"]

Jednak my nadal staramy się odwoływać do tej zmiennej, jak do tablicy.
pisząc:
$langs['test'] php nie znajduje takiego pola, stwierdza natomiast, że $langs nie jest tablicą asocjacyjną.
Konwertuje więc słowo 'test' na int, (w efekcie otrzymuje 0 i sprawdza, czy istnieje taki index w naszej pseudo tablicy.
Co prawda nie istnieje, ale php 4 pozwala na odwoływanie się do kolejnych znaków stringa poprzez $string[ $i ] więc w wyniku otrzymujemy znak nr. 0 naszego stringa.

Nie bardzo wiem tylko, jak zachodzi transformacja, w wyniku której w $langs nie znajduje się napis 'english' tylko 'xnglish' ale to musi być jakoś związane z sobą.

edited.
Już wiem jak. W wyniku działania variables_order i nadpisywania zmiennych nie dochodzi do czystego nadpisania zmiennej (na zasadzie $lang = $_SESSION["lang"] ) tylko na połączeniu tych zmiennych, gdzie nasza zmienna jest wrzucana na koniec zmennej tablicowej w sessji. Oczywiście gdy jest to tablica.
Gdy w sessji jest string, zachodzi ta dziwna konwersja typów, czego efekty dało się zauważyć.



Jak z tym walczyć?
Ja używam prefixów w zmiennych sessyjnych (stare przyzwyczajenie, ale przydatne, bo nie zawsze można wymusić przełączenie na register_globals =off
scanner
Czyli kłaniają się stanbdardykodowania...
$arrlang i po sprawie...

albo OOP:
  1. <?php
  2.  
  3. echo Lang::Get('en', 'test');
  4. echo Lang::Get('pl', 'test');
  5.  
  6. class Lang
  7. {
  8. function Get( $lang, $id )
  9. {
  10. $languages['pl']['test'] = 'Test polski';
  11. $languages['en']['test'] = 'Test angielski';
  12.  
  13. return $lang[$lang][$id];
  14. }
  15. // zaczerponiete z Seth'owego XBS'a
  16.  
  17. ?>
Cod
Dzięki wszystkim za rozwiązanie problemu i szczegółowe wyjaśnienie, o co chodziło. Niestety nie mogę wyłączyć register_globals, więc pozostaje mi podmianka jednego "lang" na coś innego. Tak właśnie zrobiłem i wszystko jest git.

cool.gif
Liko
Jeżeli możesz kozystać z plików .htaccess to możesz wyłączyć register_globals. Stworz plik ".htaccess" i wpisz w nim taką treść:
Kod
php_flag register_globals 0


Nie wiem czy tak, ale prawodopodobne tak.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.