MySQL, PHP και Ελληνικά (Μέρος 1ο)
Στο άρθρο αυτό καλύπτουμε πρακτικά μέσω ενός παραδείγματος τη χρήση ελληνικών χαρακτήρων στη βάση δεδομένων MySQL και ειδικά την περίπτωση εγγραφής και ανάγνωσης στη βάση μέσω της γλώσσας PHP, ώστε να λειτουργούν σωστά τα Ελληνικά στις εφαρμογές σας.
Επειδή ο τρόπος που χειρίζεται η MySQL τα διάφορα σετ χαρακτήρων (character sets) άλλαξε από την έκδοση 4.1 της MySQL και μετά, στο άρθρο θα καλυφθούν συνολικά οι εξής 3 περιπτώσεις:
- Χρήση ελληνικών χαρακτήρων σε MySQL version < 4.1
- Χρήση ελληνικών χαρακτήρων σε MySQL version 4.1 +
- Migration (μεταφορά) υπάρχουσας βάσης δεδομένων από MySQL version < 4.1 σε MySQL version 4.1 +
Σε αυτό το 1ο μέρος του άρθρου καλύπτουμε τις 2 πρώτες περιπτώσεις, ενώ η 3η περίπτωση θα ακολουθήσει στο 2ο μέρος του άρθρου.
H MySQL με το πέρασμα του χρόνου αποκτά όλο και περισσότερα χαρακτηριστικά που έχουν μεγάλα συστήματα βάσεων δεδομένων (όπως οι Oracle database server, MS SQL server, IBM DB2 server). Στην έκδοση 4.1 η MySQL βελτιώθηκε και στην υποστήριξη διαφορετικών character sets και collations. Εφαρμογές που έχουν δημιουργηθεί για εκδόσεις της MySQL μικρότερες της 4.1 ενδέχεται να πάψουν να λειτουργούν σωστά στην περίπτωση αναβάθμίσης της MySQL και τότε χρειάζονται συγκεκριμένες ενέργειες για να υποστηρίζονται ξανά σωστά οι Ελληνικοί χαρακτήρες.
Το παράδειγμα
Θεωρούμε ότι έχουμε μια βάση δεδομένων με όνομα my_db, η οποία έχει έναν πίνακα με όνομα persons και 2 πεδία: id (int) και name (varchar). Στο πεδίο name θέλουμε να αποθηκεύουμε Ελληνικούς χαρακτήρες.
Ενδεικτικά ένα στιγμιότυπο του πίνακα persons μπορεί να έχει ως εξής:
id | name |
---|---|
1 | Ορέστης |
2 | Βασιλική |
3 | Larry |
Παρακάτω θα δούμε πως μπορούμε να δημιουργήσουμε αυτές τις εγγραφές μέσω PHP και να δείξουμε τις εγγραφές αυτές του πίνακα σωστά σε μια web σελίδα μέ χρήση php, στις περιπτώσεις που αναφέραμε.
MySQL version < 4.1
Η περίπτωση αυτή αναφέρεται για λόγους πληρότητας. Μια εφαρμογή που αναπτύσσεται σήμερα στη MySQL θα χρησιμοποιεί κανονικά πιο σύγχρονη έκδοση της MySQL. Στις εκδόσεις < 4.1 της MySQL δεν υπάρχει η υποστήριξη των character sets και collations όπως εμφανίζεται στις μεταγενέστερες εκδόσεις.
Για να υποστηρίζονται τα Ελληνικά σε αυτές τις παλαιότερες εκδόσεις της MySQL, ο MySQL server πρέπει να τρέχει κατά την έναρξή της με την εξής ρύμθιση (π.χ. στο αρχείο my.cnf ή my.ini του συστήματος).
[mysqld]
default-character-set=greek
Με αυτόν τον τρόπο υποστηρίζονται τα Ελληνικά στη MySQL (δηλώνοντας τo default character set στον server καθορίζουμε ποιοί χαρακτήρες επιτρέπονται στα ονόματα και πως γίνεται η ταξινόμηση στα ORDER BY και GROUP BY των εντολών SELECT).
Δημιουργία του σχήματος στη MySQL
Ακολουθούν οι εντολές για τη δημιουργία του σχήματος του παραδείγματός μας.
Για να εκτελέσετε τις παρακάτω SQL εντολές μπορείτε να χρησιμοποιήσετε το command line tool «mysql» της MySQL ή οποιοδήποτε άλλο πρόγραμμα σας επιτρέπει την εκτέλεση εντολών SQL στη MySQL (όπως το phpmyadmin ή το SQLyog).
Δημιουργία Βάσης Δεδομένων:
CREATE DATABASE my_db;
Επιλογή της νέας βάσης δεδομένων:
USE my_db;
Δημιουργία πίνακα persons στη βάση δεδομένων my_db:
CREATE TABLE persons (
id int(10),
name varchar(40),
PRIMARY KEY (id)
);
Έτσι θα έχουμε στη στη διάθεσή μας τη βάση δεδομένων my_db με τον πίνακα persons (πίνακας τύπου MyISAM).
Κώδικας PHP/HTML
Ακολουθεί ο κώδικας της σελίδας/script για την εισαγωγή των δεδομένων στον πίνακα (π.χ. example_insert.php):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso8859-7" >
<title>Εισαγωγή Δεδομένων</title>
</head>
<body>
<p>php script εισαγωγής δεδομένων</p>
<?php
//Create a connection to MySQL and select "my_db" database
//$con = mysql_connect("hostname","username","password")
or die( 'Could not connect to DB: ' . mysql_error() );
mysql_select_db("my_db", $con) or die(mysql_error());
// Insert data
mysql_query("INSERT INTO persons (id, name) VALUES ('1', 'Ορέστης' ) ")
or die(mysql_error());
mysql_query("INSERT INTO persons (id, name) VALUES ('2', 'Βασιλική' ) ")
or die(mysql_error());
mysql_query("INSERT INTO persons (id, name) VALUES ('3', 'Larry' ) ")
or die(mysql_error());
//Close our connection
mysql_close($con);
?>
</body>
</html>
O κώδικας της σελίδας/script για την προβολή των δεδομένων του πίνακα (π.χ. example_select.php):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso8859-7" >
<title>Προβολή δεδομένων</title>
</head>
<body>
<p>Αποτελέσματα του SELECT (ταξινομημένα):</p>
<?php
//Create a connection to MySQL and select "my_db" database
//$con = mysql_connect("hostname","username","password")
or die( 'Could not connect to DB: ' . mysql_error() );
mysql_select_db("my_db", $con) or die( mysql_error() );
//Execute the SQL query
$result = mysql_query("SELECT * FROM persons ORDER BY name");
while($row = mysql_fetch_array($result)) {
echo $row['id'] . " - " . $row['name'];
echo "<br>";
}
//Close our connection
mysql_close($con);
?>
</body>
</html>
Και στα 2 παραπάνω scripts για να λειτουργήσουν πρέπει να αντικαταστήσετε τις παραμέτρους στην κλήση της συνάρτησης mysql_connect() με τα σωστά στοιχεία για την περίπτωση σας (δηλαδή σωστό hostname ή IP, username και password ώστε να συνδεθεί η PHP επιτυχώς στη MySQL).
MySQL εκδόσεις 4.1+
Σε εκδόσεις μεγαλύτερες ή ίσες της 4.1, υποστηρίζονται πλέον διαφορετικά character sets και collations σε διαφορετικά σημεία/επίπεδα του συστήματος (όπως σε επίπεδο σύνδεσης με τη MySQL, βάσης, πίνακα, πεδίου κ.α.). Αυτή η υποστήριξη αντικατοπτρίζεται πια τόσο στον κώδικα SQL, όσο και σε διαφορετικά σημεία της υλοποίησής.
Χωρίς να αποτελεί μονόδρομο, στο παράδειγμά μας για την υποστήριξη των Ελληνικών θα επιλέξουμε να χρησιμοποιούμε το utf8 character set (unicode character set – με τον τρόπο αυτόν δεν έχετε υποστήριξη μόνο για Ελληνικά, αλλά για πλήθος γλωσσών ταυτόχρονα, με μειονέκτημα όμως τη χρήση περισσότερου χώρου και μνήμης για τη λειτουργία της βάσης – συνήθως όμως αυτό δεν αποτελεί πρόβλημα και δεν σας απασχολεί).
Δημιουργία του σχήματος στη MySQL
Ακολουθούν οι εντολές για τη δημιουργία του σχήματος του παραδείγματός μας. Για να εκτελέσετε τις παρακάτω SQL εντολές, όπως και στην περίπτωση της MySQL version < 4.1, μπορείτε να χρησιμοποιήσετε το command line tool «mysql» της MySQL ή οποιοδήποτε άλλο πρόγραμμα που σας επιτρέπει την εκτέλεση εντολών SQL στη MySQL (όπως το phpmyadmin ή το SQLyog).
Δημιουργία Βάσης Δεδομένων:
CREATE DATABASE my_db DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Επιλογή της νέας βάσης δεδομένων:
USE my_db;
Δημιουργία πίνακα:
CREATE TABLE persons (
id int(10),
name varchar(40) collate utf8_unicode_ci,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_unicode_ci
CHARSET=utf8 COLLATE=utf8_unicode_ci;
Παρατηρούμε ότι πλέον (σε σχέση με την περίπτωση της MySQL < 4.1) αναφέρουμε πλέον ρητά τα character sets και τα collations που θέλουμε να χρησιμοποιούνται στη βάση my_db, στον πίνακα persons και στο πεδίο name.
Συγκεκριμένα, έχουμε δηλώσει για τη βάση δεδομένων και για τον πίνακα persons ότι θα χρησιμοποιούν to utf8 character set. Στον πίνακα persons και στο πεδίο name έχουμε δηλώσει να χρησιμοποιείται το collation utf8_unicode_ci (utf8, case insensitive).
Τα collations μπορείτε να τα δείτε ως «οδηγίες» προς τη βάση δεδομένων ώστε να ταξινομούνται σωστά τα δεδομένα σας (π.χ. στην περίπτωση ενός ORDER BY κλάδου στην SQL). Αν βλέπετε σωστά Ελληνικά, αλλά λάθος ταξινομήσεις στα δεδομένα σας αυτό που πρέπει να κοιτάξετε είναι το collation που χρησιμοποιείται.
Κώδικας PHP/HTML
H σελίδα/script για την εισαγωγή των δεδομένων στον πίνακα (π.χ. example_insert.php):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Εισαγωγή Δεδομένων</title>
</head>
<body>
<p>script εισαγωγής δεδομένων</p>
<?php
//Create a connection to MySQL and select "my_db" database
//$con = mysql_connect("hostname","username","password")
or die( 'Could not connect to DB: ' . mysql_error() );
mysql_select_db("my_db", $con) or die(mysql_error());
mysql_query("SET NAMES 'utf8'", $con);
// Insert data
mysql_query("INSERT INTO persons (id, name) VALUES ('1', 'Ορέστης' ) ")
or die(mysql_error());
mysql_query("INSERT INTO persons (id, name) VALUES ('2', 'Βασιλική' ) ")
or die(mysql_error());
mysql_query("INSERT INTO persons (id, name) VALUES ('3', 'Larry' ) ")
or die(mysql_error());
//Close our connection
mysql_close($con);
?>
</body>
</html>
H σελίδα/script για την προβολή των δεδομένων του πίνακα (π.χ. example_select.php):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Προβολή δεδομένων</title>
</head>
<body>
<p>Αποτελέσματα του SELECT (ταξινομημένα):</p>
<?php
//Create a connection to MySQL and select "my_db" database
//$con = mysql_connect("hostname","username","password")
or die( 'Could not connect to DB: ' . mysql_error() );
mysql_select_db("my_db", $con) or die( mysql_error() );
mysql_query("SET NAMES 'utf8'", $con);
//Execute the SQL query
$result = mysql_query("SELECT * FROM persons ORDER BY name");
while($row = mysql_fetch_array($result)) {
echo $row['id'] . " - " . $row['name'];
echo "<br>";
}
//Close our connection
mysql_close($con);
?>
</body>
</html>
Τα 2 scripts έχουν τις εξής διαφορές σε σχέση με αυτά που είχαμε για την περίπτωση της MySQL < 4.1
Η ύπαρξη της γραμμής:
mysql_query("SET NAMES 'utf8'", $con);
Αυτό που κάνει η γραμμή αυτή είναι να εκτελεί την εντολή:
SET NAMES 'utf8';
στην σύνδεση $con που έχει γίνει με τη Βάση Δεδομένων.
Η εντολή αυτή δίνει στις παραμέτρους character_set_client, character_set_results και character_set_connection της σύνδεσης που κάνει η PHP με τη βάση δεδομένων την τιμή ‘utf8’.
Στην html των 2 web σελίδων που δημιουργούνται μέσω των 2 παραπάνω php αρχείων επιλέγεται (META tags) ως character set το utf8 (αυτό θα μπορούσε να ακολουθείται και από αντίστοιχη κλήση της συνάρτησης header() της php ώστε να στέλνεται to utf-8 character set).
Τα αρχεία, λόγω της χρήσης utf-8 χαρακτήρων, αυτή τη φορά πρέπει να αποθηκευτούν με utf8 encoding. Ανάλογα με τον editor που χρησιμοποιείτε για να γράψετε τον κώδικα αυτό γίνεται με διαφορετικό τρόπο. Μερικά ενδεικτικά παραδείγματα:
- Windows και notepad: Στις τελευταίες εκδόσεις του nodepad των Windows καθώς επιλέγετε «File»/»Save As» μπορείτε να διαλέξετε και από τη λίστα επιλογών για encoding τo UTF-8.
- Windows και Dreamweaver MX: Μπορείτε να επιλέξετε «Modify»/»Page Properties» και στο «Title/Encoding» να δώσετε στο drop-down «Encoding» την τιμή «Unicode (UTF-8)».
Unix/Linux: Στον vim μπορείτε να δώσετε την εντολή:
:set encoding=utf-8
και αν χρειάζεται και την εντολή:
:set guifont=-misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1
Εναλλακτικά μπορείτε να χρησιμοποιήσετε το πρόγραμμα iconv για τη μετατροπή.
Εάν δεν κάνετε την αποθήκευση σε utf-8, για παράδειγμα αν δεν αποθηκεύσετε το αρχείο example_insert.php με UTF-8 encoding, τότε η εκτέλεση του script θα έχει ως αποτέλεσμα τη λανθασμένη εισαγωγή δεδομένων στον πίνακα (με αποτέλεσμα να βλέπετε ερωτηματικά ή κενά στο πεδίο name όπου έχει Ελληνικούς χαρακτήρες).
Συνήθως τα δεδομένα που εισάγετε σε έναν πίνακα δεν είναι hard-coded στον κωδικά όπως στο παράδειγμά μας, αλλά προέρχονται από φόρμες HTML. Στην περίπτωση αυτή οι σύγχρονοι browsers αναγνωρίζουν ότι η σελίδα από την οποία προέρχονται τα δεδομένα (π.χ. μια σελίδα με μια HTML φόρμα) έχει endoding utf-8 και στέλνουν τα δεδομένα που συμπλήρωσε ο χρήστης επίσης σε utf-8 πίσω στον server.
Πώς μπορούμε να αποφύγουμε τη χρήση της γραμμής mysql_query(«SET NAMES ‘utf8′», $con) ώστε ο php κώδικας των scripts να μη διαφέρει από αυτόν για την περίπτωση MySQL < 4.1;
Αυτό δεν είναι πάντοτε εφικτό. Για να αποφύγουμε τη χρήση και την εκτέλεση αυτής της εντολής (SET NAMES) πρέπει να έχουμε πρόσβαση στις ρυθμίσεις του MySQL server που χρησιμοποιούμε. Εάν έχουμε πρόσβαση μπορούμε να το αποφύγουμε, προσθέτοντας στις ρυθμίσεις με τις οποίες ξεκινά ο server (π.χ. στο αρχείο my.cnf ή my.ini του συστήματος), στο section [mysqld] την παρακάτω γραμμή:
[mysqld] default-character-set=utf8
Aυτό έχει ως αποτέλεσμα οι μεταβλητές της MySQL character_set_server, character_set_database, collation_database και collation_server να παίρνουν την τιμή: utf8.
Εδώ ολοκληρώνεται το 1ο μέρος του άρθρου «MySQL, PHP και Ελληνικά». Στο 2ο μέρος θα δούμε το θέμα του migration μιας υπάρχουσας βάσης δεδομένων από MySQL version < 4.1 σε έκδοση MySQL 4.1+.
Αυτό το έργο, εκτός αν έχει ρητώς διατυπωθεί διαφορετικά, εκδίδεται υπό μία Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Άδεια.
21 Σχόλια στο “MySQL, PHP και Ελληνικά (Μέρος 1ο)”
Πολύ καλό άρθρο. Πολύ όμορφο theme στο site.
Χαίρομαι όταν βλέπω τέτοιο επίπεδο σε Ελληνικό blog.
Μπράβο.
Συμφωνώ.
Τέλειο άρθρο.
Όλα εξηγούνται πολύ καλά. Με βοήθησε πάρα πολύ.
Para polu kalo,
diafotistikotato..
Ευχαριστώ για την βοήθεια. Ακριβώς ότι απαιτήτe για την αποθήκευση και την εξόρυξη ελληνικών χαρακτήρων από μία MySQL βάση μέσω PHP.
Big up!
Ευχαριστώ πάαααααααααααραα πολύ. Μόλις είχα αρχίσει να απελπίζομαι με το phpmyadmin 4.1 και νόμιζα ότι εδώ τελειώναν όλα…
Πολύ καλή δομή του άρθρου και επαρκής επεξήγηση να μην υπάρχουν πουθενά λάθη…
το openspot.gr μπαίνει αυτόματα στα favorites μου…thx again!!!!
poly poly kalo to arthraki!!! Na’stai kala!
Καλό άρθρο.
Ένα πρόβλημα μόνο: Πώς μπορώ να κάνω case-insensitive αναζήτηση? Για παράδειγμα αν γράψω «ελληνικά» αντί «Ελληνικά» στο πεδίο αναζήτησης αυτού του Blog αυτό το άρθρο δεν παρουσιάζεται στα αποτελέσματα.
Thanks !
Καλο το άρθρο αλλά παρόλο που είναι όλα σετ σε utf8 και δουλεύει η σελίδα μια χαρά όταν κάνω browse τον πίνακα από το PHPmyAdmin παίρνω σδφγσδφγσδφγ Γιατι?
Teleio, thanks!!!
Πολύ καλό το άρθο αλλά τι γίνεται στην περίπτωση που ΔΕΝ θέλω να χρησιμοποιήσω UTF8 αλλά κωδικοποίηση iso-8859-7; Καλό το UTF8 αλλά τα δεδομένα θέλουν περισσότερο χώρο στη βάση για να αποθηκευτούν!
Ας μην υπερβάλουμε πλέον με τον περισσότερο χώρο στη βάση που θέλουν τα utf-8. Σήμερα ο χώρος έχει γίνει πολύ φτηνός ώστε να μας απασχολεί στις επιλογές μας. Αν κάποιος φτάσει να έχει τόσα δεδομένα ώστε ο χώρος να είναι θέμα, τότε μάλλον έχει και αρκετά σημαντικούς λόγους να τον αυξήσει που είναι φτηνό.
Η μόνη περίπτωση που έχει νόημα να μιλάμε για οικονομία χώρου είναι για mysql πίνακες που είναι στη μνήμη (HEAP tables). Μόον εκεί είναι πια λογικό να μιλάμε για οικονομία χώρου.
Εξαιρετικό το άρθρο σου. Αυτό το mysql_query(«SET NAMES ‘utf8′», $con); μ’ έσωσε. Να ‘σαι καλά.
Αναρωτιέμαι, το «collate utf8_unicode_ci», μετά από κάθε πεδίο του πίνακα, εξυπηρετεί κάτι, εφόσον έχουμε ορίσει ήδη ως προυεπιλογή σε όλα τα πεδία κειμένου του πίνακα το «DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_unicode_ci CHARSET=utf8 COLLATE=utf8_unicode_ci»;
Δοκίμασα να δημιουργήσω πίνακες που προσδιοριζόταν τόσο σαν προεπιλογή του πίνακα, χωρίς να προσδιορίζεται στο κάθε πεδίο, όσο και αντίστροφα, και απο τη MySQL, το αποτέλεσμα φαίνεται να είναι το ίδιο.
Κάποια διευκρίνηση παρακαλώ;
ΕΥΧΑΡΙΣΤΩ!
ΤΡΕΙΣ ΜΕΡΕΣ ΠΡΟΣΠΑΘΟΥΣΑ ΝΑ ΒΡΩ ΤΙ ΛΥΣΗ ΣΤΟ «ΙΝΤΕΡΝΕΤ» ΑΛΛΑ ΤΙΠΟΤΑ..ΧΩΡΙΣ ΑΥΤΗ ΤΗ ΓΡΑΜΜΗ ΔΕΝ ΕΜΦΑΝΙΖΩΝΤΑΝ ΤΑ ΕΛΛΗΝΙΚΑ..(mysql_query(«SET NAMES ‘utf8′», $conn);)….
Παιδία εγώ δοκιμάσα τον wampp (εκδ 5.1 της mysql)
αν θυμάμαι καλά..
Έκανα την αλλαγή στο my.ini αλλά δεν έγινε κάτι..???::(((
Πολύ καλό άθρο…
αλλα θα χρειαζόμουν την βοήθειά σας
παρόλα ποθ χρησιμοποιώ
mysql_query(«SET NAMES ‘utf8′», $con);
mysql_query(«SET CHARACTER SET ‘utf8′», $con);
, παρόλα ποθ έχω αλλάξει το collation σε utf8, εξακολουθούν τα data που ΒΑΖΩ στην βάση να μου τα βγάζει με ‘?‘….
Αν έχεις ορίσει στα πεδία τού MySQl database-πίνακα (table) utf8-unicode-ci όπως και όλη τήν database επίσης, και θέλεις μέσα στό phpMyAdmin να ΕΙΣΑΓΕΙΣ από .txt ή .csv αρχείο datarecords, ΠΩΣ ΜΠΟΡΕΙΣ να βλέπεις τίς καταχωρήσεις στόν πίνακα επίσης στα ελληνικά; Δοκίμασα στήν κωδικοποίηση του αρχείου διάφορες κωδικοποιήσεις χωρίς το επιθυμητό αποτέλεσμα. Επίσης οφείλουν ταυτόχρονα να περιγράφονται και γερμανικά Ö,ö,ü k.l.p.
Επειδή δεν μπορούσα να στείλω το κείμενο , μήπως μπορείτε να δείτε αυτό ; Κάτι πρόβλημα πρέπει να έχει η φόρμα επικοινωνίας
ideone.com/V2QFC
Καλησπερα σας, διαβασα το αρθρο MySQL, PHP και Ελληνικά (Μέρος 1ο) και ομολογω πως με βοηθησε παρα πολυ. Ωστοσο, με τον τροπο αυτο τα δεδομενα που καταχωρουνται δεν φαινονται στην βαση με ελληνικους χαρακτηρες (χρησιμοποιω utf8) επιπλεον αν κανω εισαγωγη απ την βαση μου εμφανιζει ???? στο site….μηπως μπορειτε να με βοηθησετε? σας ευχαριστω εκ των πρωτερων
Paidia gia na fanoun ta elinika gramata kante ti baasi dedomenon «greek_bin» kai ola tha pane kala.
sygnomi gia ta greeklish!!!