2020 年 5 月 12 日,星期二
作者:Sandy Galloway

使用 Editor 的函式庫進行伺服器端處理

隨著 SearchPanes 1.1 的發布並支援伺服器端處理,我們認為值得撰寫一篇部落格文章,詳細介紹如何使用 Editor 函式庫進行伺服器端處理,以取代示範伺服器端處理腳本。這些函式庫不僅是開源的,它們還支援示範腳本未涵蓋的各種功能。

這篇部落格文章將介紹如何在伺服器端使用 Editor 函式庫,而不在客戶端使用 Editor,並示範它們如何與 SearchPanes 運作。必須再次強調 - 您不需要 Editor 授權即可使用 Editor 的伺服器端函式庫!

使用 Editor 函式庫進行伺服器端處理

簡介

使用 Editor 函式庫進行伺服器端處理有多項優點。

  • 它們是開源的,可以在不使用 Editor 的客戶端部分(具有商業授權)的情況下使用
  • 它們支援聯結
  • 它們從 Editor 1.9.3 版本開始支援 SearchPanes,SearchPanes 1.1 也支援
  • 它們支援 PHP、NodeJS 和 .NET,每種都有多種不同的資料庫
  • 它們可以作為唯讀使用
  • 它還有定義完善且有文件的 API

雖然 DataTables 範例中使用的 示範伺服器端處理 PHP 腳本 非常有用且有其用途,但 Editor 函式庫的功能更為廣泛,並且專注於這些功能使我們能夠提供高品質的程式碼,我們也能夠維持高標準。因此,我們沒有計畫擴充示範伺服器端處理腳本以包含對 SearchPanes 的支援。

安裝

在客戶端設定伺服器端處理時,您必須先執行一些操作。首先,在伺服器端,您必須下載 Editor 伺服器端函式庫(.NET | NodeJS | PHP)。這些是開源且免費使用的。

每個平台都有自己的資料庫連線設定選項 - 例如,對於 PHP,您可以在 config.php 中設定資料庫連線選項。請參閱上面的連結以取得完整詳細資料。

編寫控制器

PHP

編寫控制器非常簡單。您首先包含 DataTables PHP 函式庫。

include("../lib/DataTables.php");

然後為 Editor 類別建立別名,以便稍後易於使用。首先,我們將考慮一個非常基本的初始化來掌握這個概念,因此我們只需要使用 2 個類別。

use
    DataTables\Editor,
    DataTables\Editor\Field;

接下來是初始化 Editor 類別的實例,以及我們要使用的欄位。fields() 方法可以採用您想要定義的任意多個欄位實例,也可以多次呼叫。每個 Field 實例都會取得一個參數,該參數代表要從中讀取資料的資料行名稱。

Editor::inst( $db, 'datatables_demo' )
    ->field(
        Field::inst( 'first_name' ),
        Field::inst( 'last_name' ),
        Field::inst( 'position' ),
        Field::inst( 'office' ),
        Field::inst( 'extn' ),
        Field::inst( 'start_date' ),
        Field::inst( 'salary' )
    )

重要的是停用 Editor 類別中的任何寫入功能,因為我們只在沒有 Editor 客戶端授權的情況下執行唯讀操作。這是透過加入下列方法呼叫來完成。

    ->write( false )

當 DataTables 和 Editor 向伺服器發出請求以取得或更新資料時,它們會使用 HTTP 參數傳送資料。DataTables 預設為 GET,而 POST 是 Editor 的預設值 - 在這些範例中,我們將使用 POST 資料。PHP 在其全域 $_POST(如果您使用 GET 則為 $_GET)變數中提供此資訊,該變數可以提供給 Editor 實例進行處理。

然後使用 Editor 類別的 process() 方法處理資料,並將從客戶端傳送的資料傳遞到其中。因此,我們現在必須加入以下方法呼叫。

    ->process( $_POST )

此程序的最後一步是將資料傳送回客戶端。為了簡化操作,我們將使用 Editor 類別的 json() 方法。

    ->json();

現在您的初始化應該如下所示。

Editor::inst( $db, 'datatables_demo' )
    ->field(
        Field::inst( 'first_name' ),
        Field::inst( 'last_name' ),
        Field::inst( 'position' ),
        Field::inst( 'office' ),
        Field::inst( 'extn' ),
        Field::inst( 'start_date' ),
        Field::inst( 'salary' )
    )
    ->write( false )
    ->process( $_POST )
    ->json();

將此與函式庫包含和別名結合,將為您提供一個完整的控制器。

NodeJS

NodeJS 的等效程式碼如下所示。

let editor = new Editor(db, 'datatables_demo')
    .fields(
        new Field('first_name'),
        new Field('last_name'),
        new Field('position'),
        new Field('office'),
        new Field('extn'),
        new Field('start_date'),
        new Field('salary'),
    )
    .write(false);

await editor.process(req.body);
res.json(editor.data());

