2015 年 10 月 2 日 星期五

編輯器的伺服器端事件

這是系列文章的第二篇,描述 Editor 1.5 的新功能。之前多行編輯是討論的重點,而在這篇文章中,我將介紹已新增至 PHP 和 .NET 程式庫的伺服器端事件,這些程式庫是 Editor 套件的一部分,並示範如何使用它們來提高伺服器端軟體的彈性。

為什麼需要伺服器端事件

PHP 和 .NET Editor 伺服器端程式庫可以非常簡單地建立讀取/寫入表格,可能具有複雜的操作,例如檔案上傳和聯結表格,但仍然基於簡單的讀取/寫入操作。對於較大型的應用程式,這是一個好的開始,但通常這還不夠 - 您希望能夠根據終端使用者執行的資料來執行某些操作。

伺服器端事件的一個常見範例,我們將在下面探討,是將資料變更寫入資料庫記錄表,以提供追蹤資訊和責任歸屬。另一個範例可能是根據使用者輸入啟動外部程序,例如建置腳本。無論原因為何,事件現在在 Editor 中提供了這種能力。

如何使用

PHP 和 .NET 程式庫提供*以每一行為基礎*觸發的事件 - 這很重要,因為 Editor 1.5 具有多行編輯功能。事件會在建立、編輯或刪除行之前和之後立即觸發。之前的事件允許修改欄位和輸入資料,而之後的事件可用於提供動作已發生的通知。

Editor 程式庫會觸發以下事件

PHP 名稱 .NET 名稱 說明
preCreate PreCreate 在建立新行之前立即觸發
postCreate PostCreate 在建立新行之後立即觸發
preEdit PreEdit 在更新現有行之前立即觸發
postEdit PostEdit 在更新現有行之後立即觸發
preRemove PreRemove 在刪除現有行之前立即觸發
postRemove PostRemove 在刪除行之後立即觸發

每個事件都有自己的參數傳遞到其中,請參閱 PHP.NET Editor 事件文件,以獲取這些事件及其選項的完整詳細資訊。

PHP

PHP 沒有原生事件,因此 Editor 程式庫提供了一個介面,任何使用過 jQuery 的人都会立即熟悉 - on() 方法,它接受事件名稱作為第一個參數,並接受函數作為第二個參數;當觸發事件時,將執行此函數。

例如,請考慮以下 Editor 初始化

Editor::inst( $db, 'users' )
    ->fields(
        Field::inst( 'name' ),
        Field::inst( 'username' ),
        Field::inst( 'password' )
    )
    ->on( 'postCreate', function ( $e, $id, $values, $row ) {
        syslog( LOG_INFO, 'New user registered: '.$row['username'] );
    } )
    ->process( $_POST )
    ->json();

如果您之前使用過 Editor PHP 程式庫,則上面的大部分程式碼都會很熟悉 - 我們有一個包含三個欄位的 user 表格。這裡有趣的部分是 Editor->on() 方法 - 每當建立新使用者時,都會建立系統記錄訊息 (請參閱下面的更詳細記錄)。

這就是使用 PHP 程式庫處理事件的全部內容 - 監聽事件並定義一個將執行您所需任何動作的函數!

.NET

C# 在語言中內建了原生事件處理,Editor 程式庫使用您已經熟悉的這些方法來提供與其他 C# 程式庫一致的 API。

若要監聽事件,只需將處理常式新增至您要監聽的事件名稱

var editor = new Editor(Db, "users")
    .Model<UserModel>();

editor.PostCreate += (sender, e) =>
    AppLog( "New user registered: "+(string)e.Values["Username"] );

return Json(
    editor.Process(request).Data()
);

其中 AppLog 是一個本地函數,它將寫入檔案或資料庫,而 UserModel

