MySQL ו-PHP

הסבר מקיף על שימוש בשאילתות MySQL ב-PHP פרוצדורלי

במאמר הקודם סיימנו ללמוד על Stored Procedure ובעצם השלמנו את נדבך הידע הבסיסי ב-MySQL. קצת לפני שנתקדם הלאה, אנו נדון באינטגרציה בין PHP ל-MySQL.

למרות שכל תוכנה שהיא יכולה להתחבר ל-MySQL. עבור רבים השפה הטבעית ביותר לחיבור עם MySQL היא PHP ולו רק מהסיבה הפשוטה ש-PHP נכללת בחבילת ה-LAMP ובדומה ל-MySQL (ול-Apache) קל להתקין אותה על לינוקס. גם רוב האפליקציות ואתרי האינטרנט כתובים ב-PHP ובנוסף לכל ההרחבות של MySQL ל-PHP הן מאד מאד נוחות ואינטואיטיביות.

ההנחה הסמויה היא שמי שיודע Ruby או PERL לא צריך את המדריך הזה. לפיכך נתרכז רק באינטגרציה בין PHP ל-MySQL.

בניית סביבת הפיתוח שלנו – PHP

בהנחה שה-WAMP שעליו הסברנו במאמר הראשון בסדרה הותקן, צריך ליצור DataBase ששמו הוא internet_database ובו יש טבלה שגם אותה אתם מכירים שנקראת my_costumer. הטבלה נראית כך:


+-------------+---------------+--------------+--------------+
| costumer_id | costumer_name | costumer_age | costumer_sex |
+-------------+---------------+--------------+--------------+
|           1 | moshiku       |           21 | male         |
|           2 | Haim          |           22 | male         |
|           3 | Yaakov        |           19 | male         |
|           4 | Dan           |           19 | male         |
|           5 | Dana          |           42 | female       |
|           6 | Rina          |           24 | female       |
|           7 | Omri          |            9 | male         |
+-------------+---------------+--------------+--------------+

ייבוא של מסד נתונים לסביבת העבודה שלנו הוא קל למדי (בסביבת פיתוח של לינוקס זה אפילו קל יותר). עלינו להשתמש ב-phpMyAdmin שהוא ממשק גרפי נוח למדי לניהול מסדי הנתונים. נלחץ עם הכפתור השמאלי של העכבר על סמל ה-WAMP שלנו ונבחר ב-phpMyAdmin. ייפתח לנו אתר (שיושב על המחשב שלנו כמובן) שבו יש את הממשק הגרפי.

כל מה שנותר לעשות זה:

  1. להוריד את קובץ ה-SQL של הטבלה שהכנתי.
  2. ליצור מסד נתונים חדש ששמו הוא internet_database
  3. לייבא את הקובץ
  4. לוודא שהכל תקין.

והנה מדריך וידאו קצר שיראה לכם איך לעשות זאת. כדאי להכיר קצת את ה-phpMyAdmin כי בשרתים שיתופיים משתמשים בו בדרך כלל על מנת לנהל את מסדי הנתונים.

אחרי שיש לנו טבלה שאנו יכולים לעבוד איתה, אנו צריכים ליצור קובץ php. ניתן ליצור קובץ כזה עם כל עורך טקסט שהוא. אך אני מאד ממליץ על Notepad++. הוא קל, זריז, מהיר ואידיאלי לעבודות קטנות.

נאתר את תיקית ה-WWW שנמצאת בתיקית ההתקנה של ה-WAMP. נפתח בה תיקיה (לדוגמא: site) וניצור קובץ ששמו הוא index.php.
בקובץ נכתוב את הטקסט הבא:


<?php
phpinfo();

נלחץ עם הכפתור השמאלי של העכבר על סמל ה-WAMP ב-System Tray ונבחר ב-Localhost. אחרי כן יש להוסיף את שם התיקיה שיצרנו. אם הכל תקין אנו נראה דף שבו יש את פרטי השרת. עכשיו אפשר להתחיל לעבוד. את כל הקוד של ה-PHP שאני אפרט במאמר הזה ובמאמר הבא אנו נציב ב-index.php.

הדבר האחרון שאנו צריכים לעשות זה ליצור שם משתמש וסיסמה. ב-phpMyAdmin נכנס ל-Privileges -> Add a new User. בשדה ה-User name נכניס שם משתמש (לצורך העניין internet_user) וסיסמה (לצורך העניין 123456) חובה ללחוץ על Check All כדי לתת למשתמש את כל ההרשאות ולשמור אותו.

דרכים שונות להתחבר ל-MySQL