.NET

.NET 的等效程式碼如下所示。

var response = new Editor(db, "users")
    .Model<StaffModel>()
    .Field(new Field("first_name"))
    .Field(new Field("last_name"))
    .Field(new Field("position"))
    .Field(new Field("office"))
    .Field(new Field("extn"))
    .Field(new Field("start_date"))
    .Field(new Field("salary"))
    .Process(Request)
    .Data()

return Json(response)

客戶端設定

編寫 DataTable 設定以使用 Editor 伺服器端函式庫傳回的資料同樣簡單。從您的基本 DataTables 初始化開始,並加入一個 ajax 屬性,該屬性使用 ajax.url 屬性指向您剛編寫的控制器。ajax.type 屬性也必須設定為 POST,這是必需的,因為伺服器正在尋找 POST 資料。

$('#example').DataTable({
    ajax: {
        url: "../php/exampleController.php",
        type: "POST"
    }
});

接下來是加入 columns 設定。columns 設定選項是物件的陣列 - 每個資料行一個。在每個這些物件中,我們只需要定義一個屬性。 columns.data 屬性必須設定為資料庫中資料行的名稱。您應該會得到類似以下內容的結果。

$('#example').DataTable({
    ajax: {
        url: "../php/clientSide.php",
        type: "POST"
    },
    columns: [
        { data: "first_name" },
        { data: "last_name" },
        { data: "position" },
        { data: "office" },
        { data: "extn" },
        { data: "start_date" },
        { data: "salary" }
    ]
});

您可能還希望使用資料呈現器來格式化用於呈現的資料(例如,數字)。

範例

將所有這些放在一起,會得到以下 DataTable。

姓名 職位 辦公室 薪資

聯結

當然,Editor 函式庫的一大好處是,您可以解鎖示範 SSP 類別中無法使用的大量額外功能。在這裡,我將介紹聯結,但還有更多選項在手冊中詳細說明。

因此,讓我們取得以下客戶端設定,並使用 Editor 函式庫執行聯結。

$('#example').DataTable({
    ajax: {
        url: "../php/leftJoinExample.php",
        type: "POST"
    },
    columns: [
        { data: "users.first_name" },
        { data: "users.last_name" },
        { data: "users.phone" },
        { data: "sites.name" }
    ]
});

因此,在這裡我們從使用者資料表和站點資料表中取得資料。

PHP

現在以與之前相同的方式建立您的控制器,但是在宣告 Field 的實例時,我們還必須指定資料所在的資料表。

Editor::inst( $db, 'users' )
    ->field( 
        Field::inst( 'users.first_name' ),
        Field::inst( 'users.last_name' ),
        Field::inst( 'users.phone' ),
        Field::inst( 'sites.name' )
    )

然後,我們將向 leftJoin() 加入單一方法呼叫以執行聯結。這應該放在 field() 方法呼叫之後和 process() 方法呼叫之前。leftJoin() 方法採用 4 個引數。

  • $table 要聯結的資料表名稱
  • $field1 要用作聯結連結的父資料表中的欄位
  • $operator 聯結條件(=< 等)
  • $field2 要用作聯結連結的子資料表中的欄位

了解了這一點,我們應該會得到如下所示的方法呼叫。

    ->leftJoin( 'sites', 'sites.id', '=', 'users.site' )

將此放在 field()process() 方法之間應該會產生以下控制器初始化。

Editor::inst( $db, 'users' )
    ->field( 
        Field::inst( 'users.first_name' ),
        Field::inst( 'users.last_name' ),
        Field::inst( 'users.phone' ),
        Field::inst( 'sites.name' )
    )
    ->leftJoin( 'sites', 'sites.id', '=', 'users.site' )
    ->process($_POST)
    ->json();

NodeJS

NodeJS 的等效程式碼是

let editor = new Editor(db, 'users')
    .fields(
        new Field('users.first_name'),
        new Field('users.last_name'),
        new Field('users.phone'),
        new Field('sites.name')
    )
    .write(false)
    .leftJoin('sites', 'sites.id', '=', 'users.site');

await editor.process(req.body);
res.json(editor.data());

.NET

.NET 的等效程式碼是

var response = new Editor(db, "users")
    .Model<StaffModel>()
    .Field(new Field("users.first_name"))
    .Field(new Field("users.last_name"))
    .Field(new Field("users.phone"))
    .Field(new Field("sites.name"))
    .Write(False)
    .LeftJoin("sites", "sites.id", "=", "users.site")
    .Process(Request)
    .Data()

return Json(response)

SearchPanes 伺服器端處理

鑑於撰寫這篇部落格文章的最初原因是 SearchPanes 支援伺服器端處理,讓我們現在深入探討一下!

客戶端

看一下這個客戶端設定

$('#example').DataTable( {
    ajax: {
        url: "../php/searchPanes.php",
        type: "POST"
    },
    columns: [
        { data: "users.first_name" },
        { data: "users.last_name" },
        { data: "users.phone" },
        { data: "sites.name" }
    ],
    columnDefs:[{
        searchPanes:{
            show: true,
        },
        targets: '_all',
    }],
    layout: {
        top1: 'searchPanes'
    },
    serverSide: true
} );

這裡發生了一些不同的事情,所以讓我們來詳細討論一下。

  • layout 選項設定為決定 SearchPanes 在頁面中的放置位置,在此範例中,直接放置在其他所有內容的上方。對於舊版的 DataTables 1.x,請使用 dom 選項,並使用字母 Q 來表示 SearchPanes 的位置。
  • ajax 選項與我們之前的使用方式一致,使用 HTTP POST 指向控制器。
  • columns 選項與之前相同,定義要用於 DataTable 中每個資料行的資料。
  • 正在使用 columnDefs 選項將 columns.searchPanes.show 設定為所有窗格的 true,這表示它們都將顯示。

伺服器端

PHP

在控制器檔案中,除了函式庫中的 EditorField 類別外,我們還想要使用 SearchPaneOptions 類別,因此我們將其加入 use 語句中

use
    DataTables\Editor,
    DataTables\Editor\Field,
    DataTables\Editor\SearchPaneOptions;

對於控制器,必須進行一些新增。請考慮以下控制器。

Editor::inst( $db, 'users' )
    ->field(
        Field::inst( 'users.first_name' )
            ->searchPaneOptions( SearchPaneOptions::inst() ),
        Field::inst( 'users.last_name' )
            ->searchPaneOptions( SearchPaneOptions::inst() ),
        Field::inst( 'users.phone' )
            ->searchPaneOptions( SearchPaneOptions::inst()
                ->table( 'users')
                ->value( 'phone' )
            ),
        Field::inst( 'sites.name' )
            ->searchPaneOptions( SearchPaneOptions::inst()
                ->value( 'users.site')
                ->label( 'sites.name' )
                ->leftJoin( 'sites', 'sites.id', '=', 'users.site' )
            )
    )
    ->write(false)
    ->leftJoin( 'sites', 'sites.id', '=', 'users.site' )
    ->process($_POST)
    ->json();

在這裡,在每個欄位實例上,我們都初始化一個 SearchPaneOptions 類別,以指示函式庫確定每個資料行搜尋窗格應顯示哪些選項。

然後,可以透過多種不同的方式呼叫它,以確定應在客戶端窗格中顯示哪些選項。最簡單的方法是建立一個沒有選項的新 SearchPaneOptions 實例,軟體將自動確定要使用欄位的名稱和資料表從資料庫讀取哪些資料。每個函式庫都記錄了完整的選項集

如果您使用的是自己的伺服器端處理腳本,而不是 Editor 函式庫。 SearchPanes 文件詳細說明了傳送到伺服器的參數以及它期望傳回的內容。

NodeJS

如果您在 NodeJS 世界中工作,則等效程式碼是

let editor = new Editor(db, 'users')
    .fields(
        new Field('users.first_name')
            .searchPaneOptions(new SearchPaneOptions()),
        new Field('users.last_name')
            .validator(Validate.notEmpty())
            .searchPaneOptions(new SearchPaneOptions()),
        new Field('users.phone')
            .searchPaneOptions(
                new SearchPaneOptions()
                    .table('users')
                    .value('phone')
            ),
        new Field('sites.name')
            .searchPaneOptions(
                new SearchPaneOptions()
                    .value('users.site')
                    .label('sites.name')
                    .leftJoin('sites', 'sites.id', '=', 'users.site')
            )
    )
    .leftJoin('sites', 'sites.id', '=', 'users.site');

await editor.process(req.body);
res.json(editor.data());

.NET

對於 .NET

var response = new Editor(db, "users")
    .Model<UploadManyModel>()
    .Field(new Field("users.first_name")
        .SearchPaneOptions( new SearchPaneOptions() )
    )
    .Field(new Field("users.last_name")
        .SearchPaneOptions( new SearchPaneOptions() )
    )
    .Field(new Field("users.phone")
        .SearchPaneOptions(new SearchPaneOptions()
            .Table("users")
            .Value("phone")
        )
    )
    .Field(new Field("sites.name")
        .SearchPaneOptions(new SearchPaneOptions()
            .Label("sites.name")
            .Value("users.site")
            .LeftJoin("sites", "sites.id", "=", "users.site")
        )
    )
    .LeftJoin("sites", "sites.id", "=", "users.site")
    .Process(Request)
    .Data();

return Json(response);

即時範例

將以上所有內容整合起來,結果如下表所示

名字 姓氏 電話 網站

意見回饋

一如既往,我們很希望了解您如何使用 DataTables、Editor 和 SearchPanes。請在論壇中留言,告訴我們您使用我們軟體的狀況,或者您是否遇到任何問題,或是對未來的功能增強有任何想法。

祝您使用愉快!