שאילתות

קריאת נתונים עם DB::query, DB::get_all, DB::get_row ו-DB::get_val: חתימות מדויקות, תנאי where, מיון, limit, ו-DB::escape לקלט חיצוני, כולל המלכודות של ה-builder.

⏱ 5 דק' קריאה 959 מילים ערוך דף זה ב-GitHub

בדף הזה כל דרכי הקריאה מהמסד: ה-builder DB::query() שמחזיר אובייקט שאילתה, הקיצורים DB::get_val() ו-DB::get_all(), ו-SQL גולמי דרך DB::sql(). תראו מה כל אחד מקבל ומחזיר, איך כותבים תנאים, ואילו חלקים בשאילתה אינם עוברים escaping.

בעמוד הזה system/ הוא תיקיית הליבה הפרוסה (= api/core בריפו) ו-{admin} הוא CONFIG::$admin_url של האתר.

DB::query#

DB::query($table = "", $whereCond = [], $orderBy = "", $lang = "", $limit = null): DB_QUERY_OBJECT
פרמטרמשמעות
$tableשם הטבלה בלי CRM_
$whereCondמערך עמודה => ערך, תנאי שוויון בלבד (ראו למטה)
$orderByמחרוזת SQL גולמית, למשל "ord ASC, id DESC"
$langמזהה שפה (CRM_platforms.id) לטבלאות _content. ריק = השפה הנוכחית (CONFIG::$lang)
$limitמחרוזת "offset,count", למשל "0,20" (ה-offset קודם)

האובייקט שחוזר לא מריץ כלום עד שקוראים לאחת ממתודות הקריאה שלו:

מתודהמה היא עושה
get_row()מביאה את השורה הבאה ומחזירה אותה (וגם שומרת ב-$q->rows). false כשנגמרו
get_all($key = false, $value = false)מחזירה את כל השורות. עם $key המערך ממופתח לפי העמודה הזאת. עם $value נוסף, הערכים הם העמודה הזאת בלבד
num_rows()מספר השורות. מריצה את השאילתה מחדש
affected_rows()מספר השורות שהושפעו
free_results()משחררת את ה-statement
// שורה אחת
$page = DB::query("pages", ["id" => 12])->get_row();

// לולאה
$q = DB::query("pages", ["noDelete" => 0], "ord ASC", "", "0,20");
while ($q->get_row()) {
    echo $q->rows["id"];
}

// הכול, ממופתח לפי id
$byId = DB::query("pages", [], "ord")->get_all("id");

תנאי where#

מערך ה-where הוא שוויון בלבד, והכללים הם:

  • המפתח id מקבל אוטומטית את הקידומת tConf. (הטבלה הראשית). מפתחות אחרים נכנסים כמו שהם.
  • הערך null הופך ל-IS NULL.
  • ערך מספרי (is_numeric) נכנס בלי גרשיים.
  • ערך שמתחיל בתו backtick נכנס גולמי, כהפניה לעמודה.
  • כל ערך אחר הופך ל-= '<escaped>'.

לכל תנאי אחר (>, LIKE, IN, OR) משתמשים במאפיין filter, מחרוזת SQL גולמית שהליבה עוטפת ב-AND (...):

$q = DB::query("pages");
$q->filter = "ord > 5 AND title LIKE '%" . DB::escape($search) . "%'";
$q->fields = "id, title";
$q->order_by = "id DESC";
$q->limit = "0,50";
while ($q->get_row()) { /* ... */ }

מאפיינים נוספים באובייקט: fields (ברירת מחדל "*"), group_by, lang, ו-BuildQuery() שמחזירה את מחרוזת ה-SQL שתורץ.

מספר טלפון שנראה מספרי
is_numeric("0501234567") הוא true, ולכן הערך נכנס כמספר בלי גרשיים ו-MySQL משווה אותו כמספר: האפס המוביל אובד. כדי להשוות מחרוזת ספרות כמחרוזת, השתמשו ב-filter עם גרשיים: $q->filter = "phone = '" . DB::escape($phone) . "'".

מה לא עובר escaping ב-builder
fields, filter, order_by, group_by, limit, שמות המפתחות של מערך ה-where, וערכים שמתחילים ב-backtick נכנסים ל-SQL כפי שהם. קלט של משתמש שמגיע לאחד מהם (למשל ?sort= שהופך ל-order_by) הוא SQL injection. אמתו מול רשימה לבנה, או העבירו DB::escape() ושימו בגרשיים בעצמכם. ראו SQL injection.

DB::get_val#

DB::get_val($tblName, $filter = "", $rowName = "")

קיצור לשורה אחת או לערך אחד. $filter יכול להיות:

סוגמשמעות
מערךתנאי שוויון מחוברים ב-AND
מספרid
מחרוזת לא ריקהSQL גולמי שמשמש כתנאי
ריקמחזירה false

אם נתתם $rowName, מוחזר ערך העמודה הזאת, אחרת כל השורה. אין שורה מתאימה: false. השאילתה משתמשת ב-limit "0,1".

$version = DB::get_val("params", ["sysName" => "attaches_version"], "value");
$row     = DB::get_val("pages", 12);
מחרוזת כ-filter היא SQL
DB::get_val("pages", $_GET["x"]) עם מחרוזת מהמשתמש מזריק אותה ישירות ל-SQL. העבירו מערך (["id" => ...]) או מספר מאומת.

DB::sql, DB::get_all, DB::get_row#

DB::sql($sql)                                   // PDOStatement
DB::get_all($res, $key = NULL, $val = NULL)     // array
DB::get_row($res, $return_key = false)          // array | false | ערך

כאן שמות הטבלאות עם CRM_. get_all ו-get_row מקבלות או מחרוזת SQL או statement ש-DB::sql החזירה.

$platforms = DB::get_all("SELECT * FROM CRM_platforms", "domain");   // ממופתח לפי domain
$names     = DB::get_all("SELECT id, name FROM CRM_platforms", "id", "name");  // id => name
$one       = DB::get_row("SELECT * FROM CRM_pages WHERE id = " . (int)$id);
$title     = DB::get_row("SELECT title FROM CRM_pages_content WHERE parentId = 12 LIMIT 1", "title");
לולאה אינסופית עם get_row ומחרוזת

כש-$res הוא מחרוזת, get_row מריצה את ה-SQL בכל קריאה. לכן while ($r = DB::get_row("SELECT ...")) {} לא נגמר לעולם. לולאה כותבים כך:

$res = DB::sql("SELECT id FROM CRM_pages");
while ($r = DB::get_row($res)) { /* ... */ }

DB::escape#

DB::escape($str)

משתמשת ב-PDO::quote ומקלפת את הגרשיים החיצוניים, כך שהיא לא מוסיפה גרשיים. את הגרשיים מוסיפים אתם:

$sql = "SELECT * FROM CRM_pages WHERE title = '" . DB::escape($title) . "'";

לערכים מספריים עדיף (int) או (float). מחרוזת ריקה ו-NULL מוחזרות ללא שינוי.

שגיאות ב-SQL

שאילתה שנכשלת זורקת Exception עם ההודעה "<שגיאת הדרייבר> | <ה-SQL>", ולכן אפשר להיעזר בה בדיבוג. ראו דיבוג SQL.

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.