Wątek przeniesiony 2014-12-29 19:31 z PHP przez dzek69.

Zamiast nazwiska z polskimi znakami pobiera null

0

Witam.
Ćwiczę sobie pobieranie danych za pomocą jQuery, ćwiczę robiąc klasyczną "Bibliotekę". Wszystko szło jak pomaśle, kiedy napotkałem na pewien dziwny błąd. Mianowicie mam problem związany z pobieraniem danych z bazy danych. Pobieram listę książek, i tam gdzie pojawi mi się jaki kolwiek String który zawiera polski znak, pobierany jest z bazy jako NULL mimo że w niej (podgląd za pomocą phpMyAdmin) wszystko jest normalnie, dla bazy ustawiłem porównywanie napisów na utf8_polish_ci.

Po drugie, wynik zapytania na stronie jest zupełnie inny niż na bazie danych.
Powtarzają się dane, drugie się nie wyświetlają, następne mają null, lub mają skrócone nazwy.

Nie rozumiem czemu tak się dzieje, proszę o pomoc.

Screen z bazy:

baza.jpg

Adres do aplikacji: www.storin.rdl.pl/jquery

Oto kod PHP z zapytaniami:

<?php
    include_once "connection.php";
    
global $akcja;
$akcja = $_POST['akcja'];     
$akcjaGET = $_GET['akcja']; 


// DODAWANIE
if($akcja == 'dodajKsiazke'){
    $nazwa = $_POST['nazwa'];
    $isbn =  $_POST['isbn'];
    $autor =  $_POST['autor'];
    $polka = $_POST['polka'];
    
    $query = mysql_query("INSERT INTO `ksiazki`(`nazwa`, `isbn`, `autor_id`, `polka`) VALUES ('$nazwa', '$isbn', $autor, $polka)");

// Zwracanie ID ostatnio utworzonego INSERT'A    
    $lastId = array();
    $lastId['lastId'] = mysql_insert_id(); 
    //echo $lastId; 
    echo json_encode($lastId);    
 
// LISTA KSIĄŻEK    
} else if($akcja == 'pokazKsiazki' || $akcjaGET == 'pokazKsiazki'){
    $query = mysql_query("SELECT ksiazki.id, ksiazki.nazwa, ksiazki.isbn, autor.imie, autor.nazwisko, ksiazki.polka  FROM ksiazki, autor WHERE ksiazki.autor_id = autor.id "); 
    
    if(mysql_num_rows($query) > 0){
        while($row = mysql_fetch_object($query)){
            $ksiazki[] = $row; 
        }
    }
    
    echo json_encode($ksiazki);   
    //echo "1"; 
} else if($akcja == 'edytujKsiazke'){
    //echo "1";
    
    $set = ""; 
    $idEdit = $_POST['idEdit']; 
    
    if(isset($_POST['nazwaEdit'])){
        $nazwa = $_POST['nazwaEdit']; 
        $set .= "nazwa='".$nazwa."', "; 
    }
    if(isset($_POST['isbnEdit'])){
        $isbn =  $_POST['isbnEdit'];
        $set .= "isbn='".$isbn."', ";
    }
    if(isset($_POST['autorEditId'])){
        $autor =  $_POST['autorEditId'];
        $set .= "autor_id=".$autor.", ";
    }
    if(isset($_POST['polkaEdit'])){
        $polka = $_POST['polkaEdit'];
        $set .= " polka=".$polka;
    }
    //echo $idEdit; 
    //echo $set;
    //echo $idEdit; 
     
    mysql_query("UPDATE ksiazki SET $set WHERE id = $idEdit");
    echo "1";
} else if($akcja == "usunKsiazke"){
    
    $idUsun = $_POST['idUsun'];
    
    mysql_query("DELETE FROM ksiazki WHERE id = $idUsun"); 
    echo "1"; 
    
} else if($akcja == 'pokazAutor'){
     $query = mysql_query("SELECT * FROM autor"); 
    
    if(mysql_num_rows($query) > 0){
        while($row = mysql_fetch_object($query)){
            $autor[] = $row; 
        }
    }
    echo json_encode($autor);   
    
}

?>
1

Zmień kodowanie na uft8 unicode, używaj biblioteki PDO, filtruj jakoś dane bo teraz Ci każdy moze zdropować baze bez większego problemu. Wyrazy są skracane najczęściej od momentu napotkania niewłaściwego znaku, tj. polskiego.

0

Zmiana kodowania niestety nie pomogła. Robiłem identycznie to samo wcześniej używając biblioteki mysql i nie było żadnych problemów.
Czy zmiana na PDO ma faktycznie jakieś znaczenie w tym problemie czy to tylko rada ?

1

To jest rada, bo w tym momencie kod masz dziurawy jak sito.

polecenie SET NAMES (googluj co dalej :>) na 99% naprawi problem

0
 
<?php

