有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多加思考会发现有时候这些服务其实我们一直都见过。下面就事件、事件监听举一个很简单的例子你就会发现。
这个例子是关于文章的浏览数的实现,当用户查看文章的时候文章的浏览数会增加1,用户查看文章就是一个事件,有了事件,就需要一个事件监听器,对监听的事件发生后执行相应的操作(文章浏览数加1),其实这种监听机制在 Laravel 中是通过观察者模式实现的.
注册事件以及监听器
首先我们需要在 app/Providers/目录下的EventServiceProvider.php中注册事件监听器映射关系,如下:
protected $listen = [ 'App\Events\BlogView' => [ 'App\Listeners\BlogViewListener', ], ];
然后项目根目录下执行如下命令
php artisan event:generate
该命令完成后,会分别自动在 app/Events和app/Listensers目录下生成 BlogView.php和BlogViewListener.php文件。
定义事件
<?php namespace App\Events; use App\Events\Event; use App\Post; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class BlogView extends Event { use SerializesModels; /** * Create a new event instance. * * @return void */ public function __construct(Post $post) { $this->post = $post; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return []; } }
其实看到这些你会发现该事件类只是注入了一个 Post实例罢了,并没有包含多余的逻辑。
定义监听器
事件监听器在handle方法中接收事件实例,event:generate命令将会自动在handle方法中导入合适的事件类和类型提示事件。在handle方法内,你可以执行任何需要的逻辑以响应事件,我们的代码实现如下:
<?php namespace App\Listeners; use App\Events\BlogView; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Session\Store; class BlogViewListener { protected $session; /** * Create the event listener. * * @return void */ public function __construct(Store $session) { $this->session = $session; } /** * Handle the event. * * @param BlogView $event * @return void */ public function handle(BlogView $event) { $post = $event->post; //先进行判断是否已经查看过 if (!$this->hasViewedBlog($post)) { //保存到数据库 $post->view_cache = $post->view_cache + 1; $post->save(); //看过之后将保存到 Session $this->storeViewedBlog($post); } } protected function hasViewedBlog($post) { return array_key_exists($post->id, $this->getViewedBlogs()); } protected function getViewedBlogs() { return $this->session->get('viewed_Blogs', []); } protected function storeViewedBlog($post) { $key = 'viewed_Blogs.'.$post->id; $this->session->put($key, time()); } }
注释中也已经说明了一些逻辑。
触发事件
事件和事件监听完成后,我们要做的就是实现整个监听,即触发用户打开文章事件在此我们使用和 Event提供的 fire方法,如下:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use Illuminate\Support\Facades\Event; use App\Http\Requests; use App\Events\BlogView; use App\Http\Controllers\Controller; class BlogController extends Controller { public function showPost($slug) { $post = Post::whereSlug($slug)->firstOrFail(); Event::fire(new BlogView($post)); return view('home.blog.content')->withPost($post); } }
现在打开页面发现数据库中的`view_cache已经正常加1了,这样整个就完成了。
事件广播
简介:
Laravel 5.1 之中新加入了事件广播的功能,作用是把服务器中触发的事件通过websocket服务通知客户端,也就是浏览器,客户端js根据接受到的事件,做出相应动作。本文会用简单的代码展示一个事件广播的过程。
依赖:
- redis
- nodejs, socket.io
- laravel 5.1
配置:
- config/broadcasting.php中,如下配置'default' => env('BROADCAST_DRIVER', 'redis'),,使用redis作为php和js的通信方式。
- config/database.php中配置redis的连接。
定义一个被广播的事件:
根据Laravel文档的说明,想让事件被广播,必须让Event类实现一个Illuminate\Contracts\Broadcasting\ShouldBroadcast接口,并且实现一个方法broadcastOn。broadcastOn返回一个数组,包含了事件发送到的channel(频道)。如下:
namespace App\Events; use App\Events\Event; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class SomeEvent extends Event implements ShouldBroadcast { use SerializesModels; public $user_id; /** * Create a new event instance. * * @return void */ public function __construct($user_id) { $this->user_id = $user_id; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return ['test-channel']; } }
被广播的数据:
默认情况下,Event中的所有public属性都会被序列化后广播。上面的例子中就是$user_id这个属性。你也可以使用broadcastWith这个方法,明确的指出要广播什么数据。例如:
public function broadcastWith() { return ['user_id' => $this->user_id]; }
Redis和Websocket服务器:
需要启动一个Redis,事件广播主要依赖的就是redis的sub/pub功能,具体可以看redis文档
需要启动一个websocket服务器来和client通信,建议使用socket.io,代码如下:
var app = require('http').createServer(handler); var io = require('socket.io')(app); var Redis = require('ioredis'); var redis = new Redis('6379', '192.168.1.106'); app.listen(6001, function() { console.log('Server is running!'); }); function handler(req, res) { res.writeHead(200); res.end(''); } io.on('connection', function(socket) { console.log('connected'); }); redis.psubscribe('*', function(err, count) { console.log(count); }); redis.on('pmessage', function(subscribed, channel, message) { console.log(subscribed); console.log(channel); console.log(message); message = JSON.parse(message); io.emit(channel + ':' + message.event, message.data); });
这里需要注意的是redis.on方法的定义,接收到消息后,给client发送一个事件,事件名称为channel + ':' + message.event。
客户端代码:
客户端我们也使用socket.io,作为测试,代码尽量简化,仅仅打印一个接受到的数据即可。如下:
var socket = io('http://localhost:6001'); socket.on('connection', function (data) { console.log(data); }); socket.on('test-channel:App\\Events\\SomeEvent', function(message){ console.log(message); }); console.log(socket);
服务器触发事件:
直接在router中定义个事件触发即可。如下:
Route::get('/event', function(){ Event::fire(new \App\Events\SomeEvent(3)); return "hello world"; });
测试:
- 启动redis
- 启动websocket
- 打开带有客户端代码的页面,可以看到websocket已经连接成功。
- 触发事件,打开另一个页面 localhost/event。
这时就可以发现,第一个页面的console中打印出了Object{user_id: 3},说明广播成功。

PHP在現代Web開發中仍然重要,尤其在內容管理和電子商務平台。 1)PHP擁有豐富的生態系統和強大框架支持,如Laravel和Symfony。 2)性能優化可通過OPcache和Nginx實現。 3)PHP8.0引入JIT編譯器,提升性能。 4)雲原生應用通過Docker和Kubernetes部署,提高靈活性和可擴展性。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。

PHP在現代編程中仍然是一個強大且廣泛使用的工具,尤其在web開發領域。 1)PHP易用且與數據庫集成無縫,是許多開發者的首選。 2)它支持動態內容生成和麵向對象編程,適合快速創建和維護網站。 3)PHP的性能可以通過緩存和優化數據庫查詢來提升,其廣泛的社區和豐富生態系統使其在當今技術棧中仍具重要地位。

在PHP中,弱引用是通過WeakReference類實現的,不會阻止垃圾回收器回收對象。弱引用適用於緩存系統和事件監聽器等場景,需注意其不能保證對象存活,且垃圾回收可能延遲。

\_\_invoke方法允許對象像函數一樣被調用。 1.定義\_\_invoke方法使對象可被調用。 2.使用$obj(...)語法時,PHP會執行\_\_invoke方法。 3.適用於日誌記錄和計算器等場景,提高代碼靈活性和可讀性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

WebStorm Mac版
好用的JavaScript開發工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器