מדריך PDO – הרחבה לעבודה מול מסד הנתונים

כיום קיימות מספר הרחבות המאפשרות עבודה מול מסדי נתונים.
PDO היא אחת מההרחבות המומלצות ביותר, במדריך זה נכיר את יתרונותיה, אופן פעולתה ונכתוב מספר דוגמאות.

בואו נתחיל עם הקדמה קלה, ההרחבות הנפוצות ביותר הן: MySQL, MySQLi ו-PDO.
פירוט בקצרה:

MySQL – הרחבה ישנה, deprecated מגרסא 5.5, עובדת בצורה פרוצדורלית בלבד ופריצה מאוד.
MySQLi – חידוש הרחבת MySQL, משמעות ה-i היא Improved (שיפור) ואין ספק שזוהי הרחבה מעולה, המון מתכנתים עדיין עובדים עם MySQLi והיא אפילו תומכת בתכנות מונחה עצמים.
PDO – ההרחבה המתקדמת ביותר והמומלצת (לפחות על ידי) לעבודה מול בסיסי נתונים, כמובן עובדת באופן מונחה עצמים ותומכת ב-Prepared Statements (לא מכירים? אל דאגה, תכירו בהמשך המדריך).
PDO נחשבת להרחבה די מאובטחת, ותומכת במספר בסיסי נתונים חוץ מ-MySQL כגון: SQLite, Oracle, ODBC, 4D ועוד.

בניגוד לדעה הרווחת, PDO לא באה להחליף את MySQLi, יש לה יתרונות רבים על MySQLi אבל היא עדיין נתמכת לגמרי.
מצד שני, אני כן ממליץ לעבור לעבוד עם הרחבת PDO מכיוון שהיא נחשבת למאובטחת יותר והיא תומכת בבסיסי נתונים נוספים חוץ מ-MySQL. אני מאמין כי רובכם עובדים עם מסד נתונים מסוג MySQL אך כל אחד מאיתנו עלול להיתקל בסיטואציה שבה ייאלץ לעבוד מול בסיס נתונים שהוא לא MySQL, עבודה עם הרחבת PDO תהפוך את ההתאקלמות לקלה יותר.

*מדריך PDO זה מיועד למי שעבד בעבר מול מסד נתונים ומכיר את התחביר הבסיסי של תכנות מונחה עצמים (OOP).

טוב, שנתחיל?

התחברות לבסיס הנתונים

$dbHost = "localhost";
$dbUser = "root";
$dbPass = "";
$dbName = "shoesStoreDB";

try {
	$dbh= new PDO("mysql:host={$dbHost};dbname={$dbName}",$dbUser,$dbPass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
}
catch(PDOException $e) {
	echo "Error! ".$e->getMessage();
}

בשורות 1-4 קבענו את המשתנים וביצענו השמה לפרטי מסד הנתונים שלנו.
כאשר מבצעים התחברות למסד נתונים אני ממליץ באופן נחרץ(!) להשתמש ב-try catch מהסיבה הפשוטה שבמידה וההתחברות נכשלה, "נתפוס" את ה-Exception.
בתוך ה-try ביצענו את ניסיון ההתחברות על ידי הצבת המשתנים במקומם.
חשוב מאוד: בשורה 7 הגדרנו שההתחברות למסד הנתונים תהיה בקידוד UTF-8, חשוב מאוד כאשר עובדים עם מסד נתונים בעברית, הרי לא תרצו שהנתונים יכנסו בג'יבריש 🙂

במידה וההתחברות נכשלה, בחלק השני (ה-catch), "תפסנו" את ה-Exception והצגנו אותו על ידי echo.
הערה: אני ממליץ שלא לפלוט שגיאות בפרודקשן, אף אחד לא אמור לדעת מה קורה לכם באתר, במיוחד גורם עם כוונות זדוניות.

לא קיבלתם Error? מעולה! קדימה, ממשיכים.

לפני שנתחיל בדוגמאות והסברים על שאילתות נפוצות כמו SELECT, INSERT, UPDATE ו-DELETE, אני רוצה להסביר לכם את עיקרון הפעולה של הרחבת PDO.
התהליך כאן הוא שונה ממה שהכרתם עד כה ב-MySQL/MySQLi ובדרך כלל הוא מורכב מ-4 שלבים:

1. כתיבת השאילתא והכנתה (במידת הצורך גם שימוש במחזיקי מקום)
2. קשירת הפרמטרים.
3. הזנת ערכי הפרמטרים.
4. הוצאת השאילתא אל הפועל.

הערה: שלבים 2-3 מתבצעים רק בשאילתות שיש הזנת פרמטרים אל השאילתא כגון INSERT, UPDATE ושימוש ב-WHERE.

אופן העבודה של שאילתא מסוג SELECT – שליפת נתונים ממסד הנתונים

נתחיל בדוגמא הפשוטה ביותר, ללא שלבים 2-3:

//Step 1
$stmt  = $dbh->prepare("SELECT * FROM shoes");

// Step 4
$stmt->execute();

// printing
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}