ישנן שתי דרכים להתחבר ל-MySQL אנו נחבר באחת מהן לפי פרדיגמת התכנות שלנו. כאשר אנו מתכנתים פרוצדורלי, אנו נשתמש בדרך פרוצדורלית (הרחבת MySQL) שתוסבר במאמר הזה. אם אנו מתכנתים בתכנות מונחה עצמים (גרסת PHP 5 ומעלה) אנו משתמשים באובייקט מסודר (הרחבת MySQLi) שתוסבר במאמר הבא. אם לא הבנתם מה אני רוצה מהחיים שלכם, קראו את המאמר הזה בלבד ודלגו על זה שאחריו.

PHP פרוצדורלי

כאשר אנו יוצרים שאילתת MySQL, אנו צריכים לעבור ארבעה שלבים – חיבור ראשוני לשרת ה-MySQL עצמו, בחירת מסד הנתונים שלנו (מקביל לפקודת USE) שלמדנו קודם לכן, העברת השאילתה עצמה ולבסוף חילוץ התשובה מה-resource שניתן לנו על ידי ה-MySQL.

נשמע קצת מסובך? זה ממש לא. ראשית, החיבור ל-MySQL הוא השלב שבו אנו מעבירים את שם המשתמש, הסיסמה והמיקום של שרת ה-MySQL (בדרך כלל localhost). את החיבור אנו עושים באמצעות פקודת mysql_connect :


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

אם כתבנו את שם המשתמש כשורה ואת הסיסמה כשורה, לא צריכה להיות כל בעיה אם אנו מריצים את הקוד הבא ב-WAMP שלנו. שימו לב שהפקודה mysql_connect מחזירה רפרנס לקישור (שבו נשתמש בהמשך) או FALSE במידה והיא לא מצליחה לקיים את הקישור.

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

אחרי שהתחברנו כשורה, עלינו לבצע USE למסד הנתונים שאנו רוצים להשתמש בו. במקרה הזה internet_database. אם היינו ב-Console, היינו פשוט מקישים את הפקודה:


USE internet_database;

אבל אנחנו בתוך סקריפט של php. ובתוך הסקריפט הזה אנו נשתמש בפקודת mysql_select_db. הפקודה הזו מבצעת את ה-USE עבורנו. אפשר (אבל לא חובה) להעביר לה את הרפרנס לחיבור שלנו. וחובה להעביר לה את שם מסד הנתונים. כך זה נראה:


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "
Selected successfully"; 

כעת נותר לנו לבצע את השאילתא. לצורך הדוגמא נשתמש בשאילתא פשוטה:


SELECT * FROM my_costumer;

על מנת לבצע שאילתות, אנו משתמשים בפקודת mysql_query. הנה הדוגמא שלנו:


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "
Selected successfully"; 

$result = mysql_query('SELECT * FROM my_costumer');

mysql_query מחזירה לנו resource במידה ומדובר בשאילתת SELECT, DESCRIBE או כל שאילתא אחרת שמחזירה תוצאות. במידה ומדובר בשאילתא ביצועית כמו למשל INSERT, UPDATE, DELETE, DROP אז אנו מקבלים true במקרה של הצלחה ו-false במקרה של כשלון.

resource הוא לא מערך או אובייקט. מה-resource הזה אנו צריכים לחלץ את מה שאנו צריכים – שורה אחר שורה.

באופן עקרוני, אנו יכולים לחלץ שורה בכל פעם מה-resource בכמה אופנים – כמערך רגיל, מערך אסוציאטיבי או כאובייקט. על מנת לקבל את השורה כמערך רגיל אנו נשתמש בפונקצית mysql_fetch_row. אם אנו רוצים לקבל את השורה כמערך אסוציאטיבי, אנו נשתמש בפונקצית mysql_fetch_assoc. ואם אנו רוצים לקבל את השורה כאובייקט, אנו נשתמש בפונקצית mysql_fetch_object.

אם נריץ את הסקריפט הבא למשל:


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "
Selected successfully
"; 

$result = mysql_query('SELECT * FROM my_costumer');

$my_Array = mysql_fetch_assoc($result);

print_r($my_Array);

זו התוצאה שנקבל:


Connected successfully
Selected successfully
Array ( [costumer_id] => 1 [costumer_name] => moshiku [costumer_age] => 21 [costumer_sex] => male ) 

אבל כפי שאנו יודעים, כאשר אנו מריצים "SELECT *" אנו מקבלים יותר משורה אחת. לאן נעלם שאר המידע? הוא לא נעלם, הפקודה mysql_fetch_assoc רצה בכל פעם על שורה אחת. אם נריץ אותה בסקריפט פעמיים:


<?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "<br />Selected successfully<br />"; 

$result = mysql_query('SELECT * FROM my_costumer');

