Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem początkującego - dlaczego nie działa ten kod?
Forum PHP.pl > Forum > XML, AJAX > AJAX
m010ch
Witam.

Zakupiłem niedawno książkę: "AJAX i PHP. Tworzenie interaktywnych aplikacji internetowych" (wyd. Helion) i mam niestety problem już na pierwszym przykładzie z tej książki (zapewne jakiś błąd w druku, bo kod jest prawie że w 100% skopiowany z książki). Niestety - moja mała (jeszcze) wiedza na temat AJAKSA nie pozwala mi rozwiązać problemu samodzielnie (uprzedzając pytania - Google też nie pomogło).

Plik index.html:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  4. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  5.  
  6. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl">
  7. <head>
  8. <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
  9. <title>AJAX i PHP: Szybki start</title>
  10. <script type="text/javascript" src="quickstart.js"></script>
  11. </head>
  12. <body onload="process()">
  13. <p>Serwer chce poznać Twoje imię: <input type="text" id="myName" /></p>
  14. <p id="ajaxMessage" />
  15. </body>
  16. </html>


Plik quickstart.js:

Kod
var xmlHttp = createXmlHttpRequestObject();

function createXmlHttpRequestObject() {
    var xmlHttp;

    if (window.ActiveXObject) {
        try {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (e) {
            xmlHttp = false;
        }
    }
    else {
        try {
            xmlHttp = new XMLHttpRequest();
        }
        catch (e) {
            xmlHttp = false;
        }
    }
    
    if (!xmlHttp) {
        alert("Błąd podczas tworzenia obiektu XMLHttpRequest!");
    }
    else {
        return xmlHttp;
    }
}

function process() {
    if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0) {
        name = encodeURIComponent(document.getElementById("myName").value);
        xmlHttp.open("GET", "quickstart.php?name=" + name, true);
        xmlHttp.onreadystatechange = handleServerResponse;
        xmlHttp.send(null);
        xmlHttp.overrideMimeType("application/xhtml+xml; charset=utf-8");
    }
    else {
        setTimeout("process()", 1000);
    }
}

function handleServerResponse() {
    if (xmlHttp.readyState == 4) {
        if (xmlHttp.status == 200) {
            xmlResponse = xmlHttp.responseXML;
            xmlDocumentElement = xmlResponse.documentElement;
            helloMessage = xmlDocumentElement.firstChild.data;
            document.getElementById("ajaxMessage").innerHTML = "<em>" + helloMessage + "</em>";
            setTimeout("process()", 1000);
        }
        else {
            alert("Wystąpił błąd podczas uzyskiwania dostępu do serwera: " + xmlHttp.statusText);
        }
    }
}


Plik quickstart.php:

  1. <?php
  2. header("Content-Type: text/xml; charset=utf-8");
  3.  
  4. echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
  5. echo '<response>';
  6.  
  7. $name = $_GET['name'];
  8. $userNames = array('MICHAŁ', 'FILIP', 'MARCIN', 'RAFAŁ', 'GRZEGORZ');
  9.  
  10. if (in_array(strtoupper($name), $userNames)) {
  11. echo 'Witaj mistrzu ' . htmlentities($name) . '!';
  12. }
  13. else if (trim($name) == '') {
  14. echo 'Nieznajomy, podaj swoje imię!';
  15. }
  16. else {
  17. echo htmlentities($name) . ', nie znam Cię!';
  18. }
  19.  
  20. echo '</response>';
  21. ?>


Po otworzeniu strony pod Firefoksem, Firebug wyrzuca cały czas jeden i ten sam error:

  1. xmlResponse has no properties
  2. Line 47


Moje pytanie brzmi - w jaki sposób poprawić wywołanie funkcji handleServerResponse(), tak aby kod ten wreszcie zaczął działać?

Z góry dziękuję za pomoc.
atomek4
Cześć,

ta książka ma kilka takich niedoróbek. Ściągnij kody źródłowe ze strony Heliona i porównaj ze swoim kodem.
m010ch
Cytat(atomek4 @ 30.09.2007, 08:00:25 ) *
ta książka ma kilka takich niedoróbek. Ściągnij kody źródłowe ze strony Heliona i porównaj ze swoim kodem.

Uwierz mi to pierwsze co zrobiłem - kod jest identyczny jak ten w książce.

Aczkolwiek uruchomiłem go przed chwilą i... skrypt zaczął działać winksmiley.jpg Najlepsze jest to, że mój doprowadziłem do identycznej postaci i dalej nic. Spróbowałem podejść do sprawy od innej strony i sprawdziłem kodowania w jakich tworzone były pliki na potrzeby książki - okazało się, że właśnie tu leży problem! Pliki quickstart.js i quickstart.php stworzone przez autora, kodowane były w ISO-8859-2 - ja mam automatycznie ustawione kodowanie UTF-8 dla wszystkich plików. Po zmianie w Notepad++ na Koduj w ANSI (+ Koduj w UTF-8 bez BOM) - zaczęło działać smile.gif

Pytanie jednak mam nadal - dlaczego pliki te mają problemy z działaniem przy ustawionym kodowaniu UTF-8?

p.s. Widzę, że nadal są problemy z polskimi znakami sad.gif Gdy wpisze w inputa: Filip, Marcin czy Grzegorz, skrypt działa oka, ale gdy próbuje użyć go dla imienia: Rafał czy Michał dostaje:

Kod
Błąd parsowania XML: niezdefiniowana jednostka Obszar: http://localhost/ajax/quickstart/quickstart.php?name=Rafa%C5%82 Numer linii 1, kolumna 70:

Kod
Błąd parsowania XML: niezdefiniowana jednostka Obszar: http://localhost/ajax/quickstart/quickstart.php?name=Micha%C5%82 Numer linii 1, kolumna 71:
atomek4
Sprawdziłem, wydaje mi się, że problem leży w BOM-ie. Pliki w paczce z Helion Notepad++ rozpoznawał jako ANSI as UTF-8 bez BOM. Natomiast po zapisaniu pliku .php zwykłym UTF z BOM wszystko siada.
Dzieje się tak dlatego, ponieważ plik .php ma za zadanie wygenerować dokument XML a nie może prawidłowo ustawić header'a gdy już coś wysłał. (BOM). Wystarczy uruchomić sam plik .php żeby się o tym przekonać. Pojawi się wtedy znany komunikat Cannot modify header information...

edit: jeśli korzystasz z Notepad++ to, to 'poprawne' kodowanie UTF-8, które nie będzie ci sprawiać problemów w PHP, to właśnie: ANSI as UTF-8 bez BOM
m010ch
Cytat(atomek4 @ 30.09.2007, 10:20:43 ) *
Dzieje się tak dlatego, ponieważ plik .php ma za zadanie wygenerować dokument XML a nie może prawidłowo ustawić header'a gdy już coś wysłał. (BOM). Wystarczy uruchomić sam plik .php żeby się o tym przekonać. Pojawi się wtedy znany komunikat Cannot modify header information...

Faktycznie - dzięki za wyjaśnienie.

Cytat(atomek4 @ 30.09.2007, 10:20:43 ) *
edit: jeśli korzystasz z Notepad++ to, to 'poprawne' kodowanie UTF-8, które nie będzie ci sprawiać problemów w PHP, to właśnie: ANSI as UTF-8 bez BOM

Tak - ustawiłem je jako domyślne dla wszystkich i faktycznie działa (co nie zmienia faktu, że błędy parsowania XML dla polskich ogonków w imieniu wpisanym do inputa, o których wspomniałem wyżej nadal występują...)

Dzięki za dotychczasową pomoc - jeżeli domyślasz się jeszcze co może powodować wspomniane przeze mnie problemy - podziel się proszę swoimi podejrzeniami snitch.gif
atomek4
Co parsowania ogonków, to w tych kodach z książki używane są funkcje:w pliku JS encodeURIComponent() a w PHP htmlentities" title="Zobacz w manualu PHP" target="_manual i to one powodują błędy, po usunięciu ich występowania wszystko działa. Z tego co pamiętam to adresy URL są właśnie kodowane Unikodem, czyli tak jak pliki, więc wydaje mi się zbędne.
m010ch
Dzięki - jesteśmy coraz bliżej rozwiązania problemu, ale jednak coś jeszcze jest nie tak winksmiley.jpg

Po usunięciu obu htmlentities() z quickstart.php i jednego encodeURIComponent() z quickstart.js - owszem - nie pokazuje już błędów parsowania XML, ale za to skrypt nie działa jak powinien.

Po wpisaniu imienia np. Michał dostaje:

Michał, nie znam Cię!

zamiast

Witaj mistrzu Michał!

Wygląda na to, że teraz 'ł' wpisane do inputa nie jest tożsame z 'ł' w tablicy userNames... :/
atomek4
Chyba wiem o co chodzi, błąd tym razem dotyczy funkcji strtoupper" title="Zobacz w manualu PHP" target="_manual. Ma ona problemy ze zrobieniem wielkiej litery z polskiego znaku. Rozwiązanie znalazłem na naszym forum.
Teraz kod w pliku .php, może wyglądać tak:
  1. <?php
  2. $userNames = array('CRISTIAN', 'BOGDAN', 'FILIP', 'MIHAI', 'YODA', 'MICHAŁ');
  3. $name = mb_convert_case($name, MB_CASE_UPPER, "UTF-8");
  4. if (in_array($name, $userNames))
  5. ?>


Oczywiście reszta tak samo. Mam nadzieję, że to rozwiąże problem smile.gif

edit
: Tak masz racje, bo ja już potem nie zmieniałem tych wielkich liter. Można by tą zamianę na wielkie wpisać w tym in_array (tak jak było poprzednio), bo tu chodzi tylko porównanie. Zmienna pozostała by wtedy niezmieniona. Ja tylko tak napisałem, żeby było czytelniej.

Nie ma za co, po to jest forum. Sam mam tą książkę, ale tak szczegółowo to nawet nie analizowałem tego przykładu przy czytaniu. smile.gif
m010ch
Dzięki wielkie atomek4! smile.gif

Problem został prawie rozwiązany. Prawie - bo teraz po wpisaniu jakiegoś imienia zawsze dostaję w odpowiedzi to imię dużymi literami, np.:

Witaj mistrzu MICHAŁ!

Na szczęście - samodzielnie poradziłem sobie z tym problemem - poniżej rozwiązanie dla zainteresowanych:

1. Zamieniamy drugi parametr w funkcji mb_convert_case z MB_CASE_UPPER na MB_CASE_TITLE.
2. Ta zmiana wynika z pierwszej - w tablicy przechowującej imiona musimy zmienić zapis tych imion z pisanych dużymi literami, na pisane małymi literami z pierwszą literą dużą (czyli np. $userNames = array('Michał', 'Filip', 'Marcin', 'Rafał');)

Teraz - niezależnie czy do inputa wpisze się "Michał", "michał" czy "MICHAŁ", w odpowiedzi otrzyma się zawsze oczekiwane, czyli:

np. Witaj mistrzu Michał!

atomek4 - jeszcze raz dzięki za pomoc!
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.