בשורה מספר 1 כתבנו את השאילתא והכנו אותה על ידי עטיפתה ב-prepare.
בדוגמא זו לא עשינו שימוש ב-WHERE ולכן אנו "מדלגים" על שלבים 2-3.
בשלב האחרון – ההדפסה, עברנו על כל התוצאות באמצעות לולאת while והדפסנו כל את כל השורות.
יכלנו להימנע משימוש בלולאה על ידי שימוש ב-fetchAll:

$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($row );

במקרה זה בחרנו שהנתונים יחזרו כמערך אסוציאטיבי, אם היינו רוצים שהנתונים יחזרו כאובייקט היינו משתמשים ב-FETCH_OBJ.

נתקדם לדוגמא טיפה מורכבת יותר שכוללת שימוש ב-WHERE:

//Step 1
$stmt  = $dbh->prepare("SELECT * FROM shoes WHERE color = :color");

// Step 2
$stmt->bindParam(':color', $color);

// Step 3
$color= "black"

// Step 4
$stmt->execute();

// printing
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    print_r($row);
}

השימוש במחזיקי מקום תורם לאבטחת העבודה מול מסד הנתונים מכיוון שבשונה משאילתא של MySQL/MySQLi, כאן אנו מזינים את הערכים רק בשלב האחרון, מיד לפני הוצאת השאילתא אל הפועל (execute).
הזנת הערכים מתבצעת ב-2 תהליכים:
1. "קשירת" מחזיקי המקום עם המשתנים אשר יכילו את ערכם באמצעות bindParam.
2. הזנת הערכים של המשתנים (שלב מספר 3 בדוגמא הנ"ל).

אופן העבודה של שאילתא מסוג INSERT – הכנסת נתונים אל מסד הנתונים

// Step 1
$stmt  = $dbh->prepare("INSERT INTO shoes (color, size) value (:color, :size)");

// Step 2
$stmt->bindParam(':color', $color);
$stmt->bindParam(':size', $size);

// Insert #1
// Step 3
$color= "white";
$size= 42;
// Step 4
$stmt->execute();

// Insert #2
// Step 3
$color= "black";
$size= 45;
// Step 4
$stmt->execute();

בדוגמא הנ"ל הכנסנו שני פריטים, אחד אחרי השני.

אופן העבודה של שאילתא מסוג UPDATE – עדכון נתונים במסד הנתונים

מאוד דומה ל-INSERT:

// Step 1
$stmt  = $dbh->prepare("UPDATE shoes SET size = :size WHERE id = :id");

// Step 2
$stmt->bindParam(':size', $size);
$stmt->bindParam(':id', $id);

// Step 3
$size= 46;
$id= 1;

// Step 4
$stmt->execute();

אופן העבודה של שאילתא מסוג DELETE – מחיקת נתונים ממסד הנתונים

שוב, כמעט זהה:

// Step 1
$stmt  = $dbh->prepare("DELETE FROM shoes WHERE id = :id");

// Step 2
$stmt->bindParam(':id', $id);

// Step 3
$id= 5;

// Step 4
$stmt->execute();

טיפים ודברים שכדאי לדעת על הרחבת PDO

שימוש במחזיקי מקום ללא שם

PDO תומכת במחזיקי מקום בעלי שם (כדוגמת :color) ובמחזיקי מקום ללא שם – שימוש בסימן שאלה (?).
כך נבצע שאילתת SELECT באמצעות מחזירי מקום ללא שם:

//Step 1
$stmt  = $dbh->prepare("SELECT * FROM shoes WHERE color = ?");

// Step 2
$stmt->bindValue(1, "brown");

// Step 4
$stmt->execute();

// printing
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    print_r($row);
}

השינויים העיקריים הם שבשלב מספר 1 במקום לרשום :color השתמשנו בסימן שאלה ושלב מספר 2 מכיל בתוכו גם את שלב 3.
יש לשים לב כי לא השתמשנו ב-bindParam אלא ב-bindValue, משמעות הדבר היא שהקשירה היא עם הערך ולא עם פרמטר מחזיק מקום.
מה מסמל המספר 1? שאלה טובה – המשמעות היא שזהו מחזיק המקום מספר 1. מחזיק המקום הבא היה מקבל את המספר 2 וכ'ו.

כתיבת שאילתא באופן מקוצר

על מנת לכתוב קוד קצר ויעיל יותר, אני ממליץ לבצע את שלבים 2-4 בשורה אחת:

$stmt  = $dbh->prepare("SELECT * FROM shoes WHERE size = ?");
$stmt->execute(array(1 => '40'));

בשורה מספר 2 גם הזנו את הערכים שלנו וגם הוצאנו את השאילתא על הפועל.

קבלת ה-id האחרון שהוכנס לאחר שאילתת INSERT

אם נרצה לקבל את ה-id שהרגע יצרנו לאחר שאילתת INSERT, נוכל לקבל את ה-ID בפשטות על ידי השימוש ב-lastInsertId, דוגמא:

$id = $dbh->lastInsertId();

סיכום

הרחבת PDO היא ההרחבה המתקדמת ביותר כיום ותמיכתה בסוגים שונים של מסדי נתונים הוא יתרון גדול מאוד.
אני ממליץ ליישם את מדריך זה ולהתחיל לעבוד עם הרחבה זו כדרך קבע.
בהצלחה!

נהנת ממאמר זה? הירשם לרשימת התפוצה וקבל עדכונים על מאמרים חדשים!


כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *