FilamentPHP 中默认登录行为

394 阅读3分钟

Filament 附带的默认登录类在大多数情况下就足够了,因为它包含电子邮件密码字段以及remember_me复选框。

但是,在某些情况下,您必须覆盖默认行为并相应地实现功能。因此,在本文中,我们将讨论如何覆盖默认登录类并在其上实现我们自己的功能。

Configuration 配置

在处理 Custom Login Class 之前,我们首先需要了解 FilamentPhp 如何在后台处理登录流程。要了解这一点,我们首先要研究一下 FilamentPHP 附带的默认 Service Provider,即位于 app/Providers/Filament/ 命名空间中的 AdminPanelProvider

如果我们查看该类,则有一个链接到 $panel 的 login 方法,它指示应该为此面板启用 login 功能。

如果我们继续研究该方法的实现,我们将看到如下内容:

/**
     * @param  string | Closure | array<class-string, string> | null  $action
     */
    public function login(string | Closure | array | null $action = Login::class): static
    {
        $this->loginRouteAction = $action;

        return $this;
    }

因此,默认情况下,如果我们不将任何类传递给此 login() 方法,则使用默认的 Login::class。 所以,这里的一般思路是扩展这个类,根据我们的需要对这个类进行必要的更改,并将该类传递给 login() 方法。

定义自定义 Login 类

因此,让我们首先通过扩展默认登录类来定义自定义登录类。我们将在 app/Filament/Pages 命名空间中定义它并将其命名为 CustomLogin

CustomLogin::class 目前如下所示:

<?php

namespace App\Filament\Pages;

use Filament\Http\Livewire\Auth\Login;

class CustomLogin extends Login
{
    //
}

默认的 Login 类包括与 login 相关的所有内容,例如 static view 属性(如果我们想传递自己的 view,可以覆盖它) authenticate 方法(如果我们想更新用户的身份验证方式,我们可以覆盖它) getTitle 和 getHeading 方法覆盖页面的标题和标题 以及其他类似的属性和方法,这些属性和方法根据我们的需要被覆盖。

使用 Username 而不是 Email 进行身份验证

例如,我们将覆盖默认行为,并使用用户名而不是默认电子邮件进行身份验证。 有多种方法可以做到这一点,我们可以覆盖 getForms 方法并传递一个 $this->getUsernameFormComponent() 方法而不是 $this->getEmailFormComponent() ,

在 getUsernameFormComponent() 方法上,我们可以为 username 字段传递一个表单组件。

但是,我们将保持简单,只需覆盖 getEmailFormComponent() 方法并为 username 字段传递一个表单组件。

当我们为 Username 字段传递 Form 组件时,getEmailFormComponent() 看起来像这样

protected function getEmailFormComponent(): Component
    {
        return TextInput::make('username')
            ->label('Username')
            ->required()
            ->autofocus()
            ->extraInputAttributes(['tabindex' => 1])
            ->autocomplete();
    }

我们还需要覆盖 getCredentialsFromFormData 方法,因为此方法已传递给 authenticate 方法,并将 email key 替换为 username key。 更改后,getCredentialsFromFormData 如下所示:

protected function getCredentialsFromFormData(array $data): array
    {
        return [
            'username' => $data['username'],
            'password' => $data['password'],
        ];
    }

经过必要的修改后,最终的 login 类如下所示:

<?php

namespace App\Filament\Pages;

use Filament\Facades\Filament;
use Filament\Pages\Auth\Login;
use Filament\Forms\Components\Component;
use Filament\Forms\Components\TextInput;
use Illuminate\Contracts\Support\Htmlable;


class CustomLogin extends Login
{
    public function mount(): void
    {
        if (Filament::auth()->check()) {
            redirect()->intended(Filament::getUrl());
        }

        if (app()->environment('local')) {
            $this->form->fill([
                'username' => 'admin',
                'password' => 'password',
            ]);
        }
    }

    protected function getCredentialsFromFormData(array $data): array
    {
        return [
            'username' => $data['username'],
            'password' => $data['password'],
        ];
    }

    public function getTitle(): string|Htmlable
    {
        return __('Admin Login');
    }

    public function getHeading(): string|Htmlable
    {
        return __('Admin Login');
    }

    protected function getEmailFormComponent(): Component
    {
        return TextInput::make('username')
            ->label('Username')
            ->required()
            ->autofocus()
            ->extraInputAttributes(['tabindex' => 1])
            ->autocomplete();
    }
}

除了上面讨论的方法外,我还重写了其他一些方法,比如 getTitlegetHeading 和 mount 方法。mount 方法有点有趣,因为它检查用户是否通过身份验证,如果是,则它将重定向到预期的仪表板。

如果应用程序未登录,则如果应用程序的环境是本地的,我们将使用默认的用户名和密码填写表单。