Thursday, June 3, 2010

Minified URL | Κρατήστε τις GET μεταβλητές στο URL χωρίς να πιάνουν χώρο

4 comments
Πολλές φορές κάνετε post μία φόρμα για να κάνετε κάποιο search σε ένα site και θέλετε οι μεταβλητές να υπάρχουν στο URL έτσι ώστε να μπορεί κάποιος να στείλει πχ. αυτό το URL σε ένα φίλο του και να εκτελέσει ξανά το search αυτό.

Κάποιοι από σας μέχρι τώρα κάνατε χρήση της GET πχ:

http://www.diakopesTravelSearch.gr/search.php?dest=Athens&checkin_monthday=1&checkin_year_month=2010-9&checkout_monthday=3&checkout_year_month=2010-9 (ψεύτικο URL)
Εδώ θα εξηγήσουμε τον τρόπο για να γίνει το παραπάνω URL όπως το παρακάτω και να έχουμε πάλι πρόσβαση στις παραπάνω μεταβλητές:

http://www.diakopesTravelSearch.gr/search.php?token=WUXUY0Fq2T
Δηλαδή το URL από 149 χαρακτήρες πλέον θα έχει μόνο 62 και εννοείται ότι θα έχει πάντοτε 62, ακόμα και όταν αυξηθούν οι μεταβλητές από 5 που είναι παραπάνω σε 105!

Στην πράξη τώρα:

Αρχικά φτιάχνουμε έναν πίνακα στη βάση για να κρατάμε τα tokens που θα δημιουργούμε στη συνέχεια:

[sql]
CREATE TABLE IF NOT EXISTS `search_tokens` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`token` varchar(10) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`data` text NOT NULL,
PRIMARY KEY (`id`),
KEY `token` (`token`)
);
[/sql]

Στη φόρμα που κάνουμε το post αντί για το κλασσικό action της φόρμας και τη μέθοδο GET πχ:

[html]
<form action="http://www.diakopesTravelSearch.gr/search.php" method="get" name="searchForm">[/html]

θα χρησιμοποιούμε τη μέθοδο POST και το action μαζί με ένα τυχαίο string όπως παρακάτω:

[html]
<form action="http://www.diakopesTravelSearch.gr/search.php" token="php echo generate_token();" method="post" name="searchForm">[/html]

Η function που επιστρέφει το token (γίνεται έλεγχος για να μην υπάρχει το ίδιο στην βάση):

[php]
function generate_token(){
do{
$token = random_string(10);
$count = mysql_query("SELECT COUNT(*) FROM `search_tokens` WHERE `token` = $token");
} while($count != 0);
return $token;
}
[/php]

Εδώ θα μας χρειαστεί και η παρακάτω function για την παραγωγή ενός τυχαίου string 10 χαρακτήρων - αν θέλετε βάζετε και λιγότερους - αναλόγως πόσα search γίνονται το λεπτό! :-)

[php]
function random_string($length=10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
$string = "";
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters)-1)];
}
return $string;
}
[/php]

Οπότε μέχρι στιγμής έχουμε φτιάξει τη φόρμα με το σωστό URL.

Συνεχίζω...

Χρησιμοποιούμε την παρακάτω συνάρτηση και παίρνουμε τελικά τα data που έχουμε κάνει post

μέσα στην search.php

[php]
function get_post_data()
{
$my_token = $_GET['token'];
if(empty($_POST))
{
if(!empty($my_token))
{
$tokenSearch = mysql_query("SELECT data FROM search_tokens WHERE token = $my_token") or die(mysql_error());
if(mysql_num_rows($tokenSearch) > 0)
{
$row = mysql_fetch_row($tokenSearch);
$post_data = unserialize($row[0]);
return $post_data;
}else
die("Error.Invalid token.Maybe this search has expired.");
}else
die("Error.Nothing was posted!");
}
mysql_query("INSERT INTO search_tokens (data, token) VALUES('".serialize($_POST)."', '".$my_token."' ) ") or die(mysql_error());
return $_POST;
}[/php]

Οπότε όταν "χτυπάμε" πλέον το URL:

http://www.diakopesTravelSearch.gr/search.php?token=wthgj34jku
η get_post_data() τραβάει τα data που είχαμε κάνει post από τη βάση δεδομένων.

Πιο πρακτικά:

Μέσα στην search.php αντί να λέμε:

[php]
$variable1 = $_GET['var1'];
$variable2 = $_GET['var2'];
$variable3 = $_GET['var3'];
[/php]

κτλ κτλ...

θα λέμε:

[php]
$post_data = get_post_data();
$variable1 = $post_data['var1'];
$variable2 = $post_data['var2'];
$variable3 = $post_data['var3'];[/php]

Υπάρχουν πολλοί τρόποι να γίνει extend η παραπάνω λειτουργία (παραθέτω 2):

1. Το αποτέλεσμα του post (το αποτέλεσμα της search.php δηλαδή) να γίνεται cache κάπου στη βάση και να συνδέεται με το αντίστοιχο token έτσι ώστε σε ένα μελλοντικό search να έχετε το αποτέλεσμα έτοιμο.

2. Να γίνεται expire το token μετά από ένα προκαθορισμένο χρόνο και με χρήση Cron Job να σβήνεται από τη βάση (κάθε token στη βάση έχει creation_date).

Πιστεύω να βοήθησα...