Eiσαγωγή στην PHP Μέρος 3

Post Pic
στις 05.06.10. Kατηγορίες PHP με 6 Σχόλια

Στο δεύτερο μέρος της εισαγωγής στην PHP μιλήσαμε για τα Regular Expressions, για την μορφωποίηση των κειμένων, τις παραγράφους και τους υπερσύνδεσμους. Στο τρίτο μέρος, θα μιλήσουμε περί περιεχομένου, θα δούμε κάποια προχωρημένα πράγματα για SQL, και θα δούμε τέλος και την ταξινόμηση με την Order By

Διαχωρισμός Κειμένου σε Σελίδες

Αν και κανένα joke δεν είναι πιθανό να είναι τόσο μεγάλο που να χρειάζεται περισσότερες από μία σελίδες, πολλά content-driven sites περιέχουν μεγάλο περιεχόμενο που είναι συχνά καλύτερο να παρουσιασθεί διασπασμένο σε σελίδες. Υπάρχει μια ακόμη συνάρτηση στην PHP που το κάνει αυτό πολύ εύκολα. Η split() είναι μια συνάρτηση που δέχεται μια κανονική έκφραση και ένα string κειμένου και χρησιμοποιεί ταιριάσματα για την κανονική έκφραση για να διασπάσει το κείμενο σ’ έναν πίνακα (array). Ας δούμε το ακόλουθο παράδειγμα :

$regexp="[ \n\r\t]+";   // Ένας ή περισσότεροι whitespace characters
$text="This is a test.";
$textarray=split($regexp, $text);
echo("$textarray[0]<BR>");         // Εμφανίζει "This<BR>"
echo("$textarray[1]<BR>");         // Εμφανίζει "is<BR>"
echo("$textarray[2]<BR>");         // Εμφανίζει "a<BR>"
echo("$textarray[3]<BR>");         // Εμφανίζει "test.<BR>"

Αν αντί να αναζητούμε έναν whitespace character αναζητούμε ένα [PAGEBREAK] tag και αντί να εμφανίζουμε όλα τα κομμάτια του κειμένου εμφανίσουμε μόνο τη σελίδα που μας ενδιαφέρει, η οποία δείχνεται από μια μεταβλητή $page που μεταβιβάζεται μαζί με την αίτηση για τη σελίδα (page request), για παράδειγμα, μπορούμε να διαιρέσουμε το περιεχόμενο σε σελίδες.

// Αν δεν έχει καθορισθεί κάποια σελίδα, default είναι η
// πρώτη σελίδα ($page = 0)
if (!isset($page)) $page = 0;
// Διαιρούμε το κείμενο σ’ έναν πίνακα (array) από σελίδες
$textarray=split("\[PAGEBREAK]", $text);
// Επιλέγουμε τη σελίδα που θέλουμε
$pagetext=$textarray[$page];
$regexp="[ \n\r\t]+";   // Ένας ή περισσότεροι whitespace characters
$text="This is a test.";
$textarray=split($regexp, $text);
echo("$textarray[0]<BR>");         // Εμφανίζει "This<BR>"
echo("$textarray[1]<BR>");         // Εμφανίζει "is<BR>"
echo("$textarray[2]<BR>");         // Εμφανίζει "a<BR>"
echo("$textarray[3]<BR>");         // Εμφανίζει "test.<BR>"

Αν αντί να αναζητούμε έναν whitespace character αναζητούμε ένα [PAGEBREAK] tag και αντί να εμφανίζουμε όλα τα κομμάτια του κειμένου εμφανίσουμε μόνο τη σελίδα που μας ενδιαφέρει, η οποία δείχνεται από μια μεταβλητή $page που μεταβιβάζεται μαζί με την αίτηση για τη σελίδα (page request), για παράδειγμα, μπορούμε να διαιρέσουμε το περιεχόμενο σε σελίδες.

// Αν δεν έχει καθορισθεί κάποια σελίδα, default είναι η
// πρώτη σελίδα ($page = 0)
if (!isset($page)) $page = 0;
// Διαιρούμε το κείμενο σ’ έναν πίνακα (array) από σελίδες
$textarray=split("\[PAGEBREAK]", $text);
// Επιλέγουμε τη σελίδα που θέλουμε
$pagetext=$textarray[$page];

