panel_table: טבלאות בפאנל

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

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

panel_table היא המחלקה שמציגה כמעט כל רשימה בפאנל הניהול: אתם נותנים לה שאילתה והגדרת עמודות, והיא מחזירה טבלה מלאה (אפליקציית Vue) עם מיון, דפדוף, סינון לפי עמודה, חיפוש חופשי, פעולות ויצוא. בדף הזה מוסבר איך מגדירים עמודות, סינון, פעולות וייצוא. את רשימת כל המאפיינים והמתודות תמצאו ב-רפרנס panel_table.

{admin} הוא CONFIG::$admin_url, ו-system/ הוא תיקיית הליבה (api/core בריפו). המחלקה נמצאת ב-system/libraries/panel_table.php ונטענת אוטומטית בבקשת אדמין.

דוגמה מינימלית#

public function index()
{
    $tbl = new panel_table("redirections_list");   // מזהה ייחודי וקבוע
    $tbl->title = "הפניות";
    $tbl->query = DB::query("redirections");
    $tbl->order_manager = false;
    $tbl->btn_add_url = CONFIG::$admin_url . "/redirections/insert";
    $tbl->btn_add_url_target = "popup";             // "inner" (ברירת מחדל) או "popup"
    $tbl->delete = function ($id) {
        DB::delete("redirections", ["id" => $id]);
        cache_engine::remove("redirections");
    };
    $tbl->titles = [
        ["title" => "ID",      "field" => "id"],
        ["title" => "מכתובת", "field" => "url_from"],
        ["title" => "לכתובת", "field" => "url_to"],
    ];
    $tbl->actions = function ($row) {
        return [[
            "title"  => "עריכה",
            "link"   => "EDIT",
            "target" => "popup",
            "icon"   => '<i class="fas fa-edit"></i>',
        ]];
    };
    return $tbl->get_html();
}
שימו לב

הפרמטר של הבנאי (new panel_table($tblID)) הוא המזהה שהדפדפן שולח בכל בקשה. אם לא תעבירו אותו, הוא נקבע לפי מספר סידורי בבקשה, ולכן ישתנה כשנוספת טבלה נוספת בעמוד. תנו תמיד מזהה ייחודי וקבוע.

שימו לב
order_manager מופעל כברירת מחדל: הרשימה נמיינת לפי עמודת ord, ואם העמודה חסרה בטבלה, המחלקה מריצה ALTER TABLE ... ADD ord INT NOT NULL בזמן ריצה. כבו אותו ($tbl->order_manager = false) בכל רשימה שאין בה גרירה לסידור, וגם כש-query היא מחרוזת ולא אובייקט DB::query.

מקורות הנתונים#

מאפייןמשמעות
queryDB::query(...) (אובייקט DB_QUERY_OBJECT) או מחרוזת SQL גולמית. המחלקה עוטפת אותה כתת-שאילתה SELECT * FROM (...) AS tbl ומסננת עליה
rowsמערך שורות ידני שנוסף לראש התוצאות
rows_funcfunction($qu, $results) שמחזירה שורות נוספות

כל שורה חייבת לכלול עמודת id. אתם מגדירים את גודל העמוד ב-limit (ברירת מחדל 50).

עמודות: titles#

titles הוא מערך של עמודות. כל עמודה היא מערך עם המפתחות:

מפתחמשמעות
titleכותרת העמודה
fieldשם השדה בשאילתה
typeid, text (ברירת מחדל), number, date, datetime, select, multiselect, list, image
funcfunction($row, $title): מחזירה את הערך להצגה. הפלט מוצג כ-HTML
linkfunction($row, $title): מחזירה כתובת, והתא הופך לקישור
editabletrue, או function($row, $title) שמחזירה bool: עריכה בתוך התא
editable_table"content" או "conf": לאיזו טבלה נשמר ערך רב-לשוני
editable_field_tableשם טבלה לעדכון ישיר של השדה
editable_field_funcfunction($row, $value, $title): שמירה מותאמת
editable_successfunction($row, $value, $title): נקראת אחרי שמירה מוצלחת
select_optionsמערך [id => טקסט] לעמודות select, multiselect ו-list, למשל DB::query("groups")->get_all("id", "name"). ללא מפתח זה הן נבנות מהערכים השונים שבטבלה
filter_funcfunction($fieldObj, $val): מחזירה תנאי SQL (בלי AND בסוף) כשמסננים לפי העמודה
permsהרשאה (למשל "export"): עמודה שהמנהל לא מורשה לה מוסרת מהתצוגה
class, styleמחלקת CSS וסגנון לתא
confirmטקסט אישור שהדפדפן מציג לפני שמירת שדה שניתן לעריכה (צד לקוח)

