资讯专栏INFORMATION COLUMN

基于Model Event模型事件的Laravel实时APP

afishhhhh / 1030人阅读

摘要:重点是在页面写入新文本,页面不能实时显示。想要了解更多可以参考这篇文章基于驱动的事件广播下测试实时功能刷新页面,并观察数据库。测试实时创建功能。

说明:本文主要来源于real-time-apps-laravel-5-1-event-broadcasting

本文主要基于Laravel的Model Event介绍该框架的实时通信功能,Laravel模型的生命周期中包含事件:createdcreatingsavedsavingupdatedupdatingdeleteddeletingrestoredrestoring,同时结合了Pusher包,有关Pusher的注册和使用相关信息可以参考:基于 Pusher 驱动的 Laravel 事件广播(上)。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。
备注:Laravel对Model的CRUD操作都会触发对应的事件,如create操作会在创建前触发creating事件,创建后触发created事件,即Model Event。

Non Real-time App Laravel程序安装

先全局安装composer:

    curl -sS https://getcomposer.org/installer | php
    mv composer.phar /usr/local/bin/composer

新建一个空文件夹,在文件夹下,再使用composer安装Laravel项目:

composer create-project laravel/laravel mylaravelapp --prefer-dist
写一个TODO APP 写路由Route

在app/Http/routes.php中写上资源型路由:

Route::get("/", function () {
    return view("index");
});
Route::resource("items", "ItemController", ["except" => ["create", "edit"]]);//排除掉create和edit操作
写个Model

先建个迁移文件:

php artisan make:migration create_items_table --create=items

