Σελίδα 1 από 2 12 Τελευταία
Εμφάνιση αποτελεσμάτων : 1 έως 15 από 21

Προχωρημένα Θέματα στην PHP

Αυτή είναι μια συζήτηση με θέμα: Προχωρημένα Θέματα στην PHP στο forums PHP και MySQL, μέρος της κατηγορίας Supa Wikipedia (Βοηθήματα) : Οι Κανονικές Εκφράσεις (Regular Expressions) Μια κανονική έκφραση (regular expression) είναι ένα κομμάτι (string) κειμένου που περιέχει ειδικούς κωδικούς που .....

  1. #1

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Προχωρημένα Θέματα στην PHP

    Οι Κανονικές Εκφράσεις (Regular Expressions)

    Μια κανονική έκφραση (regular expression) είναι ένα κομμάτι (string) κειμένου που περιέχει ειδικούς κωδικούς που του δίνουν τη δυνατότητα να μπορεί να χρησιμοποιηθεί με κάποιες συναρτήσεις της PHP για εντοπισμό και διαχείριση κειμένου. Για παράδειγμα, η επόμενη είναι μια κανονική έκφραση που κάνει αναζήτηση για το κείμενο PHP :

    PHP
    Για να μπορέσουμε να χρησιμοποιήσουμε μια κανονική έκφραση, πρέπει να είμαστε εξοικειωμένοι με τις συναρτήσεις των κανονικών εκφράσεων που υπάρχουν στην PHP. Η ereg() είναι η βασικότερη απ’ αυτές και μπορεί να χρησιμοποιηθεί για να καθορίσουμε αν μια κανονική έκφραση ικανοποιείται από ένα συγκεκριμένο string κειμένου. Ας δούμε τον επόμενο κώδικα :

    $text = "Κανόνες της PHP!";

    if (ereg("PHP", $text)) {

    echo( '$το κείμενο περιέχει το string "PHP".' );

    } else {

    echo( '$το κείμενο δεν περιέχει το string "PHP".' );

    }

    Σ’ αυτό το παράδειγμα, η κανονική έκφραση ικανοποιείται επειδή το string που είναι αποθηκευμένο στη μεταβλητή $text περιέχει το PHP. Ο παραπάνω κώδικας θα εξάγει συνεπώς τα εξής :

    $το κείμενο περιέχει το string "PHP".

    Δεν πρέπει να ξεχνάμε όταν τα μονά εισαγωγικά αποτρέπουν την PHP από το να εμφανίσει την τιμή της μεταβλητής $text.

    Η eregi() είναι μια συνάρτηση που συμπεριφέρεται σχεδόν παρόμοια με την ereg(), εκτός από το ότι αγνοεί τα πεζά και τα κεφαλαία γράμματα όταν αναζητά ταιριάσματα :

    $text = "Τι είναι η Php;";

    if (eregi("PHP", $text)) {

    echo( '$το κείμενο περιέχει το string "PHP".' );

    } else {

    echo( '$το κείμενο δεν περιέχει το string "PHP".' );

    }

    Αυτό εμφανίζει πάλι το ίδιο μήνυμα :

    $το κείμενο περιέχει το string "PHP".

    Θα δούμε μερικά παραδείγματα για να μάθουμε τη βασική σύνταξη των κανονικών εκφράσεων. Πρώτα απ’ όλα, το σύμβολο caret (Ù) μπορεί να χρησιμοποιηθεί για να δείξει την αρχή ενός string, ενώ το σύμβολο του δολαρίου ($) χρησιμοποιείται για να δείξει το τέλος :

    PHP // Ταιριάζει με το "What is PHP?"

    ÙPHP // Ταιριάζει με το "PHP rules!", όχι με το "What is PHP?"

    PHP$ // Ταιριάζει με το "I love PHP", όχι με το "What is PHP?"

    ÙPHP$ // Ταιριάζει με το "PHP" και τίποτα άλλο

    Προφανώς, θα υπάρχουν φορές που θα θέλουμε να χρησιμοποιήσουμε τα σύμβολα ^, $ ή και άλλους ειδικούς χαρακτήρες για να συμπεριλάβουμε τον αντίστοιχο χαρακτήρα στο string αναζήτησης. Για να αφαιρέσουμε το ειδικό νόημα ενός χαρακτήρα, προτάσσουμε τον χαρακτήρα \ (backslash), ως εξής :

    \$\$\$ // Ταιριάζει με το "Show me the $$$!"

    Οι αγκύλες μπορούν να χρησιμοποιηθούν για να ορίσουν ένα σύνολο χαρακτήρων που μπορεί να ταιριάξει. Για παράδειγμα, η ακόλουθη κανονική έκφραση ταιριάζει μ’ ένα μόνο από τα ψηφία 1 έως 5.

    [12345] // Ταιριάζει με το "1" και το "3", αλλά όχι με το "a" ή το "12"

    Μπορούμε να καθορίσουμε και περιοχές αριθμών ή γραμμάτων.

    [1-5] // Το ίδιο όπως προηγουμένως

    [a-z] // Ταιριάζει μ’ ένα οποιοδήποτε πεζό γράμμα

    [0-9a-zA-Z] // Ταιριάζει μ’ ένα οποιοδήποτε γράμμα ή ψηφίο

    Οι χαρακτήρες ?, + και * έχουν επίσης ειδικό νόημα. Συγκεκριμένα, το ? σημαίνει ότι ο προηγούμενος χαρακτήρας είναι προαιρετικός, το + σημαίνει έναν ή περισσότερους από τους προηγούμενους χαρακτήρες και το * σημαίνει κανέναν ή έναν από τους προηγούμενους χαρακτήρες.

    bana?na // Ταιριάζει με τα "banana" και "banna",

    // αλλά όχι με το "banaana"

    bana+na // Ταιριάζει με τα "banana" και "banaana",

    // αλλά όχι με το "banna"

    bana*na // Ταιριάζει με τα "banna", "banana" και "banaaana",

    // αλλά όχι με το "bnana"

    Ù[a-zA-z]+$ // Ταιριάζει μ’ ένα οποιοδήποτε string που έχει έναν

    // τουλάχιστον χαρακτήρα

    Οι παρενθέσεις μπορούν να χρησιμοποιηθούν για να ομαδοποιήσουμε strings και να εφαρμόσουμε τα ?, + ή * σ’ αυτά σαν σύνολο.

    ba(na)+na // Ταιριάζει με τα "banana" και "banananana",

    // αλλά όχι με το "bana" ή το "banaana"

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

    \n // Ταιριάζει μ’ έναν χαρακτήρα νέας γραμμής (newline character)

    Ù // Ταιριάζει μ’ έναν οποιονδήποτε χαρακτήρα εκτός από τον

    // χαρακτήρα νέας γραμμής

    \r // Ταιριάζει μ’ έναν χαρακτήρα carriage return

    \t // Ταιριάζει με τον χαρακτήρα tab

    Oι χρήστες του Supa.gr χρησιμοποιούν το "Like" για να εκτιμήσουν τις δημοσιεύσεις

  2. #2

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Αντικατάσταση Strings με Κανονικές Εκφράσεις

    Χρησιμοποιώντας την ereg() ή την eregi() με τη σύνταξη των κανονικών εκφράσεων που μόλις είδαμε, μπορούμε να εντοπίσουμε εύκολα την παρουσία tags σ’ ένα δεδομένο string κειμένου. Αυτό που πρέπει να κάνουμε, όμως, είναι να σημειώσουμε με ακρίβεια αυτά τα tags και να τα αντικαταστήσουμε με κατάλληλα HTML tags.

    Για να γίνει αυτό, πρέπει να δούμε μερικές ακόμα συναρτήσεις κανονικών εκφράσεων που υπάρχουν στην PHP : την ereg_replace() και την eregi_ replace().

    Η ereg_replace(), σαν την ereg(), δέχεται μια κανονική έκφραση και ένα string κειμένου και προσπαθεί να ταιριάξει την κανονική έκφραση με το string. Επιπλέον, όμως, η ereg_replace() δέχεται ένα δεύτερο string κειμένου και αντικαθιστά κάθε ταίριασμα της κανονικής έκφρασης σ’ αυτό το string. Η σύνταξη της ereg_replace() είναι ως εξής :

    $newstring = ereg_replace(<regexp>, <replacewith>, [list=1]);

    όπου η <regexp> είναι η κανονική έκφραση και το <replacewith> είναι το string που θα αντικαταστήσει τα ταιριάσματα στην <regexp> όπου υπάρχει το [list=1]. Η συνάρτηση επιστρέφει το νέο string που προκύπτει από τη λειτουργία της αντικατάστασης. Στην παραπάνω πρόταση, αυτό απoθηκεύεται στη μεταβλητή $newstring.

    Η eregi_replace(), όπως είναι αναμενόμενο, είναι παρόμοια με την ereg_replace(), εκτός από το ότι δεν ελέγχει τα πεζά/κεφαλαία όταν κάνει αναζήτηση για ταιριάσματα.

    Είμαστε τώρα έτοιμοι να αρχίσουμε να δημιουργούμε τη δική μας προσαρμοσμένη γλώσσα σήμανσης (custom markup language).

  3. #3

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Έντονο και Πλάγιο Κείμενο

    Θα ξεκινήσουμε υλοποιώντας tags για να δημιουργήσουμε έντονο και πλάγιο κείμενο. Ας υποθέσουμε ότι θέλουμε το [B] να ξεκινάει το έντονο κείμενο (bold text) και το [EB] να τελειώνει το έντονο κείμενο. Προφανώς, θα πρέπει να αντικαταστήσουμε το [B] με το και το [EB] με το .

    Η λειτουργία αυτή αποτελεί μια απλή εφαρμογή της συνάρτησης eregi_replace() :

    $joketext = eregi_replace("\[b]", "", $joketext);

    $joketext = eregi_replace("\[eb]", "
    ", $joketext);

    Εφόσον το [ κανονικά δείχνει την αρχή ενός συνόλου αποδεκτών χαρακτήρων σε μια κανονική έκφραση, τοποθετούμε τον χαρακτήρα \ (backslash) πριν απ’ αυτόν για να αφαιρέσουμε το ειδικό νόημα που έχει. Χωρίς ένα αντίστοιχο [, το ] χάνει το ειδικό νόημα που έχει και δεν χρειάζεται συνεπώς έναν χαρακτήρα backslash, αν και θα μπορούσαμε να τοποθετήσουμε ένα backslash μπροστά του επίσης.

    Παρατηρούμε επίσης, ότι, εφόσον χρησιμοποιούμε τη συνάρτηση eregi_replace(), η οποία δεν ξεχωρίζει τα πεζά από τα κεφαλαία γράμματα (case insensitive), το [B] και το [b] θα εργάζονται σαν tags στη δική μας προσαρμοσμένη γλώσσα σήμανσης (custom markup language).

    Το πλάγιο κείμενο μπορεί να γίνει με τον ίδιο τρόπο :

    $joketext = eregi_replace("\[i]", "", $joketext);

    $joketext = eregi_replace("\[ei]", "
    ", $joketext);

  4. #4

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Οι Παράγραφοι

    Ενώ μπορούμε να δημιουργήσουμε tags για παραγράφους όπως ακριβώς κάναμε για το έντονο και πλάγιο κείμενο, υπάρχει και μια πιο απλή λύση. Εφόσον ο χρήστης θα καταχωρήσει το περιεχόμενο σ’ ένα πεδίο φόρμας (form field) που θα του δίνει τη δυνατότητα να μορφοποιήσει το κείμενο χρησιμοποιώντας το πλήκτρο enter, θα ορίσουμε το linefeed (\n) να δείχνει μια αλλαγή γραμμής (line break),
    ) και το διπλό linefeed (\n\n) να δείχνει μια νέα παράγραφο (

    ).

    Φυσικά, εφόσον τα PC's παριστάνουν τις νέες γραμμές σαν ένα ζευγάρι του linefeed με το carriage return (\n\r) θα πρέπει πρώτα να αφαιρέσουμε τα carriage returns. Ο κώδικας γι’ όλα αυτά είναι ο εξής :

    // Αφαιρεί τα carriage returns

    $joketext = ereg_replace("\r", "", $joketext);

    // Χειρισμός των παραγράφων

    $joketext = ereg_replace("\n\n", "

    ", $joketext);

    // Χειρισμός των αλλαγών γραμμής (line breaks)

    $joketext = ereg_replace("\n", "
    ", $joketext);

    Το κείμενο θα εμφανίζεται τώρα σε παραγράφους όπως θα ανέμενε ο χρήστης και δεν χρειάζεται να μάθει να δημιουργεί προσαρμοσμένα tags για να το κάνει.

  5. #5

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Οι Υπερσύνδεσμοι (Hyperlinks)

    Ενώ μπορεί να φανεί ανόητο το να υποστηρίζουμε τους υπερσυνδέσμους (hyperlinks) στο κείμενο των jokes, αυτό το χαρακτηριστικό έχει νόημα σ’ άλλες εφαρμογές. Οι υπερσύνδεσμοι είναι λίγο περισσότερο πολύπλοκοι από την απλή μετατροπή ενός κώδικα σ’ ένα HTML tag. Πρέπει να μπορούμε να εξάγουμε ένα URL όπως και το κείμενο που πρέπει να εμφανίζεται σαν ο σύνδεσμος (link).

    Ένα άλλο χαρακτηριστικό των συναρτήσεων ereg_replace() και eregi_replace() θα φανεί εδώ. Περιβάλλοντας ένα τμήμα της κανονικής έκφρασης με παρενθέσεις, μπορούμε να αποσπάσουμε το αντίστοιχο τμήμα του κειμένου που ταιριάζει και να το χρησιμοποιήσουμε στο string αντικατάστασης με τον κώδικα \\n, όπου το n είναι 1 για το πρώτο τμήμα της κανονικής έκφρασης που βρίσκεται σε παρενθέσεις, 2 για το δεύτερο και έως 9 για το ένατο. Ας δούμε το ακόλουθο παράδειγμα :

    $text = "banana";

    $text = eregi_replace("(.*)(nana)", "\\2\\1", $text);

    echo($text); // εμφανίζει "nanaba"

    Στο παραπάνω, το \\1 αντικαθίσταται με το ba στο string αντικατάστασης, το οποίο αντιστοιχεί στο (.*) (κανένας ή περισσότεροι χαρακτήρες διάφοροι της νέας γραμμής, new line) στην κανονική έκφραση. Το \\2 αντικαθίσταται με το nana, το οποίο αντιστοιχεί στο (nana) στην κανονική έκφραση.

    Η ίδια αρχή μπορεί να χρησιμοποιηθεί για να δημιουργήσουμε τους υπερσυνδέσμους μας (hyperlinks). Θα ξεκινήσουμε με μια απλή φόρμα ενός link, όπου το κείμενο του link είναι το ίδιο με το URL. Θέλουμε να υποστηρίξουμε την εξής σύνταξη :

    Visit [L]http://www.php.net/[EL].

    Ο αντίστοιχος HTML κώδικας είναι ο εξής :

    Visit <a class="postlink" href="http://www.php.net/">http://www.php.net/ </A>
    Πρώτα, χρειαζόμαστε μια κανονική έκφραση που θα ταιριάζει με τους συνδέσμους (links) αυτής της φόρμας, ως εξής :

    \[L][-_./a-zA-Z0-9!&%#?,'=:~]+\[EL]

    Ξανά, έχουμε τοποθετήσει backslashes μπροστά από τις αγκύλες στα [L] και [EL] για να δείξουμε ότι θα τα αντιμετωπίσουμε κυριολεκτικά. Χρησιμοποιούμε μετά αγκύλες (square brackets) για να εμφανίσουμε όλους τους χαρακτήρες που θέλουμε να δεχθούμε σαν μέρος του URL. Τοποθετούμε ένα + μετά από τις αγκύλες για να δείξουμε ότι το URL θα αποτελείται από έναν ή περισσότερους χαρακτήρες που παίρνονται από τη λίστα.

    Για να εξάγουμε το link, θα πρέπει να βρούμε το URL και να το εξάγουμε σαν το HREF attribute του tag Α καθώς και σαν το κείμενο του link. Για να βρούμε το URL, περιβάλλουμε το αντίστοιχο τμήμα της κανονικής έκφρασης με παρενθέσεις :

    \[L]([-_./a-zA-Z0-9!&%#?,'=:~]+)\[EL]

    Έτσι, κάνουμε τη μετατροπή link με τον εξής κώδικα :

    $joketext = ereg_replace(

    "\[L]([-_./a-zA-Z0-9!&%#?,'=:~]+)\[EL]",

    "<A HREF=\"\\1\">\\1</A>", $joketext);

    Έπρεπε να τοποθετήσουμε backslashes μπροστά από τα διπλά εισαγωγικά στον HTML κώδικα για να μην τα μπερδέψει η PHP με τα εισαγωγικά που περιβάλλουν το string αντικατάστασης. Το \\1 αντικαθίσταται με το URL για το link και η έξοδος είναι η αναμενόμενη.

    Θα θέλαμε επίσης να υποστηρίξουμε τα hyperlinks που περιέχουν κείμενο link που διαφέρει από τα δικά τους URL. Ας υποθέσουμε ότι η μορφή του link μας είναι ως εξής :

    Check out [L=http://www.php.net/]PHP[EL].

    Ακολουθεί η κανονική έκφραση :

    \[L=([-_./a-zA-Z0-9!&%#?,'=:~]+)]([-_./a-zA-Z0-9 !&%#?,'=:~]+)\[EL]

    Το παραπάνω κάνει αυτό ακριβώς που θέλουμε, καθώς βρίσκει και το URL (\\1) και το κείμενο (\\2) για το link. Ο PHP κώδικας για να γίνει η αντικατάσταση είναι ο εξής :

    $joketext = ereg_replace(

    "\[L=([-_./a-zA-Z0-9!&%#?,'=:~]+)]".

    "([-_./a-zA-Z0-9 !&%#?,'=:~]+)\[EL]",

    "<A HREF=\"\\1\">\\2</A>", $joketext);

  6. #6

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

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

    Αν και κανένα 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]
    "); // Εμφανίζει "This
    "

    echo("$textarray[1]
    "); // Εμφανίζει "is
    "

    echo("$textarray[2]
    "); // Εμφανίζει "a
    "

    echo("$textarray[3]
    "); // Εμφανίζει "test.
    "

    Αν αντί να αναζητούμε έναν 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("

    <A HREF=\"$PHP_SELF?id=$id&page=$prevpage\">".

    "Προηγούμενη Σελίδα</A></P>");

    }

    // Το περιεχόμενο της σελίδας εμφανίζεται εδώ …

    if ($page < count($textarray) - 1) {

    $nextpage = $page + 1;

    echo("

    <A HREF=\"$PHP_SELF?id=$id&page=$nextpage\">".

    "Επόμενη Σελίδα</A></P>");

    }

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



    ...
    // Παίρνουμε (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]","", $joketext);

    $joketext = eregi_replace("\[eb]","
    ", $joketext);

    $joketext = eregi_replace("\[i]","", $joketext);

    $joketext = eregi_replace("\[ei]","
    ", $joketext);

    // Παράγραφοι και αλλαγές γραμμών

    $joketext = ereg_replace("\r", "", $joketext);

    $joketext = ereg_replace("\n\n", "

    ", $joketext);

    $joketext = ereg_replace("\n", "
    ", $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("

    <A HREF=\"$PHP_SELF?id=$id&page=$prevpage\">".

    "Προηγούμενη Σελίδα</A></P>");

    }

    echo( "

    $joketext" );

    if ($page < count($textarray) - 1) {

    $nextpage = $page + 1;

    echo("

    <A HREF=\"$PHP_SELF?id=$id&page=$nextpage\">".

    "Επόμενη Σελίδα</A></P>");

    }

    ...

  7. #7

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

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

    Θα δούμε τώρα πώς μπορούμε να δεχόμαστε 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.

  8. #8

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Προχωρημένη 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 για να αντιστρέψουμε τη σειρά ταξινόμησης.

  9. #9

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Η Έκφραση 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("

    Λάθος στην πρόσθεση ".

    "γι' αυτό το 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.

  10. #10

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Οι Εκφράσεις 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");

  11. #11

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Ψευδώνυμα (Aliases) Στηλών και Πινάκων

    Μερικές φορές είναι βολικό να αναφερόμαστε στις στήλες και στους πίνακες της MySQL με διαφορετικά ονόματα. Θα δούμε ένα παράδειγμα μιας βάσης δεδομένων που χρησιμοποιείται στο σύστημα κρατήσεων online μιας αεροπορικής εταιρείας. Για να παρουσιάσει τις πτήσεις που προσφέρονται από την εταιρεία, η βάση δεδομένων περιέχει τους εξής δύο πίνακες : Flights και Cities.

    Η κάθε καταχώρηση στον πίνακα Flights παριστάνει μια πραγματική πτήση ανάμεσα σε δύο πόλεις, την αρχή και τον προορισμό της πτήσης. Προφανώς, οι Origin και Destination θα αποτελούν στήλες του πίνακα Flights, μαζί μ’ άλλες στήλες για πράγματα όπως η ημερομηνία και η ώρα της πτήσης, ο τύπος του αεροσκάφους, ο αριθμός της πτήσης και τα διάφορα ναύλα.

    Ο πίνακας Cities περιέχει μια λίστα όλων των πόλεων προς τις οποίες πετάει η εταιρεία. Έτσι, και οι δύο στήλες Origin και Destination στον πίνακα Flights θα πρέπει να περιέχουν κωδικούς (ID's) για να αναφέρονται στις καταχωρήσεις του πίνακα Cities. Θα δούμε τώρα μερικά ερωτήματα (queries).

    Για να πάρουμε μια λίστα όλων των πτήσεων με τις πόλεις προέλευσής τους :

    mysql> SELECT Flights.Number, Cities.Name

    -> FROM Flights, Cities

    -> WHERE Flights.Origin = Cities.ID;

    +--------+-----------+

    | Number | Name |

    +--------+-----------+
    | CP110 | Montreal |

    | CP226 | Sydney |


    | QF2026 | Melbourne |

    ... ...

    Για να πάρουμε μια λίστα όλων των πτήσεων με τις πόλεις προορισμού τους :

    mysql> SELECT Flights.Number, Cities.Name

    -> FROM Flights, Cities

    -> WHERE Flights.Destination = Cities.ID;

    +--------+----------+

    | Number | Name |

    +--------+----------+

    | CP110 | Sydney |

    | CP226 | Montreal |

    | QF2026 | Sydney |

    ... ...

    Τι μπορούμε να κάνουμε τώρα αν θέλουμε να εμφανίσουμε την προέλευση και τον προορισμό της κάθε πτήσης μ’ ένα μόνο ερώτημα; Ένα ερώτημα που μπορεί να σκεφθούμε να χρησιμοποιήσουμε είναι το εξής :

    mysql> SELECT Flights.Number, Cities.Name, Cities.Name

    -> FROM Flights, Cities

    -> WHERE Flights.Origin = Cities.ID

    -> AND Flights.Destination = Cities.ID;

    Empty set (0.01 sec)

    Το παραπάνω ερώτημα δεν δουλεύει επειδή λέμε στην MySQL να ενώσει (join) τους πίνακες Flights και Cities και να εμφανίσει τον αριθμό πτήσης, το όνομα της πόλης και το όνομα της πόλης ξανά όλων των καταχωρήσεων που επιστρέφονται αν ταιριάξουμε το Origin με το City ID και το Destination με το City ID.

    Μ’ άλλα λόγια, οι στήλες Origin, Destination και City ID πρέπει να είναι ίσες μεταξύ τους. Αυτό έχει σαν αποτέλεσμα μια λίστα όλων των πτήσεων όπου η προέλευση και ο προορισμός είναι ίδιοι. Δεν θα υπάρχουν λοιπόν καθόλου καταχωρήσεις που να ταιριάζουν με την παραπάνω περιγραφή και έτσι είχαμε το αποτέλεσμα "Empty set".

    Αυτό που χρειαζόμαστε είναι ένας τρόπος να μπορούμε να επιστρέψουμε δύο διαφορετικές καταχωρήσεις από τον πίνακα Cities, μια για την προέλευση και μια για τον προορισμό, για κάθε αποτέλεσμα. Αν είχαμε δύο αντίγραφα του πίνακα, ένα με όνομα Origins και ένα με όνομα Destinations, αυτό θα ήταν πολύ εύκολο να γίνει, αλλά γιατί να έχουμε δύο πίνακες που να περιέχουν την ίδια ακριβώς λίστα των πόλεων;

    Η λύση είναι να δώσουμε στον πίνακα Cities δύο διαφορετικά προσωρινά ονόματα (ψευδώνυμα, aliases) για τους σκοπούς αυτού του ερωτήματος (query). Αν γράψουμε μετά από το όνομα ενός πίνακα την έκφραση AS Alias στο τμήμα FROM του ερωτήματος SELECT, μπορούμε να του δώσουμε ένα προσωρινό όνομα με το οποίο να αναφερόμαστε σ’ αυτό οπουδήποτε στο ερώτημα. Ακολουθεί το παραπάνω ερώτημα ξανά, αλλά αυτή τη φορά έχουμε δώσει στον πίνακα Cities το ψευδώνυμο (alias) Origins.

    mysql> SELECT Flights.Number, Origins.Name

    -> FROM Flights, Cities AS Origins

    -> WHERE Flights.Origin = Origins.ID;

    Αναφερόμενοι στον πίνακα Cities δύο φορές, χρησιμοποιώντας δύο διαφορετικά ψευδώνυμα (aliases), μπορούμε να χρησιμοποιήσουμε μια ένωση (join) τριών πινάκων, όπου οι δύο από τους πίνακες θα είναι ουσιαστικά ίδιοι, για να πάρουμε το αποτέλεσμα που θέλουμε :

    mysql> SELECT Flights.Number, Origins.Name,

    -> Destinations.Name

    -> FROM Flights, Cities AS Origins,

    -> Cities AS Destinations

    -> WHERE Flights.Origin = Origins.ID

    -> AND Flights.Destination = Destinations.ID;

    +--------+-----------+----------+

    | Number | Name | Name |

    +--------+-----------+----------+

    | CP110 | Montreal | Sydney |

    | CP226 | Sydney | Montreal |

    | QF2026 | Melbourne | Sydney |

    ... ... ...

    Μπορούμε επίσης να ορίσουμε ψευδώνυμα για τα ονόματα στηλών. Θα μπορούμε να το χρησιμοποιήσουμε αυτό, για παράδειγμα, για να διαχωρίσουμε τις δύο στήλες "Name" στον παραπάνω πίνακα αποτελεσμάτων :

    mysql> SELECT F.Number, O.Name AS Origin,

    -> D.Name AS Destination

    -> FROM Flights AS F, Cities AS O, Cities AS D

    -> WHERE F.Origin = O.ID AND F.Destination = D.ID;

    +--------+-----------+-------------+

    | Number | Origin | Destination |

    +--------+-----------+-------------+

    | CP110 | Montreal | Sydney |

    | CP226 | Sydney | Montreal |

    | QF2026 | Melbourne | Sydney |

    ... ... ...

  12. #12

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Η Έκφραση GROUP BY

    Στα προηγούμενα, είχαμε δει το παρακάτω query, το οποίο μας εμφανίζει πόσα jokes είναι αποθηκευμένα στον πίνακα Jokes :

    mysql> SELECT COUNT(*) FROM Jokes;

    +----------+

    | COUNT(*) |

    +----------+

    | 4 |

    +----------+

    Η συνάρτηση COUNT() της MySQL ανήκει σε μια ειδική κατηγορία συναρτήσεων άθροισης (summary functions) ή συναρτήσεων ομαδοποίησης (group-by functions). Σ’ αντίθεση μ’ άλλες συναρτήσεις οι οποίες επηρεάζουν τις καταχωρήσεις στο αποτέλεσμα του ερωτήματος SELECT, οι συναρτήσεις άθροισης ομαδοποιούν μαζί όλα τα αποτελέσματα και επιστρέφουν ένα μόνο αποτέλεσμα.

    Στο παραπάνω παράδειγμα, η συνάρτηση COUNT() επιστρέφει τον συνολικό αριθμό των γραμμών του αποτελέσματος.

    Ας υποθέσουμε ότι θέλουμε να εμφανίσουμε μια λίστα των συγγραφέων με τον αριθμό των jokes που αντιστοιχεί στον καθένα. Η πρώτη μας σκέψη θα ήταν να πάρουμε μια λίστα των ονομάτων και των ID’s όλων των συγγραφέων και μετά να χρησιμοποιήσουμε τη συνάρτηση COUNT() για να μετρήσουμε τον αριθμό των αποτελεσμάτων όταν κάνουμε SELECT στα jokes με το ID του κάθε συγγραφέα. Ο PHP κώδικας θα είναι ως εξής :

    // Μια λίστα όλων των συγγραφέων

    $authors = mysql_query( "SELECT Name, ID FROM Authors" );

    // Επεξεργασία του κάθε συγγραφέα

    while ($author = mysql_fetch_array($authors)) {

    $name = $author["Name"];

    $id = $author["ID"];

    // Μέτρηση των jokes που ανήκουν σ' αυτόν τον συγγραφέα

    $result = mysql_query(

    "SELECT COUNT(*) AS NumJokes ".

    "FROM Jokes WHERE AID=$id" );

    $row = mysql_fetch_array($result);

    $numjokes = $row["NumJokes"];

    // Εμφάνιση του συγγραφέα και του αριθμού των jokes

    echo("

    $name ($numjokes jokes)</P>");

    }

    Χρησιμοποιήσαμε το AS στο δεύτερο query παραπάνω για να δώσουμε ένα φιλικότερο όνομα (NumJokes) στο αποτέλεσμα της COUNT(*). Η τεχνική αυτή θα δουλέψει αλλά θα χρειασθεί n+1 ξεχωριστά ερωτήματα, όπου n είναι ο αριθμός των συγγραφέων στη βάση δεδομένων. Υπάρχει, όμως, μια λύση σ’ αυτό.

    Προσθέτοντας την έκφραση GROUP BY σ’ ένα ερώτημα SELECT, μπορούμε να πούμε στην MySQL να ομαδοποιήσει (group) τα αποτελέσματα του ερωτήματος σε σύνολα που να έχουν την ίδια τιμή στις στήλες που έχουμε καθορίσει. Οι συναρτήσεις άθροισης, όπως είναι η COUNT(), επενεργούν μετά σ’ αυτές τις ομάδες και όχι στο συνολικό αποτέλεσμα.

    Το ακόλουθο query, για παράδειγμα, εμφανίζει τον αριθμό των jokes που έχουν αποδοθεί σε κάθε συγγραφέα στη βάση δεδομένων :

    mysql> SELECT Authors.Name, COUNT(*) AS NumJokes

    -> FROM Jokes, Authors

    -> WHERE AID = Authors.ID

    -> GROUP BY AID;

    +-----------------+----------+

    | Name | NumJokes |

    +-----------------+----------+

    | Kevin Yank | 3 |

    | Joan Smith | 1 |

    | Ted E. Bear | 5 |

    +-----------------+----------+

    Ομαδοποιώντας τα αποτελέσματα ως προς το ID του συγγραφέα (AID), παίρνουμε μια ταξινόμηση των αποτελεσμάτων για τον κάθε συγγραφέα. Θα μπορούσαμε να είχαμε χρησιμοποιήσει και την έκφραση GROUP BY Authors.ID και να πάρουμε το ίδιο αποτέλεσμα.

  13. #13

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Η Έκφραση LEFT JOIN

    Μπορούμε να δούμε από τα παραπάνω αποτελέσματα ότι ο Kevin Yank έχει τρία jokes στο όνομά του, ο Joan Smith έχει ένα και ο Ted E. Bear έχει πέντε. Αυτό που δεν δείχνουν αυτά τα αποτελέσματα είναι ότι υπάρχει ένας τέταρτος συγγραφέας, η Amy Mathieson, που δεν έχει κανένα joke στο όνομά της. Εφόσον δεν υπάρχουν καταχωρήσεις στον πίνακα Jokes με AID's που να ταιριάζει το δικό της ID, δεν θα υπάρχουν αποτελέσματα που να ικανοποιούν την έκφραση WHERE στο παραπάνω ερώτημα γι’ αυτήν και συνεπώς θα αποκλειστεί από τον πίνακα των αποτελεσμάτων.

    Η MySQL παρέχει μια άλλη μέθοδο για την ένωση (joining) πινάκων, δηλ. την εμφάνιση πληροφοριών από πολλούς πίνακες ταυτόχρονα, που απoκαλείται left join, και είναι σχεδιασμένη γι’ αυτήν ακριβώς την κατάσταση. Για να κατανοήσουμε πώς διαφέρουν τα left joins από τα standard joins, πρέπει πρώτα να θυμηθούμε πώς δουλεύουν τα standard joins.

    Η MySQL εκτελεί ένα standard join δύο πινάκων εμφανίζοντας όλους τους δυνατούς συνδυασμούς των γραμμών αυτών των πινάκων. Σε μια απλή περίπτωση, ένα standard join δύο πινάκων με δύο γραμμές για τον καθένα θα περιέχει τέσσερις γραμμές. Αφού υπολογισθούν οι γραμμές του αποτελέσματος, η MySQL μετά κοιτάει την έκφραση WHERE για να πάρει οδηγίες για το ποιες γραμμές πρέπει να εμφανισθούν, όπως για παράδειγμα εκείνες που η στήλη AID του πίνακα 1 θα ταιριάζει με τη στήλη ID του πίνακα 2.

    Ο λόγος που το παραπάνω δεν ικανοποιεί τους σκοπούς μας είναι ότι θα θέλαμε να συμπεριλάβουμε επίσης και τις γραμμές του πίνακα 1 (Authors) που δεν έχουν κάποιες γραμμές που να ταιριάζουν στον πίνακα 2 (Jokes). Ένα left join κάνει ό,τι ακριβώς χρειαζόμαστε, αναγκάζοντας μια γραμμή να εμφανισθεί στα αποτελέσματα για κάθε γραμμή του πρώτου (αριστερού) πίνακα, ακόμη κι αν δεν βρεθούν καταχωρήσεις που να ταιριάζουν στον δεύτερο (δεξιό) πίνακα. Αυτές οι καταχωρήσεις παίρνουν τιμές NULL γι’ όλες τις στήλες του δεξιού πίνακα.

    Για να κάνουμε ένα left join ανάμεσα σε δύο πίνακες στην MySQL, διαχωρίζουμε τα ονόματα των δύο πινάκων στην έκφραση FROM με το LEFT JOIN αντί με κόμμα. Γράφουμε μετά το όνομα του δεύτερου πίνακα με ON <συνθήκη>, όπου η <συνθήκη> καθορίζει τα κριτήρια ταιριάσματος των γραμμών στους δύο πίνακες. Ακολουθεί το αναθεωρημένο ερώτημα για την εμφάνιση των συγγραφέων με τον αριθμό των jokes που τους έχει αποδοθεί :

    mysql> SELECT Authors.Name, COUNT(*) AS NumJokes

    -> FROM Authors LEFT JOIN Jokes

    -> ON AID = Authors.ID

    -> GROUP BY AID;

    +---------------+----------+

    | Name | NumJokes |

    +---------------+----------+

    | Amy Mathieson | 1 |

    | Kevin Yank | 3 |

    | Joan Smith | 1 |

    | Ted E. Bear | 5 |

    +---------------+----------+

    Πρέπει να έχουμε υπόψη μας ότι η συνάρτηση COUNT(*) μετράει τον αριθμό των γραμμών που επιστρέφονται για κάθε συγγραφέα. Αν κοιτάξουμε στα μη ομαδοποιημένα αποτελέσματα του LEFT JOIN, θα δούμε τα εξής :

    mysql> SELECT Authors.Name, Jokes.ID AS JokeID

    -> FROM Authors LEFT JOIN Jokes

    -> ON AID = Authors.ID;

    +---------------+--------+

    | Name | JokeID |

    +---------------+--------+

    | Kevin Yank | 1 |

    | Kevin Yank | 2 |

    | Kevin Yank | 4 |

    | Joan Smith | 3 |

    | Ted E. Bear | 5 |

    | Ted E. Bear | 6 |

    | Ted E. Bear | 7 |

    | Ted E. Bear | 8 |

    | Ted E. Bear | 9 |

    | Amy Mathieson | NULL |

    +---------------+--------+

    Τώρα η Amy Mathieson έχει μια γραμμή με τιμή NULL. Το ότι η τιμή του Joke ID είναι NULL δεν επηρεάζει την συνάρτηση COUNT(*)× αυτή το μετράει σαν μια γραμμή. Αν αντί για το *, προσδιορίσουμε το όνομα μιας στήλης, όπως Jokes.ID, θα αγνοήσει τις τιμές NULL αυτής της στήλης και θα μας δώσει το αποτέλεσμα που ψάχνουμε :

    mysql> SELECT Authors.Name, COUNT(Jokes.ID) AS NumJokes

    -> FROM Authors LEFT JOIN Jokes

    -> ON AID = Authors.ID

    -> GROUP BY AID;

    +---------------+----------+

    | Name | NumJokes |

    +---------------+----------+

    | Amy Mathieson | 0 |

    | Kevin Yank | 3 |

    | Joan Smith | 1 |

    | Ted E. Bear | 5 |

    +---------------+----------+

  14. #14

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

    Η Έκφραση HAVING

    Τι γίνεται, όμως, αν θελήσουμε μια λίστα μόνο εκείνων των συγγραφέων που δεν έχουν κανένα joke στο όνομά τους; Ας δούμε πρώτα το ερώτημα που θα επέλεγαν οι περισσότεροι χρήστες :

    mysql> SELECT Authors.Name, COUNT(Jokes.ID) AS NumJokes

    -> FROM Authors LEFT JOIN Jokes

    -> ON AID = Authors.ID

    -> WHERE NumJokes = 0

    -> GROUP BY AID;

    ERROR 1054: Unknown column 'NumJokes' in 'where clause'
    Ο λόγος που η έκφραση WHERE NumJokes = 0 δεν μας έκανε τη δουλειά είναι επειδή οι συνθήκες στην έκφραση WHERE επηρεάζουν τις καταχωρήσεις που έχουν επιλεγεί πριν ομαδοποιηθούν σύμφωνα με την έκφραση GROUP BY.

    Έτσι, αν θελήσουμε να αποκλείσουμε από το μέτρημα τα jokes που περιέχουν τη λέξη "chicken", θα μπορούσαμε να χρησιμοποιήσουμε την έκφραση WHERE, όμως εφόσον η στήλη NumJokes δεν υπάρχει πριν επενεργήσει η GROUP BY, θα πρέπει να χρησιμοποιήσουμε μια διαφορετική μέθοδο για να ορίσουμε συνθήκες.

    Οι συνθήκες που επηρεάζουν τα αποτελέσματα αφού έχει γίνει η ομαδοποίηση (grouping) πρέπει να εμφανισθούν σε μια ειδική έκφραση HAVING. Έτσι λοιπόν, το σωστό ερώτημα είναι το εξής :

    mysql> SELECT Authors.Name, COUNT(Jokes.ID) AS NumJokes

    -> FROM Authors LEFT JOIN Jokes

    -> ON AID = Authors.ID

    -> GROUP BY AID

    -> HAVING NumJokes = 0;

    +---------------+----------+

    | Name | NumJokes |

    +---------------+----------+

    | Amy Mathieson | 0 |

    +---------------+----------+

    Μερικές συνθήκες εργάζονται και στις δύο εκφράσεις HAVING και WHERE. Για παράδειγμα, αν θελήσουμε να αποκλείσουμε έναν συγκεκριμένο συγγραφέα με το όνομά του, θα μπορούσαμε να χρησιμοποιήσουμε το Authors.Name != "AuthorName" σε μια από τις εκφράσεις WHERE ή HAVING, επειδή αν φιλτράρουμε τον συγγραφέα πριν ή μετά από την ομαδοποίηση, θα πάρουμε τα ίδια αποτελέσματα.

    Σε μερικές περιπτώσεις, είναι πάντα καλύτερο να χρησιμοποιούμε την έκφραση WHERE, επειδή η MySQL είναι καλύτερη στο να βελτιστοποιεί εσωτερικά τέτοια ερωτήματα και έτσι εκτελούνται ταχύτερα.

  15. #15

    Εγγραφή
    Jun 2008
    Περιοχή
    Athens
    Μηνύματα
    8.313
    Liked
    567 times
    Τα Στατιστικά μου στο Arcade
    Blog Entries
    3

    Re: Προχωρημένα Θέματα στην PHP

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

    Η ισχύς της PHP βρίσκεται στην τεράστια βιβλιοθήκη της από ενσωματωμένες συναρτήσεις που περιέχει, οι οποίες μας δίνουν τη δυνατότητα να κάνουμε πολύ πολύπλοκες εργασίες χωρίς να χρειασθεί να εγκαταστήσουμε νέες βιβλιοθήκες ή να ανησυχούμε για λεπτομέρειες, όπως συμβαίνει συχνά μ’ άλλες δημοφιλείς server-side γλώσσες όπως είναι η Perl. Θα δούμε μερικά από τα χρήσιμα χαρακτηριστικά που έχει να προσφέρει η PHP σε κάποιον που δημιουργεί ένα database driven Web site.

    Θα ξεκινήσουμε με τη συνάρτηση include() της PHP, η οποία μας δίνει τη δυνατότητα να χρησιμοποιήσουμε ένα κομμάτι κώδικα της PHP σε πολλές σελίδες. Θα δούμε επίσης το πώς μπορούμε να προσθέσουμε ένα επιπλέον επίπεδο ασφάλειας στο site μας μ’ αυτό το χαρακτηριστικό.

    Η PHP, ενώ είναι γενικά γρήγορη και αποδοτική, παρ’ όλα αυτά επιβαρύνει τον χρόνο φόρτωσης (load time) και το φορτίο εργασίας (workload) του μηχανήματος πάνω στο οποίο τρέχει ο server. Σε sites με μεγάλη κυκλοφορία, αυτό το φορτίο μπορεί να αυξηθεί σε μη αποδεκτά επίπεδα. Αλλά αυτό δεν σημαίνει ότι πρέπει να εγκαταλείψουμε την database-driven φύση του site μας. Θα δούμε πώς μπορούμε να χρησιμοποιήσουμε την PHP στον παρασκήνιο για να δημιουργήσουμε ημιδυναμικές (semi-dynamic) σελίδες που δεν φορτώνουν τον server τόσο πολύ.

    Μια κοινή ερώτηση είναι πώς μπορούμε να χρησιμοποιήσουμε ένα tag <INPUT TYPE=FILE> για να δεχθούμε uploads αρχείων από τους επισκέπτες του site. Θα μάθουμε πώς μπορούμε να το κάνουμε αυτό με την PHP.

    Τέλος, ένα εξαιρετικά ισχυρό χαρακτηριστικό της PHP είναι η ικανότητά της να στέλνει εύκολα μηνύματα email με δυναμικά παραγόμενο περιεχόμενο. Είτε θέλουμε να χρησιμοποιήσουμε την PHP για να επιτρέψουμε στους επισκέπτες να στέλνουν με email παραλλαγές του περιεχομένου του site μας στους φίλους τους ή απλά να παρέχουμε έναν τρόπο στους χρήστες για να ανακτούν τα ξεχασμένα passwords τους, η συνάρτηση email() της PHP κάνει καλή δουλειά.

 

 

Πληροφορίες Θέματος

Users Browsing this Thread

Υπάρχουν 1 χρήστης/ες που πλοηγούνται σ' αυτό το θέμα. (0 μέλος/η και 1 επισκέπτης/ες)

Παρόμοια Θέματα

  1. Συναφή θέματα
    By Dr.Overflow in forum Ανακοινώσεις Supas
    Απαντήσεις: 2
    Τελευταίο Μήνυμα: 18-05-2010, 20:36
  2. Βασικά καταναλωτικά θέματα
    By Μαρακι in forum Συμβουλές - TIPS
    Απαντήσεις: 1
    Τελευταίο Μήνυμα: 26-09-2009, 20:06
  3. ΠΡΟΤΑΣΕΙΣ..ΓΙΑ ΝΕΑ ΘΕΜΑΤΑ..
    By thiseas in forum Ερωτήσεις - Απαντήσεις - Σχόλια και Προτάσεις
    Απαντήσεις: 8
    Τελευταίο Μήνυμα: 22-09-2009, 16:30
  4. ΔΟΡΥΦΟΡΙΚΑ ΘΕΜΑΤΑ
    By Κατερίνα in forum ΧΡΗΣΙΜΑ LINK
    Απαντήσεις: 0
    Τελευταίο Μήνυμα: 09-10-2008, 16:11

Δικαιώματα - Επιλογές

  • Δεν μπορείτε να δημοσιεύετε νέα θέματα
  • Δεν μπορείτε να απαντάτε σε θέματα
  • Δεν μπορείτε να δημοσιεύετε συνημμένα
  • Δεν μπορείτε να επεξεργάζεστε τις δημοσιεύσεις σας
  •