סוגי עמודה בעלי התנהגות מיוחדת:

  • date / datetime: מעוצבים Y-m-d / Y-m-d H:i.
  • image: ערך מספרי הוא מזהה קובץ ב-STORAGE (מומר ל-URL דרך STORAGE::get_url), ומחרוזת היא כתובת.
  • list: ערך בפורמט |1||2| (פירוק עם MISC::bgl_explode).
  • select / multiselect: ערך בודד או רשימה.
$tbl->titles = [
    ["title" => "ID", "field" => "id"],
    ["title" => "תמונה", "field" => "pic", "type" => "image"],
    [
        "title" => "כותרת",
        "field" => "title",
        "link"  => fn($row) => CONFIG::$admin_url . "/articles/insert/" . $row["id"],
    ],
    [
        "title"    => "קטגוריה",
        "field"    => "cat_id",
        "type"     => "select",
        "select_options" => [1 => "חדשות", 2 => "בלוג"],
    ],
    [
        "title" => "סטטוס",
        "field" => "published",
        "func"  => fn($row) => $row["published"] ? "מפורסם" : "טיוטה",
    ],
    ["title" => "עדכון", "field" => "updated", "type" => "datetime"],
    ["title" => "מחיר", "field" => "price", "type" => "number", "editable" => true],
];
שימו לב

הפלט של func מוצג כ-HTML, בלי escape. אם הוא מכיל ערך שמקורו בנתוני משתמש, העבירו אותו דרך htmlspecialchars. בערכים רגילים (בלי func) המחלקה מנקה תווי בקרה ותווים לא תקינים, ומסירה גם אמוג'י, ולכן אל תסתמכו על אמוג'י בתוכן תא.

סינון, חיפוש ומיון#

סינון ומיון מבוצעים בשרת על התת-שאילתה. הדפדפן שולח בכל פעולה גוף JSON עם q (חיפוש), filters (מפתח לכל שדה), ordBy ו-ordDir, pgnm (מספר עמוד).

סוג עמודהאיך מסננים
idשוויון (=)
textLIKE %x%, והתאמה מדויקת נשלחת ראשונה
date, datetimeטווח בין שני תאריכים
numberמ-עד
selectשוויון
multiselectIN (...)
listLIKE '%|id|%'
אחר= אם הערך מספר שלם, אחרת LIKE

הערך המיוחד --none-- מתאים לשדה ריק או 0. ערכי הסינון עוברים DB::escape.

חיפוש חופשי (q):

  • אם הגדרתם $tbl->searchFunc = function ($escaped_q) { ... }, היא מחזירה את תנאי ה-SQL (הקלט כבר עבר escape).
  • אחרת החיפוש הוא LIKE על כל העמודות של השורה הראשונה בתוצאה.
$tbl->searchFunc = function ($q) {
    return "(title LIKE '%$q%' OR body LIKE '%$q%')";
};

מיון ברירת מחדל נקבע ב-default_order (למשל "id DESC"). כש-order_manager פעיל המיון הוא לפי ord.

אזהרה

שם עמודת המיון והכיוון (ordBy, ordDir) שמגיעים מהדפדפן משורשרים לשאילתה ללא ולידציה בליבה הנוכחית. הם נשלחים רק על ידי מנהל מחובר, אבל אל תפעילו panel_table בפאנל שמוגדר skip_permission_check מעל נתונים רגישים.

פעולות לשורה: actions#

actions היא פונקציה שמקבלת שורה ומחזירה מערך של פעולות. כל פעולה:

מפתחמשמעות
titleטקסט הכפתור
iconHTML של אייקון (FontAwesome 5)
linkכתובת, או "EDIT" שמשמעה btn_add_url. המזהה מתווסף כ-/id, או ?id= אם בכתובת כבר יש סימן שאלה
targetpopup, _blank, או ברירת מחדל (טעינה בתוך #mainframe דרך adminMovePage)
funcfunction($row): פעולה בשרת. אם מוחזרת מחרוזת היא מוצגת למשתמש כהודעה (alertService.fire({html})); מחרוזת שמתחילה ב-<script מורצת
alertטקסט אישור לפני הרצה
permsהרשאה נדרשת (ADMIN::has_perms)
class, styleסגנון הכפתור
action_typeedit או סוג אחר, לעיצוב
loadingהצגת מחוון טעינה בזמן הרצה
$tbl->actions = function ($row) {
    return [
        ["title" => "עריכה", "link" => "EDIT", "icon" => '<i class="fas fa-edit"></i>'],
        [
            "title" => "פרסם",
            "icon"  => '<i class="fas fa-check"></i>',
            "alert" => "לפרסם את המאמר?",
            "perms" => "edit",
            "func"  => function ($row) {
                $up = DB::update("articles");
                $up->set_var("published", 1);
                $up->update((int)$row["id"]);
                return "המאמר פורסם";
            },
        ],
    ];
};

כל פעולה מקבלת טוקן (MISC::encode של הפעולה והמזהה). הדפדפן מחזיר אותו בבקשה, והשרת מריץ רק פעולות שהוגדרו בפועל, לא קוד שרירותי.

פעולת delete (המאפיין $tbl->delete = function ($id, $row) {...}) מוסיפה פעולת מחיקה קבוצתית, ורק למי שיש ADMIN::has_perms("delete"). dblclick_url מוסיף פעולת "כניסה" ומגדיר מה קורה בלחיצה כפולה על שורה.

פעולות קבוצתיות#

$tbl->group_actions זהה במבנה, אבל func היא function($row, $action) שנקראת לכל שורה מסומנת (הדפדפן שולח checkgroup עם רשימת המזהים ואת הטוקן).

$tbl->group_actions = [[
    "title" => "הסתר",
    "icon"  => '<i class="fas fa-eye-slash"></i>',
    "alert" => "להסתיר את הפריטים שנבחרו?",
    "func"  => function ($row, $action) {
        $up = DB::update("articles");
        $up->set_var("published", 0);
        $up->update((int)$row["id"]);
    },
]];
שימו לב
ignore_perms = true משמיט את בדיקות ההרשאה בעמודות ובפעולות, אך כרגע get_actions קורסת כשהוא מופעל. אל תשתמשו בו לפני שתבדקו את הרשימה בפועל.

עריכה בתוך הטבלה#

עמודה עם editable => true מציגה שדה שנשמר בלחיצה. השמירה נשלחת עם tbl_action = editable_field, והשרת:

  1. מוודא שהעמודה ניתנת לעריכה לפי הגדרת ה-titles (לא לפי מה שהדפדפן אומר);
  2. שומר דרך editable_field_table או editable_field_func, ואם אין, דרך DB::update לטבלת השאילתה (ל-content או conf לפי editable_table);
  3. קורא ל-editable_success.

ייצוא לאקסל#

כפתור הייצוא מוצג למנהל עם ADMIN::has_perms("export") ויוצר קובץ xlsx (דרך PhpSpreadsheet, עם כיוון RTL) לפי הסינון הנוכחי. limit בבקשת הייצוא קובע כמה שורות.

שימו לב

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

ממשק ה-JSON של הטבלה#

הדפדפן שולח ל-URL של הפאנל עצמו גוף JSON, והשרת מחזיר {more_data, lines, paging, order_manager, action_result}. הפרוטוקול המלא מפורט ב-ממשק JSON.

כרטיס פתיחה ותוכן נוסף#

$tbl->intro (טקסט) ו-$tbl->intro_card = true מציגים כרטיס הסבר מעל הטבלה, ו-head_html מקבל מערך אלמנטי HTML לכותרת הטבלה. additional_content היא function($tbl) שמחזירה תוכן נוסף שנשלח עם כל טעינת נתונים.

ראו גם#

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