2015 年 10 月 2 日,星期五

编辑器服务器端事件

这是介绍 Editor 1.5 新功能的一系列文章中的第二篇。此前,多行编辑 是讨论的重点,而在本文中,我将研究已添加到 PHP 和 .NET 库中的服务器端事件,这些事件可作为 Editor 包的一部分使用,并演示如何将它们用于提高服务器端软件的灵活性。

为什么使用服务器端事件

PHP 和 .NET Editor 服务器端库非常简便,可以创建可读/写表,但可能包含复杂的操作,例如文件上传和连接表,但依然以简单的可读/写操作为根基。对于大型应用程序而言,这是一个良好的开端,但通常还不够——你希望能够根据最终用户执行的数据执行某些操作。

服务器端事件的一个常见示例,也是我们将在下面探讨的一个示例,是将数据更改写入数据库日志表以提供跟踪信息和责任制。另一个示例可能是基于用户输入启动外部进程,例如构建脚本。无论出于何种原因,事件现在在 Editor 中提供了该能力。

如何使用

PHP 和 .NET 库提供的事件在逐行的基础上触发——这一点非常重要,因为 Editor 1.5 具有多行编辑功能。这些事件在创建、编辑或删除行之前立即和之后触发。 beforehand 事件允许修改字段和输入数据,而 afterwards 事件可用于提供已发生该操作的通知。

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() 方法 - 每当创建新用户时,将创建一个 syslog 消息(有关更详细的日志记录,请参见下文)。

使用 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") }
});

结论

这是介绍编辑器 1.5 的三部分系列中的第二个部分——下一个是编辑器 1.5 中可用的表单提交选项。