我甚至试图在我的 L5 应用程序中挂接登录以设置上次登录时间和 IP 地址。 我可以使其与以下内容一起使用:
Event::listen('auth.login', function($event)
{
Auth::user()->last_login = new DateTime;
Auth::user()->last_login_ip = Request::getClientIp();
Auth::user()->save();
});
但是,我想知道在 L5 中执行此操作的最佳方法是使用事件处理程序对象。 我尝试创建一个事件处理程序并将 auth.login 添加为事件服务提供商中的数组键,但这不起作用。 我不确定 auth.login 事件是否可能。 如果不是, 放置上述代码最合适的位置在哪里。为了进行测试,我把它放在我的 routes.php 文件中,但我知道这不是它应该在的地方。
在 laravel 5.2 中; auth.login 不起作用...必须使用以下内容:
protected $listen = [
'Illuminate'Auth'Events'Attempting' => [
'App'Listeners'LogAuthenticationAttempt',
],
'Illuminate'Auth'Events'Login' => [
'App'Listeners'LogSuccessfulLogin',
],
'Illuminate'Auth'Events'Logout' => [
'App'Listeners'LogSuccessfulLogout',
],
'Illuminate'Auth'Events'Lockout' => [
'App'Listeners'LogLockout',
],
];
如此处的文档中所述
编辑:这仅适用于 5.0.* 和 5.1.*。
有关 5.2.* 解决方案,请参阅下面的 JuLiAnc 响应。
在处理了两个提议的答案以及更多的研究之后,我终于想出了如何以我最初尝试的方式做到这一点。
我运行了以下工匠命令
$ php artisan handler:event AuthLoginEventHandler
然后我更改了生成的类,删除了 Event 类的导入并导入了用户模型。我还User $user
和$remember
传递给了句柄方法,因为当 auth.login 事件被触发时,这就是传递的内容。
<?php namespace App'Handlers'Events;
use Illuminate'Queue'InteractsWithQueue;
use Illuminate'Contracts'Queue'ShouldBeQueued;
use App'User;
class AuthLoginEventHandler {
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param User $user
* @param $remember
* @return void
*/
public function handle(User $user, $remember)
{
dd("login fired and handled by class with User instance and remember variable");
}
}
现在我打开了 EventServiceProvide.php并修改了 $listen
数组,如下所示:
protected $listen = [
'auth.login' => [
'App'Handlers'Events'AuthLoginEventHandler',
],
];
我意识到如果一开始这不起作用,您可能需要
$ php artisan clear-compiled
现在,我们可以使用事件处理程序类响应通过 auth.login 事件登录的用户!
小心询问做X的最佳方法是什么,因为特别是Laravel提供了许多完成相同任务的方法 - 在某些情况下,有些方法比其他方法更好。
看看Laravel文档,我个人会选择"基本用法",因为它似乎与您所说的用例相匹配。
如果我们运行以下 Artisan 命令,我们可以为 UserLoggedIn 事件生成一个模板。
$ php artisan make:event UserLoggedIn
(请注意过去时,因为事件发生了,然后订阅者会收到事件发生的通知)
(注意2:命名空间中的app
字符串是Laravel开箱即用的,如果您执行了php artisan app:name
命令,则可能会有所不同)
为我们生成以下类:
<?php namespace app'Events;
use app'Events'Event;
use Illuminate'Queue'SerializesModels;
class UserLoggedIn extends Event {
use SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
}
如果我们向构造函数添加 userId
参数,则事件不需要知道身份验证外观/保护协定。这意味着我们的UserLoggedIn
事件代码不会与 Eloquent 或您决定在应用中使用的身份验证框架紧密耦合。无论如何,让我们添加该userId
参数。
<?php namespace app'Events;
use app'Events'Event;
use app'User;
use Illuminate'Queue'SerializesModels;
class UserLoggedIn extends Event {
use SerializesModels;
public $userId;
/**
* Create a new event instance.
*
* @param int userId the primary key of the user who was just authenticated.
*
* @return void
*/
public function __construct($userId)
{
$this->userId = $userId;
}
}
现在你可能想知道,这很好,但是我们如何对这个事件采取行动?好问题!我们需要创建一个事件处理程序来处理触发此事件的时间。现在让我们使用 Artisan 来做到这一点:
$ php artisan handler:event UpdateUserMetaData --event=UserLoggedIn
我们将新的事件处理程序命名为 UpdateUserMetaData
,并告诉 Artisan 我们要处理的事件是UserLoggedIn
事件。
现在我们在app/Handlers/Events/UpdateUserMetaData.php
内部有一些看起来像这样的代码:
<?php namespace app'Handlers'Events;
use app'Events'UserLoggedIn;
use Illuminate'Queue'InteractsWithQueue;
use Illuminate'Contracts'Queue'ShouldBeQueued;
class UpdateUserMetaData {
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserLoggedIn $event
* @return void
*/
public function handle(UserLoggedIn $event)
{
//
}
}
我们可以更新句柄方法,以便能够像您上面指定的那样轻松处理此事件:
<?php namespace app'Handlers'Events;
use app'Events'UserLoggedIn;
use Illuminate'Http'Request;
class UpdateUserMetaData {
protected $request;
/**
* Create the event handler.
*
* @param Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Handle the event.
*
* @param UserLoggedIn $event
*/
public function handle(UserLoggedIn $event)
{
$user = User::find($event->userId); // find the user associated with this event
$user->last_login = new DateTime;
$user->last_login_ip = $this->request->getClientIp();
$user->save();
}
}
作为旁注,如果您不熟悉 Carbon,您可能需要考虑使用它,以便您可以利用其出色的 API,就像在大多数模型上使用 Eloquent 的 created_at
和updated_at
时间戳字段一样。这里有一个链接,告诉你Eloquent哪些字段应该与Carbon一起使用:http://laravel.com/docs/master/eloquent#date-mutators。
这段代码在您的Laravel应用程序中工作之前,我们必须执行最后两个步骤。
我们需要将事件映射到
app/Providers
目录下EventServiceProvider
类中的事件处理程序。我们需要在登录后触发事件。
要完成第一步,我们只需要将我们的事件类添加到 $listeners
属性中,如下所示app/Providers/EventServiceProvder.php
:
UserLoggedIn::class => [
UpdateUserMetaData::class
]
如果您导入 EventServiceProvider
类中的类,并且您使用的是 PHP 5.5,则上述方法将起作用。如果您使用的是较低的 PHP 版本,则需要以字符串形式提供每个类的完整路径,如下所示:'app/Events/UserLoggedIn'
和 'app/Handlers/Events/UpdateUserMetaData'
。
$listeners
数组将事件映射到其各自的处理程序。
好了,现在是最后一步!在代码库中,找到对用户进行身份验证的位置并添加以下内容:
event(new 'app'Events'UserLoggedIn(Auth::user()->id));
我们完成了!我在写这个答案时测试了这段代码,如果您有任何问题,请随时提出后续问题。
对于 5.2 类似
的东西在侦听器中:
use Carbon'Carbon;
use Illuminate'Auth'Events'Login;
class UpdateLastLoginWithIp
{
public function handle(Login $event)
{
$event->user->last_login_at = Carbon::now();
$event->user->last_login_ip = Request::getClientIp()
$event->user->save();
}
}
在 EventServiceProvider 中.php :
protected $listen = [
'Illuminate'Auth'Events'Login' => [
'City'Listeners'UpdateLastLoginWithIp',
],
];
通常,您可以通过逐步执行此操作来实现 用户登录日志
首先,您应该拥有身份验证脚手架
- 将此用作事件,
- 登录
- 事件的"亮起''身份验证''事件''登录" 注销
- 事件的"照亮''身份验证''事件''注销"
位于 的登录和注销事件:
vendor''laravel''framework''src''Illuminate''Auth''Events
事件服务提供商.php
protected $listen = [
'Illuminate'Auth'Events'Login' => [
'App'Listeners'LoginLogs',
],
'Illuminate'Auth'Events'Logout' => [
'App'Listeners'LogoutLogs',
],
];
public function boot()
{
parent::boot();
}
- 然后在完成事件服务提供程序后,执行下一步
- 键入此工匠命令 PHP 工匠事件:生成
- 在应用程序文件夹中查找文件夹侦听器,检查是否包含 php 文件登录日志和注销日志
- 创建迁移和模型
命令: PHP 工匠制作:迁移create_UserLoginHistory
迁移文件
public function up()
{
Schema::create('tbl_user_login_history', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->datetime('login_at')->nullable();
$table->datetime('logout_at')->nullable();
$table->string('login_ip')->nullable();
$table->string('role');
$table->string('session_id');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('tbl_user_login_history');
}
然后你的模型:用户登录历史
public $timestamps = false;
protected $table = 'tbl_user_login_history';
protected $fillable = ['user_id','login_at','logout_at','login_ip','role','session_id'];
public function setLogOutLog(){
$this->where('session_id',request()->session()->getId())->update([
'logout_at' =>Carbon::now(),
]);
}
public function setLogInLog(){
$this->insert(
['user_id' => Auth::user()->id,'login_at' =>Carbon::now(),
'login_ip'=>request()->getClientIp(),'role' =>Auth::user()->role,
'session_id'=>request()->session()->getId()
]);
}
4.在迁移和模型创建过程之后,假设您已经在"用户"表中具有角色
- 侦听器部分
侦听器:登录日志类
use App'UserLoginHistory;
private $UserLoginHistory;
public function __construct(UserLoginHistory $UserLoginHistory)
{
// the initialization of private $UserLoginHistory;
$this->UserLoginHistory = $UserLoginHistory;
}
public function handle(Login $event)
{
// from model UserLoginHistory
$this->UserLoginHistory->setLogInLog();
}
侦听器:注销日志类
private $UserLogoutHistory;
public function __construct(UserLoginHistory $UserLoginHistory)
{
// the initialization of private $UserLogoutHistory;
$this->UserLogoutHistory = $UserLoginHistory;
}
public function handle(Logout $event)
{
// from model UserLoginHistory
$this->UserLogoutHistory->setLogOutLog();
}
完成所有步骤后,尝试使用身份验证登录
的方法:
我已经在用户登录时使用以下命令制作事件处理程序:
- 拉
- 拉维尔 5.8
1) 运行以下 artian 命令
php artisan make:listener Auth/UserLoggedIn --event='Illuminate'Auth'Events'Login'
*
它将在文件夹app'Listeners'Auth'
中创建一个侦听器:UserLoggedIn
2)然后您需要将此侦听器添加到EventServiceProvider
:**
...
protected $listen = [
...
'Illuminate'Auth'Events'Login' => [
'App'Listeners'Auth'UserLoggedIn',
],
];
最后,当用户登录位于UserLoggedIn
监听器handle
功能时,您可以进行记录:
public function handle(Login $event)
{
//you have access to user object by using : $event->user
}
- 您可以使用所有其他身份验证事件,以下是可能的事件:
'Illuminate'Auth'Events'Registered',
'Illuminate'Auth'Events'Attempting',
'Illuminate'Auth'Events'Authenticated',
'Illuminate'Auth'Events'Login',
'Illuminate'Auth'Events'Failed',
'Illuminate'Auth'Events'Logout',
'Illuminate'Auth'Events'Lockout',
**您可以在EventServiceProvider
中使用所有这些事件:https://laravel.com/docs/5.8/authentication#events
打开 EventServiceProvider.php在引导方法中,您可以通过回调侦听'auth.login'
事件。
public function boot(DispatcherContract $events)
{
parent::boot($events);
$events->listen('auth.login', function()
{
dd('logged in event');
});
}
您可能希望创建侦听器,以便将回调函数移动到其他地方。按照这个 http://laravel.com/docs/4.2/events#using-classes-as-listeners<</p>
就是这样做
的 <?php
namespace App'Providers;
use App'User;
use Auth;
use DB;
use Illuminate'Contracts'Events'Dispatcher as DispatcherContract;
use Illuminate'Foundation'Support'Providers'EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
];
/**
* Register any other events for your application.
*
* @param 'Illuminate'Contracts'Events'Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
{
parent::boot($events);
$events->listen('auth.login', function()
{
DB::table('users')
-> where('id', Auth::id())
-> update(array(
'last_login' => date('Y-m-d H:i:s')
));
});
//
}
}