$connection = mysql_connect('*****', '*****', '*****'); 
if($connection){
    echo " Połączenie udane"; 
}
mysql_select_db("*******"); 
mysql_query("SET NAME 'utf8'"); 

if(!$connection){
    die('Błąd połączenia z bazą danych: ' . mysql_error()); 
}

//echo 'Połączenie prawidłowe'; 


?>

Miałem to od początku.
Czyli rozumiem połączenie do bazy i wysyłanie zapytań jest bezpieczniejsze ? PDO nie przyjmuje zapytań w wysyłanych danych INSERT INTO ?

1

SET NAME, a SET NAMES to jest chyba różnica, nieprawdaż?

Co do PDO - tam nie budujesz (można, ale nie powinieneś) zapytań sam, tylko masz coś takiego:

$sth = $dbh->prepare('INSERT INTO `ksiazki`(`nazwa`, `isbn`, `autor_id`, `polka`) VALUES (:nazwa, :isbn, :autor_id, :polka)');
$sth->bindParam(':nazwa', $_POST['nazwa'], PDO::PARAM_STR, 50);
$sth->bindParam(':isbn', $_POST['isbn'], PDO::PARAM_STR, 20);
$sth->bindParam(':autor_id', $_POST['autor'], PDO::PARAM_INT);
$sth->bindParam(':polka', $_POST['polka'], PDO::PARAM_INT);
$sth->execute();

Nie podając żadnych zmiennych wewnątrz zapytania bezpośrednio, tylko poprzez bindParam (lub bindValue - poczytaj w manualu jaka jest różnica) zabezpieczasz się przed SQLInjection. Zauważ, że w bindParam definiujesz dodatkowo (wedle potrzeby, domyślnie jest to string) spodziewany typ zmiennej, oraz ew. maksymalną długość (jak w bazie).

Kolejna rzecz: Mówiłeś, że w phpMyAdmin masz dobrze, a ID 30 jest źle ;)

0

Dziękuje bardzo za pomoc, za chwile przerobie sobie wszystko na PDO.

Co do problemy z wyświetlaniem nulla, SET NAMES załatwiło sprawę, pozostał jednak jeszcze problem błednie wyświetlanych danych, response json'a jest ok, jednak pliki są źle wyświetlane w tabeli co dla mnie też jest nie wytłumaczalne.

Screen tego problemu:

response.jpg

1

Ale co Ci się źle wyświetla? Pan Wołodyjowski? Przecież to już w bazie masz źle! (na co zwróciłem Ci uwagę w poprzednim poście)

0

Zobacz jakie rekordy mam w bazie danych, a jakie mi się wyświetlają w aplikacji. Pan Wołodyjowski źlę się wyświetla ponieważ umieszczałem go w bazie poprzez aplikacje, i bez kodowania się tak zapisał, ale na niego w ogóle nie zwracam uwagi, chodzi mi o niezgodność rekodrdów, a nawet powtarzanie się kilku (3 ostatnie).

1

Poczytaj o (LEFT) JOIN - i pierwsze zapytania popróbuj sobie wykonywać w phpMyAdmin, zanim przerobisz je na kod - tak żebyś widział jak Twoje eksperymenty wpływają na wyniki

0

Zapytanie jest dobre, wyświetliłem specjalnie obok response jaki otrzymałem z pliku PHP z zapytaniami, przetestowałem te zapytanie bezpośrednio w phpMyAdmin, jak i w shellu i wszędzie jest dobrze, problem jest z wyświetlaniem tych danych w przeglądarce, z jakiegoś powodu wyświetla źle. Załącze do tego kod JS.

 
function loadBookList(){
    
    $.ajax({
        type: "POST",
        url: "querys.php", 
        dataType: 'json', 
        data: {
            akcja : 'pokazKsiazki'
        },
        success : function(json){
            console.log(json);
            for(var klucz in json ){
                console.log(json[klucz[0]].id);
                
                var idGET = json[klucz[0]].id; 
                var nazwaGET = json[klucz[0]].nazwa; 
                var isbnGET = json[klucz[0]].isbn; 
                var imieGET = json[klucz[0]].imie; 
                var nazwiskoGET = json[klucz[0]].nazwisko; 
                var polkaGET = json[klucz[0]].polka; 
                
                $("#tabela").append('<tr><td>'+idGET+'</td><td>'+nazwaGET+'</td><td>'+isbnGET+'</td><td>'+imieGET+' '+nazwiskoGET+'</td><td>'+polkaGET+'</td><td><a href="#" class="edit"><img src="img/edit.png" alt="Edytuj"/></a><a href="#" class="delete"><img src="img/delete.png" alt="Usuń"/></a></td></tr>');
                registerHandlers();
            }
        },
        error: function(blad){
         
          console.log(blad); 
        }

    }); 
}

Dodam że wcześniej bez SET NAMES, rekordy pobierane do pliku były odpowiednio, problem zaczynał się w momencie json_encode($ksiazki);, funkcja wysyłała rekordy z polskimi znakami jako null, lecz SET NAMES naprawiło problem.

1

Na screenshocie nie widać framentu z problematycznymi wpisami. Wklej tu całą odpowiedź serwera.

Druga rzecz - robisz kolejną dziurę - tym razem XSS i nieprzemyślane użycie append. Co, jeżeli jakaś książka będzie nosiła tytuł "<script>alert(1);</script>" ? No właśnie.

0

Wchodzi że zamiast potop II wyświetla się HP i kamień filizoficzny

Screeny:

Dane jakie są w aplikacji(niepoprawne):

aplikacja.jpg

To samo zapytanie, bezpośrednio w phpMyAdmin:

zapytanie.jpg

Wynik owego zapytania(poprawny):

wynik_zapytania.jpg

0

jsona wklej

0

Potop II na końcu jest jeden bo dwa pozostałe wywliłem, w aplikacji zamiast na koncy trzech kamieni zrobił się odpowiednio jeden.
W bazie dodatkowo jest jeszcze jakiś rekord, któruego tu nie ma ani w json, tym samym w aplikacji, jednak na początku interesuje mnie czemu zamiast Potop II pojawia się Harry Potter i Kamień Filozoficzny.

[{"id":"32","nazwa":"Harry Potter i Czara Ognia","isbn":"745698","imie":"J.K","nazwisko":"Rowling","polka":"7"},

{"id":"34","nazwa":"Harry Potter i Kamie\u0144 filozoficzny","isbn":"7458652222","imie":"J.K","nazwisko":"Rowling","polka":"7"},

{"id":"35","nazwa":"Harry Potter i Zakon Feniksa","isbn":"7845621","imie":"J.K","nazwisko":"Rowling","polka":"7"},

{"id":"36","nazwa":"Harry Potter i Wi\u0119zie\u0144 Askabanu","isbn":"5864125555","imie":"J.K","nazwisko":"Rowling","polka":"7"},

{"id":"41","nazwa":"\u0139\u009adasd","isbn":"21231","imie":"J.K","nazwisko":"Rowling","polka":"2"},

{"id":"25","nazwa":"Pan Tadeusz","isbn":"456789","imie":"Adam","nazwisko":"Mickiewicz","polka":"2"},

{"id":"26","nazwa":"Kordian","isbn":"789456123","imie":"Juliusz","nazwisko":"S\u0142owacki","polka":"1"},

{"id":"28","nazwa":"Ogniem i Mieczem","isbn":"4789651","imie":"Henryk","nazwisko":"Sienkiewicz","polka":"5"},

{"id":"29","nazwa":"Potop","isbn":"2700880990","imie":"Henryk","nazwisko":"Sienkiewicz","polka":"5"},

{"id":"30","nazwa":"Pan Wo\u0139\u0082odyjowski","isbn":"85642144","imie":"Henryk","nazwisko":"Sienkiewicz","polka":"5"},

{"id":"38","nazwa":"Potop II","isbn":"587496","imie":"Henryk","nazwisko":"Sienkiewicz","polka":"5"}] 
2

Powodem jest stosowanie [klucz[0]].
Dlaczego w ogóle tak robisz?

klucz jest stringiem, u Ciebie kolejno:
"0",
"1",
"2",
..,
"9",
"10",
"11",
"12",
"13",
.. // potem byłoby:
"19",
"20",
"21" ...

Robiąc string[0] wyciągasz pierwszy znak ze stringa.
Dla "1" to jest "1"
"2" => "2"
...
"9" => "9"
"10" => "1"
"11" => "1"
...
"20" => "2"
"21" => "2" (tu zaczęła by Ci się powtarzać trzecia książka z listy)

0

Zrobiłem to w ten sposób i działa :) Serdecznie dziękuje za cierpliwość i pomoc :)


function loadBookList(){
    
    $.ajax({
        type: "POST",
        url: "querys.php", 
        dataType: 'json', 
        data: {
            akcja : 'pokazKsiazki'
        },
        success : function(json){
            console.log(json);
           // for(json ){
           for(var i = 0; i < json.length; i++){
                console.log(json[i].id);
                
                var idGET = json[i].id; 
                var nazwaGET = json[i].nazwa; 
                var isbnGET = json[i].isbn; 
                var imieGET = json[i].imie; 
                var nazwiskoGET = json[i].nazwisko; 
                var polkaGET = json[i].polka; 
                
                $("#tabela").append('<tr><td>'+idGET+'</td><td>'+nazwaGET+'</td><td>'+isbnGET+'</td><td>'+imieGET+' '+nazwiskoGET+'</td><td>'+polkaGET+'</td><td><a href="#" class="edit"><img src="img/edit.png" alt="Edytuj"/></a><a href="#" class="delete"><img src="img/delete.png" alt="Usuń"/></a></td></tr>');
                registerHandlers();
            }
        },
        error: function(blad){
         
          console.log(blad); 
        }

    }); 
}

 

1 użytkowników online, w tym zalogowanych: 0, gości: 1