在迁移文件database/migrations/*_create_items_table.php中写上:

/**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("items", function (Blueprint $table) {
            $table->increments("id");
            $table->string("title");
            $table->boolean("isCompleted")->default(false);
            $table->timestamps();
        });
    }

新建一个Eloquent Model:

php artisan make:model Item

别忘了配置下数据库,我用的是MAMP集成环境,数据库服务是MySQL。数据库配置主要在config/database.php和.env文件中,在.env文件中写上对应的host,database,user,password:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=model_event
DB_USERNAME=root
DB_PASSWORD=model_event
写控制器Controller

首先在项目根目录下输入artisan命令创建个ItemController:

php artisan make:controller ItemController

在ItemController中写上增删改查:

class ItemController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $uncompletedItems = Item::where("isCompleted", 0)->get();
        $completedItems = Item::where("isCompleted", 1)->get();

        $data = ["uncompletedItems" => $uncompletedItems,
            "completedItems" => $completedItems];

        return view("item.index", $data);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store(Request $request)
    {
        $item = new Item;
        $item->title = $request->title;
        $item->save();
        return response()->json(["id" => $item->id]);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        $item = Item::find($id);
        return view("item.show", ["item" => $item]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $item = Item::find($id);
        $item->isCompleted = (bool) $request->isCompleted;
        $item->save();
        return;
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function destroy($id)
    {
        $item = Item::find($id);
        $item->delete();
        return;
    }
}
写个View视图

建个reources/views/index.php:



  
    
    
    
    
    Todo App

    
    {{----}}
      

    
    
    
      {{----}}
    {{----}}
  
  
    

Todo App


{{----}} {{----}} {{----}}

ItemController控制器中返回两个子视图item.index、item.show,在resources/views/item中建两个:

//item.index
未完成的Items
    @foreach ($uncompletedItems as $item) @include("item.show") @endforeach

完成的Items
    @foreach ($completedItems as $item) @include("item.show") @endforeach
//item.show
  • 一切准备就OK了,我的在MAMP环境输入路由:http://laravelmodelevent.app:...,新开AB两个页面,然后在输入框里提交文本后:

    A页面输入后B页面只有刷新才能看到最新输入的文本,不能实时显示,当然,输入的文本已经保存在model_event.items表里了:

    页面里改变每一个item的checkbox后,该item的状态将会互换,在UI上显示也是上下位置互换,具体逻辑可以看views/index.blade.php的JS逻辑,这不是本文的重点,故不详述。

    重点是:在A页面写入新文本,B页面不能实时显示。这还不是个实时APP。

    Real-time App 创建三个广播事件

    创建三个广播事件:

    ItemCreated:当新建一个item完成时触发

    ItemUpdated:当更新一个item完成时触发(isCompleted=0或1)

    ItemDeleted:当删除一个item完成时触发

    在项目根目录依次输入:

    php artisan make:event ItemCreated
    php artisan make:event ItemUpdated
    php artisan make:event ItemDeleted

    Laravel事件广播需要实现ShouldBroadcast接口并且在broadcastOn()方法中写上广播频道:

    class ItemCreated extends Event implements ShouldBroadcast
    {
        use SerializesModels;
    
        public $id;
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct(Item $item)
        {
            $this->id = $item->id;
        }
    
        /**
         * Get the channels the event should be broadcast on.
         *
         * @return array
         */
        public function broadcastOn()
        {
            return ["itemAction"];
        }
    }
    class ItemDeleted extends Event implements ShouldBroadcast
    {
        use SerializesModels;
    
        public $id;
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct(Item $item)
        {
            $this->id = $item->id;
        }
    
        /**
         * Get the channels the event should be broadcast on.
         *
         * @return array
         */
        public function broadcastOn()
        {
            return ["itemAction"];
        }
    }
    class ItemUpdated extends Event implements ShouldBroadcast
    {
        use SerializesModels;
    
        public $id;
        public $isCompleted;
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct(Item $item)
        {
            $this->id          = $item->id;
            $this->isCompleted = (bool)$item->isCompleted;
        }
    
        /**
         * Get the channels the event should be broadcast on.
         *
         * @return array
         */
        public function broadcastOn()
        {
            return ["itemAction"];
        }
    }
    创建Model Event

    Laravel的Eloquent每一CRUD操作都会触发Model事件,可以在service provider里监听这些事件从而触发新建的三个广播事件,在AppServiceProvider中:

    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            Item::created(function($item){
                event(new ItemCreated($item));
            });
            Item::deleted(function($item){
                event(new ItemDeleted($item));
            });
            Item::updated(function($item){
                event(new ItemUpdated($item));
            });
        }
    
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }
    使用Pusher

    Pusher的作用、注册和安装可参考:基于 Pusher 驱动的 Laravel 事件广播(上)
    注册安装也比较简单,总之使用Pusher能做个实时APP。
    更新resources/views/index.blade.php文件:

    ...
        Todo App
          
        
        //引入pusherJS文件
               
    ...
            $.post( "/items", $(this).serialize(), function( data ) {
    //                    addItem(data.id, false);//注销掉
                        $( "#title" ).val("");
                    });
    ...
           $.ajax("/items/" + id, {//进入ItemController::update(),更细下item状态
                        data: {"isCompleted": isCompleted},
                        method: "PATCH",
                        success: function() {//根据状态变化删除增加item
    //                        removeItem(id);//注销掉
    //                        addItem(id, isCompleted);//注销掉
                        }
                    });
    ...                
            $(document).on("click", ".deleteItem", function() {
                    var id = $(this).closest("li").data("id");
                    $.ajax("/items/" + id, {//进入ItemController::destroy()删除数据库中item
                        method: "DELETE",
                        success: function() {//UI删除该item
    //                        removeItem(id);//注销掉
                        }
                    });
                });
            })(jQuery, addItem, removeItem);
    
        //新加代码
            var pusher            = new Pusher("{{env("PUSHER_KEY")}}");
            var itemActionChannel = pusher.subscribe("itemAction");
            itemActionChannel.bind("AppEventsItemCreated", function (data) {
                console.log(data.id);
               addItem(data.id, false);
            });
            itemActionChannel.bind("AppEventsItemDeleted", function (data) {
                console.log(data.id);
               removeItem(data.id);
            });
            itemActionChannel.bind("AppEventsItemUpdated", function (data) {
                removeItem(data.id);
                addItem(data.id, data.isCompleted);
            });     
          
          

    新加代码主要用pusher对象注册三个事件广播的频道"itemAction",并分别绑定三个事件,成功后回调执行对应的UI操作。想要了解更多可以参考这篇文章:基于 Pusher 驱动的 Laravel 事件广播(下)

    测试实时功能

    刷新AB页面,并观察数据库model_event.items。

    测试实时创建功能。A页面输入文本后发现B页面不用刷新就实时显示对应内容,且数据库已经保存刚刚创建的文本:

    测试实时更新功能。B页面点击状态更新checkbox后,A页面该item状态也实时更新,且数据库isCompleted字段变为1:

    测试实时删除功能。A页面点击删除按钮后,B页面也实时删除对应的item,且数据库该item也删除:

    OK,It is working!!!

    总结:本节主要利用Laravel的Model Event来创建一个实时WEB APP,挺好玩的,可以玩一玩哦。有问题可留言。嘛,过两天还想结合Laravel的Container Event容器事件新开篇文章,到时见。

    欢迎关注Laravel-China。

    RightCapital招聘Laravel DevOps

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/21530.html

    相关文章

    • [Laravel 5.3] Notification 个人理解,及 BearyChat Channe

      摘要:提供了一种全新的发送通知的方式。个人理解是可以基于某事件操作触发一系列的通知任务,而通知方式由通知渠道接管,这样使得通知或推送逻辑更抽象,更易于管理和重构。在之前,我是利用的来完成这一系列通知。使用的配置文件还是原来的,无需重新配置。 Laravel Notification Laravel 5.3 提供了一种全新的发送通知的方式:Notification 。个人理解是可以基于某事件(...

      Yang_River 评论0 收藏0
    • Laravel学习笔记之Model Observer模型观察者

      摘要:说明本文主要学习下的模型观察者,把一点点经验分享出来希望对别人能有帮助。模型观察者这个功能能做很多事情,比如模型更新时发个通知。总结本篇文章主要学了下的模型观察者,发现这个功能也能使代码结构更清晰,觉得挺好的。 说明:本文主要学习下Laravel的Model Observer模型观察者,把一点点经验分享出来希望对别人能有帮助。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率...

      Crazy_Coder 评论0 收藏0
    • Laravel学习笔记之Redis保存页面浏览量

      摘要:说明本文主要讲述使用作为缓存加快页面访问速度。何不用来做缓存,等到该达到一定浏览页面后再刷新下,效率也很高。可作缓存系统队列系统。 说明:本文主要讲述使用Redis作为缓存加快页面访问速度。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。 备注:作者最近在学习github上别人的源码时,发现好多在计算一篇博客页面访问量view_count时都是这么做的:利用Laravel...

      z2xy 评论0 收藏0
    • Laravel学习笔记之Redis保存页面浏览量

      摘要:说明本文主要讲述使用作为缓存加快页面访问速度。何不用来做缓存,等到该达到一定浏览页面后再刷新下,效率也很高。可作缓存系统队列系统。 说明:本文主要讲述使用Redis作为缓存加快页面访问速度。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。 备注:作者最近在学习github上别人的源码时,发现好多在计算一篇博客页面访问量view_count时都是这么做的:利用Laravel...

      Jokcy 评论0 收藏0
    • laravel 模型事件几种用法

      摘要:一简单粗鲁用于本地测试路由中定义测试一下修改事件二生成事件和监听器在定义对应关系生成文件中注入要操作的类中方法注入对应事件类测试一下修改事件最后在模型中添加属性三利用框架的方法直接在相关中定义测试一下修改事件四定义如果想对多个模型的或事件进 一 、简单粗鲁(用于本地测试) 路由中定义: Event::listen(eloquent.updated: AppPost,function ...

      KavenFan 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <