Sortowanie po kliknięciu na nagłówek kolumny.

Języki, których efekty są wykonywane po stronie serwera. PHP, ASP czy CGI w połączeniu z bazami danych SQL dają niezwykłe możliwości budowy i zarządzania stron WWW. Tu zadajemy pytania oraz demonstrujemy kod, z którym mamy problem.
joka2
Nowy
Nowy
Posty: 62
Rejestracja: śr lis 15, 2006 5:02 pm
Kontakt:

Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: joka2 »

Temat: Sortowanie kolumn :)

Witam serdecznie.

Rozgryzłem pewien problem, jaki mnie nurtował (sortowanie kolumn), ale nie sądzę, żeby to było uniwersalne rozwiązanie...

posiadam plik: "wynik_nr.inc"

[php]

<?php

$zapytanie = "
SELECT *
FROM dane
ORDER BY id_nr";

$conn=mysql_connect("localhost", "123");
mysql_select_db("test", $conn);


$wynik = mysql_query($zapytanie) or die(Mysql_error());

echo ("<table width=\"300\" border=\"1\">");
echo ("<tr>");
echo ("<td><a href=index.php?go=wynik_nr>Nr.</a></td>");
echo ("<td><a href=index.php?go=wynik_nazwisko>Nazwisko</a></td>");
echo ("<td><a href=index.php?go=wynik_imie>Imie</a></td>");
echo ("</tr>");

while($rekord = mysql_fetch_array($wynik))

{
$nr = $rekord[id_nr];
$nazwisko = $rekord[nazwisko];
$imie = $rekord[imie];

echo ("<tr>");
echo ("<td>$nr</td>");
echo ("<td>$nazwisko</td>");
echo ("<td>$imie</td>");
echo ("</tr>");
}

echo ("</table>");

?>
[/php]

drugi plik to: "wynik_imie.inc"

[php]
<?php

$zapytanie = "
SELECT *
FROM dane
ORDER BY imie";

$conn=mysql_connect("localhost", "123");
mysql_select_db("test", $conn);


$wynik = mysql_query($zapytanie) or die(Mysql_error());

echo ("<table width=\"300\" border=\"1\">");
echo ("<tr>");
echo ("<td><a href=index.php?go=wynik_nr>Nr.</a></td>");
echo ("<td><a href=index.php?go=wynik_nazwisko>Nazwisko</a></td>");
echo ("<td><a href=index.php?go=wynik_imie>Imie</a></td>");
echo ("</tr>");

while($rekord = mysql_fetch_array($wynik))

{
$nr = $rekord[id_nr];
$nazwisko = $rekord[nazwisko];
$imie = $rekord[imie];

echo ("<tr>");
echo ("<td>$nr</td>");
echo ("<td>$nazwisko</td>");
echo ("<td>$imie</td>");
echo ("</tr>");
}

echo ("</table>");


?>[/php]

oraz trzeci plik: "wynik_nazwisko.inc"

[php]
<?php

$zapytanie = "
SELECT *
FROM dane
ORDER BY nazwisko";

$conn=mysql_connect("localhost", "123");
mysql_select_db("test", $conn);


$wynik = mysql_query($zapytanie) or die(Mysql_error());

echo ("<table width=\"300\" border=\"1\">");
echo ("<tr>");
echo ("<td><a href=index.php?go=wynik_nr>Nr.</a></td>");
echo ("<td><a href=index.php?go=wynik_nazwisko>Nazwisko</a></td>");
echo ("<td><a href=index.php?go=wynik_imie>Imie</a></td>");
echo ("</tr>");

while($rekord = mysql_fetch_array($wynik))

{
$nr = $rekord[id_nr];
$nazwisko = $rekord[nazwisko];
$imie = $rekord[imie];

echo ("<tr>");
echo ("<td>$nr</td>");
echo ("<td>$nazwisko</td>");
echo ("<td>$imie</td>");
echo ("</tr>");
}

echo ("</table>");

?>[/php]

To są PRAWIE takie same pliki. Jedyna różnica, to ORDER BY ????.

To rozwiązanie jest pracochłonne przy modyfikacji ilości kolumn. Już tłumaczę. Przypuśćmy, że będę chciał dodać do bazy kolumnę adres. Będę zmuszony dodać tą kolumnę we wszystkich trzech plikach, a także dodać czwarty plik z sortowaniem po adresie.

Baaaardzo pracochłonne przy tabeli z 12 kolumnami :(

A na dodatek, jak bym chciał posortować malejąco??? To kolejne pliki będą się mnożyć na serwerze jak króliki na wiosnę ;)

Chciałbym, aby nagłówki kolumn przekazywały zmienną, która to wpisywała by się do ORDER BY $zmienna, wpływając na JEDEN plik

Sądzę, że da się to zrobić, tylko jak?

Czy ktoś ma jakiś pomysł?
koziolek
Przelotem
Przelotem
Posty: 387
Rejestracja: sob paź 21, 2006 10:07 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: koziolek »

Niech link nagłówek tabeli będzie linkiem o takiej oto konstrukcji:

Kod: Zaznacz cały

www.twojastrona.pl/sortuj.php?sortuj=imie
Następnie zwykłym switchem lub kilkoma ifami twórz zapytanie (wersja prosta):
[php]<?php
$sortBy = $_GET["sortuj"];
$query="Select * from tabela order by ".$sortBy.";";
?>[/php]

Po prostu to wg czego ma być sortowanie ma być przekazywane jako parametr w GET. Wada takiego prostego rozwiązania to to że ujawniasz nazwy tabel z DB.
joka2
Nowy
Nowy
Posty: 62
Rejestracja: śr lis 15, 2006 5:02 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: joka2 »

Hej.
Bardzo przyjemne rozwiązanie mojego problemu :)
Dziękuję.

PS. A może jakieś inne rozwiązanie istnieje?
PS2. Dla poszukujących zmodyfikowany kod:
[php]
<?php

$sort = $_GET["sortuj"];

$zapytanie = "
SELECT *
FROM dane
ORDER BY ".$sort."
";

$conn=mysql_connect("localhost", "123");
mysql_select_db("test", $conn);


$wynik = mysql_query($zapytanie) or die(Mysql_error());

echo ("<table width=\"300\" border=\"1\">");
echo ("<tr>");
echo ("<td><a href=index.php?go=wynik_nr&sortuj=id_nr>Nr.</a></td>");
echo ("<td><a href=index.php?go=wynik_nr&sortuj=nazwisko>Nazwisko</a></td>");
echo ("<td><a href=index.php?go=wynik_nr&sortuj=imie>Imie</a></td>");
echo ("</tr>");

while($rekord = mysql_fetch_array($wynik))

{
$nr = $rekord[id_nr];
$nazwisko = $rekord[nazwisko];
$imie = $rekord[imie];

echo ("<tr>");
echo ("<td>$nr</td>");
echo ("<td>$nazwisko</td>");
echo ("<td>$imie</td>");
echo ("</tr>");
}

echo ("</table>");

?>[/php]
koziolek
Przelotem
Przelotem
Posty: 387
Rejestracja: sob paź 21, 2006 10:07 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: koziolek »

Istnieje ale tylko mam pytanie czy Ci się chce bawić w AJAXa?

Zamiast linku można na onclick dla komórki nagłówka wywoływać funkcję AJAXową która wyciągnie z serwera już posortowaną tabelę (php bez zmian), a następnie podmieni z tą która jest na stronie.

Nie będzie wtedy takiego nieprzyjemnego "mrygania" związanego z przeładowaniem strony.
Kicok
Posty: 2
Rejestracja: czw lut 08, 2007 12:43 pm

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: Kicok »

Nie należy tez zapominać o zabezpieczeniu skryptu przed atakami typu SQL injection

[php]
<?php

$sort = $_GET["sortuj"];
if(!get_magic_quotes_gpc())
{
$sort = mysql_escape_string($sort);
}

$zapytanie = "
SELECT *
FROM dane
ORDER BY ".$sort."
";

?>
[/php]
koziolek
Przelotem
Przelotem
Posty: 387
Rejestracja: sob paź 21, 2006 10:07 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: koziolek »

SQLInjection można ominąć jeszcze poprzez nieujawnianie nazwy tabeli. Blok switch-case. Po prostu wtedy nie dopuszczamy do bezpośredniego przesyłania nazw tabeli, ale o tym już pisałem.
joka2
Nowy
Nowy
Posty: 62
Rejestracja: śr lis 15, 2006 5:02 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: joka2 »

O!
Jak dużo informacji. Dzięki za wszystkie :)

Ad. zabezpieczenie: Raczej nie będę tego potrzebować, ponieważ tylko ja jestem użytkownikiem tej bazy :) Ale nie omieszkam wypróbować.

Ad. AJAX'a: Tego na razie nie dotykam. Może kiedyś?

Ad. Blok switch-case: Poszukam o tym na forum.

Natomiast...
Zastanawiam się, czy jest możliwe powtórzenie sortowania (no jest, wystarczy jeszcze raz kliknąć nagłówek)...
Ale...
chciałbym, aby wynik był malejący (DESC). Obecnie jest default (ASC).
I znowu się kłaniają zmienne :)

Chyba coś z pętlą IF na samym początku powinno być.
Jeżeli zmienna $UPorDOWN to:

Kod: Zaznacz cały

SELECT *
FROM dane
ORDER BY ".$sort." ".$UPorDOWN."
gdzie UPorDOWN to sytuacja, gdy zmienna jest równa UP lub DOWN.

No i w linku też powinno się dodać wywolanie zmiennej

Kod: Zaznacz cały

<a href=index.php?go=wynik&sortuj=imie&UPorDOWN=$UPorDOWN>Imię</a>
Tiaaaa....
No to teraz jak to ubrać w kod???
Salfunglandyare
Nowy
Nowy
Posty: 88
Rejestracja: śr sty 24, 2007 9:52 pm
Lokalizacja: Kuj-Pom.

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: Salfunglandyare »

ad zabezpieczenie: nie tyle ty (w tym przypadku) masz dostęp do bazy, co skrypt. jeśli ktoś chce nabroić Tobie w bazie wystarczy że w url'u da

Kod: Zaznacz cały

...&UPorDOWN=desc"; delete from dane;
twoje zapytanie przyjmuje postać:

Kod: Zaznacz cały

SELECT *
FROM dane
ORDER BY costam desc; delete from dane;
co wiadomo jak się skończy :) To oczywiście zależy od serwera, czy tego potrzebujesz (magic quotes).

ad ubrania sortowania w kod: domyślnie chcesz sortować rosnąco (asc), dopiero po drugim kliknięciu - malejąco. Więc jeśli już sortujesz po pewnej kolumnie której nazwę masz w zmiennej $sort, wtedy:

Kod: Zaznacz cały

'<a href=index.php?go=wynik&sortuj=imie&UPorDOWN='.((($sort=='imie')&&($UPorDOWN=='asc'))?'desc':'asc').'>Imię</a>'
można oczywiście inaczej, np. przez switch :)

pzdr.
123456
Zaczyna działać
Zaczyna działać
Posty: 514
Rejestracja: sob paź 28, 2006 1:19 pm

...

Post autor: 123456 »

twoje zapytanie przyjmuje postać:
[sql]
SELECT *
FROM dane
ORDER BY costam desc; delete from dane;
[/sql]
co wiadomo jak się skończy. To oczywiście zależy od serwera
Patrząc na kod który przedstawił joka2 to takie zapytanie nie zostanie wykonane. Dlaczego? Na to pytanie niech odpowie sobie kto tam będzie chciał. Trzeba zwracać uwagę na kontekst całego tematu...
O!
Jak dużo informacji. Dzięki za wszystkie
Żałuje tylko, że są to informacje o tak niskim poziomie. Zapewniam Cię, że biorąc pod uwagę to co zostało napisane nadal wykonałbym SQLInjection. Programując trzeba myśleć o aplikacji jak o potencjalnej ofierze włamu... Ot tyle mojego wymądrzania się bo i tak mnie zjadą za wszystko.

P.S. Strasznie spadł poziom tego forum. Ciągle jakieś banalne pytania i problemy. Nie mam nic do newbie ale szkoda, że nic nie można się od nikogo nauczyć. Bardzo szkoda...
Salfunglandyare
Nowy
Nowy
Posty: 88
Rejestracja: śr sty 24, 2007 9:52 pm
Lokalizacja: Kuj-Pom.

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: Salfunglandyare »

Oczywiście, że nadal jest możliwość wykonania sqlinj. Podałem tylko prosty przykład, w jaki sposób to wygląda ale powiem szczerze, że przy lekkiej modyfikacji takie zapytanie UDAJE się wykonać.
Prawda jest taka, że NIGDY nie powinno się przekazywać bezpośrednio parametru użytkownika w zapytaniu SQL. Jeśli podaje się nazwę pola, dobrze umieścić je między znaki `, a najlepiej wybierać poprzez switch. Tym samym mysql_escape_string nic w tym przypadku nie pomoże.
O projektowaniu aplikacji - masz rację i zgadzam się z Tobą w całej rozciągłości, nie tylko jeśli chodzi o SQL, ale także o pliki, eval czy wykonywanie poleceń systemowych. Korzystając dajmy na to z bibliotek typu xmlrpc przy źle zabezpieczonym serwerze można dokonać rzeczy zaskakujących i strasznych :)

pzdr.
joka2
Nowy
Nowy
Posty: 62
Rejestracja: śr lis 15, 2006 5:02 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: joka2 »

Witam ponownie :)

Rozwiązałem mój problem za pomocą dwóch linków obok nagłówka sortowanej kolumny.

Fragment kodu:

Kod: Zaznacz cały

	echo ("<td>");
	echo ("Nazwisko");
	echo (" <a href=index.php?go=dodaj&sortuj=nazwisko&upordown=ASC><img src=\"strona/up.gif\" border=\"0\" width=\"8\" height=\"9\"></a>");
	echo ("<a href=index.php?go=dodaj&sortuj=nazwisko&upordown=DESC><img src=\"strona/down.gif\" border=\"0\" width=\"8\" height=\"9\"></a>");
	echo ("</td>");
Natomiast kwerendę z bazy wykonałem tak.

Fragment kodu:

Kod: Zaznacz cały

$sort = $_GET["sortuj"];
$upordown = $_GET["upordown"];

$result=mysql_query("

SELECT * FROM baza
ORDER BY ".$sort." ".$upordown."

", $conn);
Nadal jednak zastanawia mnie jak wykonać TYLKO jeden link (zamiast dwóch), do sortowania rosnącego i malejącego. Może te dwa da się przerobić na jeden???

Dzięki za odpowiedzi.
Pozdrawiam.
koziolek
Przelotem
Przelotem
Posty: 387
Rejestracja: sob paź 21, 2006 10:07 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: koziolek »

Zamiast generować dwa linki możesz generować jeden z instrukcją warunkową
[php]<?php

if($sort==''ASC'){
$SORT_NEW = "DESC";
}
else{
$SORT_NEW = "ASC";
}
/*
....
*/
echo ("<a href=index.php?go=dodaj&sortuj=nazwisko&upordown=$SORT_NEW><img src=\"strona/down.gif\" border=\"0\" width=\"8\" height=\"9\"></a>");

?>[/php]
joka2
Nowy
Nowy
Posty: 62
Rejestracja: śr lis 15, 2006 5:02 pm
Kontakt:

Re: Sortowanie po kliknięciu na nagłówek kolumny.

Post autor: joka2 »

O!
Działa :)

Dziękuję

PS. trochę zmodyfikowałem na potrzeby mojej bazy:
[php]<?php

if($upordown=='ASC'){
$SORT_NEW = "DESC";
}
else{
$SORT_NEW = "ASC";
}

?>[/php]
ODPOWIEDZ