Φυσικά, θα θελήσουμε να έχουμε κάποιον τρόπο μετακίνησης ανάμεσα στις σελίδες. Θα τοποθετήσουμε έναν σύνδεσμο (link) προς την προηγούμενη σελίδα στην κορυφή της τρέχουσας σελίδας και έναν σύνδεσμο προς την επόμενη σελίδα στη βάση της τρέχουσας σελίδας. Αν αυτή είναι η πρώτη σελίδα δεν θα χρειασθούμε ένα link προς την προηγούμενη σελίδα. Γνωρίζουμε ότι βρισκόμαστε στην πρώτη σελίδα αν το $page είναι ίσο με 0. Παρόμοια, δεν χρειαζόμαστε ένα link προς την επόμενη σελίδα όταν βρισκόμαστε στην τελευταία σελίδα.

Για να είμαστε σίγουροι ότι βρισκόμαστε στην τελευταία σελίδα, χρειαζόμαστε μια συνάρτηση της PHP με όνομα count(), η οποία δέχεται έναν πίνακα (array) και επιστρέφει τον αριθμό των στοιχείων του πίνακα. Αν μεταβιβάσουμε τον πίνακα των σελίδων, η count() θα μας πει πόσες σελίδες υπάρχουν. Αν υπάρχουν 10 σελίδες, τότε το $textarray[9] θα περιέχει την τελευταία σελίδα. Έτσι, γνωρίζουμε ότι βρισκόμαστε στην τελευταία σελίδα αν το $page είναι ίσο με count($textarray) – 1.

Ο κώδικας για τα links μετάβασης ανάμεσα στις σελίδες είναι ο εξής :

if ($page != 0) {
$prevpage = $page - 1;
echo("<P><A HREF=\"$PHP_SELF?id=$id&page=$prevpage\">".
"Προηγούμενη Σελίδα</A></P>");
}
// Το περιεχόμενο της σελίδας εμφανίζεται εδώ …
if ($page < count($textarray) - 1) {
$nextpage = $page + 1;
echo("<P><A HREF=\"$PHP_SELF?id=$id&page=$nextpage\">".
"Επόμενη Σελίδα</A></P>");
}

Ολόκληρος ο κώδικας για την εμφάνιση του κειμένου του joke είναι ως εξής :

<!-- joke.php -->
...
// Παίρνουμε (get) το κείμενο του joke από τη βάση δεδομένων
$joke = mysql_query("SELECT JokeText FROM Jokes ".
"WHERE ID=$id");
$joke = mysql_fetch_array($joke);
$joketext = $joke["JokeText"];
// Φιλτράρουμε τον HTML κώδικα
$joketext = htmlspecialchars($joketext);
// Αν δεν έχει καθορισθεί κάποια σελίδα, default είναι η πρώτη σελίδα
($page = 0)
if (!isset($page)) $page = 0;
// Διαιρούμε το κείμενο σ’ έναν πίνακα (array) από σελίδες
$textarray=split("\[PAGEBREAK]",$joketext);
// Επιλέγουμε τη σελίδα που θέλουμε
$joketext=$textarray[$page];
// Bold και italics
$joketext = eregi_replace("\[b]","<B>", $joketext);
$joketext = eregi_replace("\[eb]","</B>", $joketext);
$joketext = eregi_replace("\[i]","<I>", $joketext);
$joketext = eregi_replace("\[ei]","</I>", $joketext);
// Παράγραφοι και αλλαγές γραμμών
$joketext = ereg_replace("\r", "", $joketext);
$joketext = ereg_replace("\n\n", "<P>", $joketext);
$joketext = ereg_replace("\n", "<BR>", $joketext);
// Υπερσύνδεσμοι (Hyperlinks)
$joketext = ereg_replace(
"\[L]([-_./a-zA-Z0-9!&%#?,'=:~]+)\[EL]",
"<A HREF=\"\\1\">\\1</A>", $joketext);
$joketext = ereg_replace(
"\[L=([-_./a-zA-Z0-9!&%#?,'=:~]+)]".
"([-_./a-zA-Z0-9 !&%#?,'=:~]+)\[EL]",
"<A HREF=\"\\1\">\\2</A>", $joketext);
if ($page != 0) {
$prevpage = $page - 1;
echo("<P><A HREF=\"$PHP_SELF?id=$id&page=$prevpage\">".
"Προηγούμενη Σελίδα</A></P>");
}
echo( "<P>$joketext" );
if ($page < count($textarray) - 1) {
$nextpage = $page + 1;
echo("<P><A HREF=\"$PHP_SELF?id=$id&page=$nextpage\">".
"Επόμενη Σελίδα</A></P>");
}
...