public class StaffModel
{
    public string Name { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

範例

我們現在知道事件為何有用,以及它們如何在我們的程式碼中應用,因此讓我們看看這些技術的應用。以下範例都將使用上面定義的簡單 users 表格,並且僅顯示事件處理常式程式碼,因為其他所有內容都可以保持不變。

密碼欄位

對於密碼欄位,您通常只希望在終端使用者提供新值時才將新值寫入資料庫。如果沒有給定值,則應保留原始值。對於大多數欄位來說,這不是問題,因為可以很容易地從資料庫中讀取它們的值,但密碼不是這種情況,您不希望(並且不應該能夠)讀取實際值(它們畢竟應該是雜湊的 - 您可以使用設定格式器來執行此操作:PHP - .NET)。

使用 preEdit / PreEdit 事件,我們可以檢查使用者是否已提交值 - 如果沒有,我們可以阻止將欄位寫入,以便不會將密碼設定為空字串!

PHP
->on( 'preEdit', function ( $e, $id, $values ) {
    if ( $values['password'] === '' ) {
        $e->field( 'password' )->set( false );
    }
} );
.NET
editor.PreEdit += (sender, e) => {
    if ( e.Values["Password"] == "" ) {
        editor.Field("Password").Set(false);
    }
};

電子郵件通知

有時您可能有任務關鍵表單 - 您會為每個欄位新增驗證,但您仍然想知道何時在表格上進行編輯,以便您可以隨時掌握變更。使用*post* 事件,這非常容易

PHP
->on( 'postCreate', function ( $editor, $id, $values, $row ) {
    mail( 'myself@localhost', 'Row created', 'New row with id '.$id.' created' );
} )
->on( postEdit', function ( $editor, $id, $values, $row ) {
    mail( 'myself@localhost', 'Row edited', 'Row with id '.$id.' edited' );
} )
->on( postRemove', function ( $editor, $id, $values ) {
    mail( 'myself@localhost', 'Row deleted', 'Row with id '.$id.' deleted' );
} )
.NET
editor.PostCreate += (sender, e) =>
    Email( "Row created", "New row with id "+e.id+" created" );
editor.PostEdit += (sender, e) =>
    Email( "Row edited", "Row with id "+e.id+" edited" );
editor.PostRemove += (sender, e) =>
    Email( "Row deleted", "Row with id "+e.id+" deleted" );

其中函數 Email 可能是 (請參閱Scott Gu 的部落格,了解更多詳細資訊)

private void Email( string subject, string message )
{ 
    MailMessage message = new MailMessage();
    message.From = new MailAddress("sever@localhost);
    message.To.Add(new MailAddress("myself@localhost"));
    message.Subject = subject;
    message.Body = message;
     
    SmtpClient client = new SmtpClient();
    client.Send(message);
}

記錄

當然,對於較大或較常編輯的表格,每次編輯行的動作都收到電子郵件訊息是不切實際的。但是,能夠追蹤變更可能非常重要,在某些情況下甚至是強制性的,此時您可能需要開始考慮將記錄資訊寫入資料庫。

同樣,由於事件允許執行任何任意函數,因此我們可以輕鬆地將資訊寫入資料庫,尤其是 Editor 伺服器端程式庫提供了資料庫方法,可讓簡單的 SQL 命令得以輕鬆執行。

以下僅顯示 postEdit / PostEdit 事件,但可以輕鬆地將其擴展為適用於建立和刪除事件 - 並可能將插入移動到函數,以確保DRY

PHP
->on( 'postEdit', function ( $editor, $id, $values, $row ) {
    $editor->db()->insert( 'log', array(
        'user'   => $_SESSION['username'],
        'action' => 'Edit users table row',
        'values' => json_encode( $values ),
        'row'    => $id,
        'when'   => date('c')
    ) );
} )
.NET
editor.PostCreate += (sender, e) => db.Insert("log", new Dictionary<string, object>{
    { "user",   Session["user_id"] },
    { "action", "Edit users table row" },
    { "values", JsonConvert.SerializeObject( values ) },
    { "row",    id },
    { "when",   DateTime.Now.ToString("h:mm:ss tt") }
});

結論

這結束了介紹 Editor 1.5 的三部分系列文章的第二篇 - 接下來是 Editor 1.5 中可用的表單提交選項。