$my_Array = mysql_fetch_assoc($result);

print_r($my_Array);

$my_Array = mysql_fetch_assoc($result);

print_r($my_Array);

אנו נקבל את התוצאה הבאה (אם עושים view source):


Array
(
    [costumer_id] => 1
    [costumer_name] => moshiku
    [costumer_age] => 21
    [costumer_sex] => male
)
Array
(
    [costumer_id] => 2
    [costumer_name] => Haim
    [costumer_age] => 22
    [costumer_sex] => male
)

כלומר, יש משתנה שנקרא internal result pointer שמקושר לכל resource ו-resource שבכל פעם שאנו מריצים פקודת fetch (ולא משנה מה היא מחזירה) אותו pointer זז קדימה. באמצעות פונקצית mysql_data_seek אנו יכולים לשלוט על מיקום אותו פוינטר. כך למשל בסקריפט הבא אני אבקש להתחיל משורה 3:


<?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "<br />Selected successfully<br />"; 

$result = mysql_query('SELECT * FROM my_costumer');

mysql_data_seek ($result , 3);

$my_Array = mysql_fetch_assoc($result);

print_r($my_Array);

זו התוצאה שתצא לי:


Connected successfully
Selected successfully
Array ( [costumer_id] => 4 [costumer_name] => Dan [costumer_age] => 19 [costumer_sex] => male ) 

ניתן לקבל באמצעות פקודת mysql_num_rows את מספר השורות שיש ב-resource שלנו ואם אנו רוצים לקבל את כל התשובות אז אפשר להריץ לולאה. אך ניתן גם להשתמש ב-While:


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "
Selected successfully
"; 

$result = mysql_query('SELECT * FROM my_costumer');

while ($row = mysql_fetch_assoc($result)) {
	print_r($row);
}

ועוד הערה לפני סיום: רוב השאילתות שלנו יהיו עם כמה (וכמה) משתנים. מקובל מאד להשתמש בפונקצית sprintf על מנת להכניס אותם אל השאילתא. לדוגמא:


< ?php
$link = mysql_connect("localhost", "internet_user", "123456");
if (!$link) {
    die("Could not connect: " . mysql_error());
}
echo "Connected successfully";

$db_selected = mysql_select_db("internet_database", $link);
if (!$db_selected) {
    die ("Can't use internet_database : " . mysql_error());
}
echo "
Selected successfully
"; 

$result = mysql_query(sprintf("SELECT * FROM my_costumer where costumer_name='%s' LIMIT 1", "Omri"));

print_r(mysql_fetch_assoc($result));

כדאי לשים לב שברגע ששמתי LIMIT 1 אני לא צריך להשתמש ב-while כי אני יודע שתהיה אך ורק שורת תוצאה אחת בלבד לשאילתא שלי.

והתוצאה כמובן תהיה:


Connected successfully
Selected successfully
Array ( [costumer_id] => 7 [costumer_name] => Omri [costumer_age] => 9 [costumer_sex] => male ) 

⚠️המדריכים כאן הם טעימה בלבד! יש ספר מקיף המלמד MySQL מרמת בסיס ועד רמה מתקדמת. הספר הדיגיטלי, שרלוונטי גם לכל מסדי הנתונים שעובדים עם SQL – זמין כאן כחלק מהפרויקט "ללמוד ג'אווהסקריפט בעברית" – זו הדרך הטובה ביותר ללמוד באופן מקיף MySQL.

עד כאן בנוגע לשילוב הבסיסי בין PHP פרוצדורלי ל-MySQL. במאמר הבא אנו נדבר על הרחבת MySQli – שילוב בסיסי בין PHP מונחה עצמים ל-MySQL.

פוסטים נוספים שכדאי לקרוא

DALL·E 2024-09-06 12.34.24 - A visually engaging post about Python and cryptographic problems. The image should feature a dark-themed background with a glowing, futuristic Python
פתרונות ומאמרים על פיתוח אינטרנט

בעיות במימוש של פונקציות קריפטוגרפיות בפייתון

היום (16 לספטמבר) ממש, אני מעביר הרצאה ב-PyconIL 2024 על בעיות קריפטוגרפיות באפליקציות פייתון. לצערי אי אפשר להכניס את כל הבעיות הקריפטוגרפיות להרצאה אחת או

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

תמונה של הבית הלבן עם מחשוב ענן וטקסט: FEDRAMP
פתרונות ומאמרים על פיתוח אינטרנט

FedRAMP & FIPS מבוא למתחילים

פרק מיוחד, לצד הקלטה של פרק של עושים תוכנה על אחת התקינות החשובות ביותר עבור חברות שסביר להניח שלא הכרתם

גלילה לראש העמוד