Αυτόματη Υποβολή Περιεχομένου

Θα δούμε τώρα πώς μπορούμε να δεχόμαστε jokes αλλά να μην εμφανίζονται αμέσως στο site. Θα προσθέσουμε μια νέα στήλη στον πίνακα Jokes με όνομα Visible η οποία θα δέχεται μόνο μία από δύο τιμές : ‘Y’ και ‘N’. Τα νέα jokes που θα υποβάλλονται θα γίνονται ίσα με Visible=’N’ αυτόματα και δεν θα μπορούν να αποκλειστούν από το να εμφανισθούν στο site, προσθέτοντας απλά την έκφραση WHERE Visible=’Y’ σ’ ένα ερώτημα (query) του πίνακα Jokes για το οποίο τα αποτελέσματα προορίζονται για κοινή θέα.

Τα jokes που έχουν τη στήλη Visible=’N’ θα βρίσκονται στη βάση δεδομένων περιμένοντας τροποποίηση από έναν content manager, ο οποίος θα μπορεί να τα τροποποιήσει πριν τα κάνει ορατά ή απλά να τα διαγράψει αμέσως. Η δημιουργία μιας στήλης που μπορεί να περιέχει μία από δύο τιμές, η μια από τις οποίες είναι η προκαθορισμένη (default), έχει να κάνει μ’ ένα νέο είδος στήλης της MySQL που αποκαλείται ENUM :

mysql> ALTER TABLE Jokes ADD COLUMN
-> Visible ENUM('N', 'Y') NOT NULL;

Η πρώτη τιμή που υπάρχει στις παρενθέσεις, δηλ. το ‘N’ στην προκειμένη περίπτωση, είναι η προκαθορισμένη (default) τιμή, η οποία εκχωρείται στις νέες καταχωρήσεις αν δεν έχει καθορισθεί μια τιμή στην εντολή INSERT.

Προχωρημένη SQL

Καθώς έχουμε δουλέψει με το παράδειγμα ενός Internet Joke Database website, είχαμε την ευκαιρία να εξερευνήσουμε τις περισσότερες πλευρές της Structured Query Language (SQL), από την βασική μορφή του ερωτήματος CREATE TABLE μέχρι τους δύο τρόπους σύνταξης των ερωτημάτων INSERT. Θα δούμε τώρα μερικά ακόμα τρικ της SQL που δεν τα έχουμε συναντήσει.

Ταξινόμηση με την ORDER BY

Η Order By είναι μια προαιρετική έκφραση σ’ ένα ερώτημα SELECT με την οποία μπορούμε να καθορίσουμε μια στήλη (column) για να ταξινομήσουμε τον πίνακα των αποτελεσμάτων. Για παράδειγμα, για να ταξινομήσουμε με βάση τη στήλη Name του πίνακα Authors, δίνουμε την εξής εντολή :

mysql> SELECT Name, eMail FROM Authors ORDER BY Name;
+-----------------+----------------------+
| Name            | eMail                |
+-----------------+----------------------+
| Antonopoulos Antonis| ant@hellas.gr |
| Basileiadis Basileios| bas@hellas.gr|
| Konstantinou Konstantinos| kon@hellas.gr |
| Papadopoulos Nikolaos|pap@hellas.gr |
+-----------------+----------------------+

Αν προσθέσουμε τη λέξη κλειδί DESC μετά από το όνομα της στήλης ταξινόμησης, τα αποτελέσματα θα εμφανισθούν σε φθίνουσα σειρά, ως εξής :

mysql> SELECT Name, eMail FROM Authors ORDER BY Name DESC;
+-----------------+----------------------+
| Name            | eMail                |
+-----------------+----------------------+
| Papadopoulos Nikolaos | pap@hellas.gr|
| Konstantinou Konstantinos | kon@hellas.gr|
| Basileiadis Basileios| bas@hellas.gr|
| Antonopoulos Antonis|ant@hellas.gr|
+-----------------+----------------------+

Μπορούμε να ταξινομήσουμε και με βάση περισσότερες από μία στήλες, χωρίζοντάς τες με κόμμα στην έκφραση ORDER BY, οπότε η MySQL θα ταξινομήσει τις καταχωρήσεις με βάση την πρώτη στήλη, μετά με βάση τη δεύτερη στήλη όπου υπάρχουν ίδιες τιμές στην πρώτη στήλη κοκ. Μπορούμε να χρησιμοποιήσουμε τη λέξη κλειδί DESC σε όποια στήλη θέλουμε στην έκφραση ORDER BY για να αντιστρέψουμε τη σειρά ταξινόμησης.

Η Έκφραση LIMIT

Συχνά θα εργαζόμαστε μ’ έναν μεγάλο πίνακα μιας βάσης δεδομένων, αλλά θα μας ενδιαφέρουν λίγες μόνο καταχωρήσεις του. Ας υποθέσουμε ότι θέλουμε να παρακολουθούμε τη δημοτικότητα των διάφορων jokes στο site. Θα μπορούμε να προσθέσουμε μια στήλη με όνομα TimesViewed στον πίνακα Jokes.

Ξεκινώντας με μια τιμή 0 για τα καινούργια jokes και προσθέτοντας το 1 στην τιμή του joke που ζητήθηκε κάθε φορά που εμφανίζεται η σελίδα του joke, θα μπορούμε να παρακολουθούμε πόσες φορές έχει διαβασθεί το κάθε joke στη βάση δεδομένων.

Ο PHP κώδικας για το query που αυξάνει κατά 1 τη στήλη TimesViewed ενός joke μ’ ένα δεδομένο ID, είναι ως εξής :

$sql = "UPDATE Jokes SET TimesViewed=TimesViewed+1 ".
"WHERE ID=$id";
if (!mysql_query($sql)) {
echo("<P > Λάθος στην πρόσθεση ".
"γι' αυτό το joke! </P>\n");
}

Μια κοινή χρήση αυτού του μετρητή θα ήταν για να παρουσιάσουμε μια λίστα των “Top 10 Jokes” στην πρώτη σελίδα του site, για παράδειγμα. Μπορούμε να χρησιμοποιήσουμε την έκφραση ORDER BY TimesViewed DESC για να εμφανίσουμε τα jokes από τις υψηλότερες προς τις χαμηλότερες τιμές της στήλης TimesViewed. Θα πρέπει απλά να επιλέξουμε τις 10 πρώτες τιμές από την κορυφή της λίστας.

Με την έκφραση (clause) LIMIT μπορούμε να καθορίσουμε ότι θέλουμε έναν μόνο συγκεκριμένο αριθμό αποτελεσμάτων. Σύμφωνα με το παραπάνω παράδειγμα, χρειαζόμαστε μόνο τα 10 πρώτα :

$sql = "SELECT * FROM Jokes ORDER BY TimesViewed
DESC LIMIT 10";

Επίσης, θα μπορούμε να αποφύγουμε τη λέξη κλειδί DESC και να εμφανίσουμε τα 10 λιγότερο δημοφιλή jokes. Το επόμενο query θα εμφανίσει από το 21ο έως το 25ο πιο δημοφιλή jokes :

$sql = "SELECT * FROM Jokes ORDER BY TimesViewed
DESC LIMIT 20, 5";

Πρέπει να έχουμε υπόψη μας ότι η πρώτη καταχώρηση στη λίστα των αποτελεσμάτων έχει αριθμό 0 και έτσι η 21η καταχώρηση της λίστας θα έχει αριθμό 20.

Οι Εκφράσεις LOCK και UNLOCK

Στο ερώτημα UPDATE που χρησιμοποιήσαμε παραπάνω, υπάρχει ένας μικρός κίνδυνος. Τι θα συμβεί αν τη στιγμή που αλλάζει η τιμή της στήλης TimesViewed, κάποιος άλλος χρήστης εμφανίσει το ίδιο joke; Το PHP script θα εκτελεσθεί για δεύτερη φορά για την καινούργια αίτηση (request). Όταν εκτέλεσε το SELECT για να πάρει την τρέχουσα τιμή της στήλης TimesViewed, θα πήρε την ίδια τιμή με το πρώτο script, επειδή η τιμή δεν έχει ακόμη ενημερωθεί.

Και τα δύο scripts θα προσθέσουν μετά το 1 στην ίδια τιμή και θα γράψουν την καινούργια τιμή στον πίνακα. Το αποτέλεσμα θα είναι ότι δύο χρήστες είδαν το joke, αλλά ο μετρητής TimesViewed αυξήθηκε μόνο κατά 1. Για να αποφύγουμε προβλήματα όπως το παραπάνω, μπορούμε να κλειδώσουμε έναν ή περισσότερους πίνακες με τους οποίους εργαζόμαστε σ’ ένα ερώτημα και να έχουμε έτσι αποκλειστική πρόσβαση σ’ αυτούς για όσο διαρκεί το ερώτημα. Η σύνταξη για το κλείδωμα ενός πίνακα είναι ως εξής :

LOCK TABLES tblName { READ | WRITE }

Όταν κλειδώνουμε έναν πίνακα, πρέπει να καθορίσουμε αν θέλουμε ένα “read lock” ή ένα “write lock”. Το πρώτο εμποδίζει άλλες διεργασίες από το να κάνουν αλλαγές στον πίνακα αλλά επιτρέπει σ’ άλλες να διαβάσουν τον πίνακα. Το δεύτερο απαγορεύει όλες τις προσβάσεις στον πίνακα.

Όταν τελειώσουμε την εργασία μας μ’ έναν πίνακα που έχουμε κλειδώσει, πρέπει να απελευθερώσουμε το κλείδωμα για να μπορέσουν να έχουν οι άλλες διεργασίες πρόσβαση στον πίνακα ξανά :

UNLOCK TABLES

Ακολουθεί ένα παράδειγμα ενός PHP κώδικα :

mysql_query("LOCK TABLES inventory WRITE, shipping WRITE");
// … εντολές …
mysql_query("UNLOCK TABLES");

Tags: , , ,

Pantso { Προσωπική Ιστοσελίδα / Άρθρα Στο GreekTuts }
Ο Παναγιώτης έχει σπουδάσει προγραμματιστής και προγραμματιστής Video Games ενώ τώρα κάνει το Bachelor του σε Computer Science από το Πανεπιστήμιο του Roehampton στο Λονδίνο. Έχει εργαστεί στο Darkfall Online , το πρώτο ελληνικό MMORPG, ως World Builder, είναι BlackBoard Support Certified , ενώ σήμερα εργάζεται ώς HTML Author στην Atcom SA.

6 Σχόλια στο άρθρο Eiσαγωγή στην PHP Μέρος 3

  • datahell says:

    Οι συναρτήσεις split και ereg έχουν καταργηθεί. Θα πρέπει να χρησιμοποιήσετε POSIX συναρτήσεις (preg_split, preg_match) και αντί του eregi την preg_match με το pattern "i" (/patern/i).
    Τα regex επίσης θέλουν delimiters.
    Το PHP_SELF δεν "παίζει". Θα πρέπει να πάρετε την τιμή του από την super global μεταβλητή $_SERVER.

  • Pantso says:

    Απλά για να δείξω ότι είναι SQL query

  • ηθελα να πω για το συμβολο >

  • Pantso says:

    Το SELECT Name, eMail FROM Authors ORDER BY Name; είναι ένα ερώτημα (query) που μας επιστρέφει τις στήλες με τα ονόματα, Name και Email, από τον πίνακα Authors και τα ταξινομεί κατά όνομα αλφαβητικά ! Όσο για την αυτόματη υποβολή περιεχομένου, είναι ένας τρόπος filtering όπως αυτός που έχει το WordPress για τα comments

  • Θα ηεθλα μια διευκρινηση εκει που λες ΑΥΤΟΜΑΤΗ ΥΠΟΒΟΛΗ ΠΕΡΙΕΧΟΜΕΝΟΥ
    και γραφεις αυτο τι ενοεις ?
    mysql> SELECT Name, eMail FROM Authors ORDER BY Name;

  • Pingback: Tweets that mention Eiσαγωγή στην PHP Μέρος 3 | GreekTuts -- Topsy.com

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>