php - 如何在 PasswordBroker Laravel 5 中覆盖 reset 和 validatePasswordWithDefaults

标签 php laravel overriding laravel-5

我真的是这个框架的新手,它对我来说太神奇了。 我什至找不到它在路由和 Controller 中调用函数 reset() 的位置。 但我知道在浏览了一整天的谷歌之后,它已经在 Controller 之前被调用了。

问题来了 我一直在测试覆盖 PasswordBroker 中的函数重置和函数 validatePasswordWithDefaults

我通过扩展 PasswordBroker 来做到这一点,但似乎我必须将 Illuminate\Auth\Passwords\PasswordBroker 中的所有功能完全迁移到我的 App\Services\PasswordBroker 否则我会遇到错误:

Target [Illuminate\Contracts\Auth\UserProvider] is not instantiable

我的示例代码在这里:

将我的 PasswordBroker 绑定(bind)到 Illuminate PasswordBroker 的自定义 PasswordServiceProvider:

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class PasswordResetServiceProvider extends ServiceProvider {

/**
 * Bootstrap the application services.
 *
 * @return void
 */
public function boot()
{
    //
}

/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    //
    $this->app->bind(
        'Illuminate\Contracts\Auth\PasswordBroker','App\Services\PasswordBroker'
        );


}

}

Custom PasswordBroker:
<?php
    namespace App\Services;


    use Illuminate\Contracts\Auth\UserProvider;
    use Illuminate\Auth\Passwords\TokenRepositoryInterface;
    use Illuminate\Auth\Passwords\PasswordBroker as BasePasswordBroker;
    use Illuminate\Contracts\Auth\PasswordBroker as ContractPasswordBroker;

    use Closure;

    class PasswordBroker extends BasePasswordBroker
    {

        public function reset(array $credentials, Closure $callback)
        {
            dd($callback);
            $user = $this->validateReset($credentials);

            if ( ! $user instanceof CanResetPasswordContract)
            {
                return $user;
            }

            $pass = $credentials['password'];

            call_user_func($callback, $user, $pass);

            $this->tokens->delete($credentials['token']);

            return PasswordBrokerContract::PASSWORD_RESET;
        }

        protected function validatePasswordWithDefaults(array $credentials)
        {
            list($password, $confirm) = [
                $credentials['password'], $credentials['password_confirmation'],
            ];

            return $password === $confirm && mb_strlen($password) >= 4;
        }
    }
    ?>

最佳答案

这并不简单,在我看来,框架不应该向代码发送如此深入的电子邮件,并提供一种从 Controller 覆盖它的方法。

我不得不覆盖电子邮件发送,因为我需要使用 Mandrill 的 api,所以我必须在邮件发送的那一刻发送额外的标题。这就是我所做的:

  1. 在 App\Providers\PasswordResetServiceProvider 上创建提供程序类。我复制了框架的默认提供程序 (Illuminate\Auth\Passwords\PasswordResetServiceProvider),但我不得不对注册顺序和稍后检索 token 服务的方式进行一些细微修改。您还必须指定您的 PasswordBroker 的位置(在我的例子中是在\App\Services\PasswordBroker 上)

     use Illuminate\Support\ServiceProvider;
     use Illuminate\Auth\Passwords\DatabaseTokenRepository as DbRepository;
    
     class PasswordResetServiceProvider extends ServiceProvider {
    
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;
    
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerTokenRepository();
        $this->registerPasswordBroker();
    }
    
    /**
     * Register the password broker instance.
     *
     * @return void
     */
    protected function registerPasswordBroker()
    {
        return $this->app->singleton('auth.password', function($app)
        {
            // The password token repository is responsible for storing the email addresses
            // and password reset tokens. It will be used to verify the tokens are valid
            // for the given e-mail addresses. We will resolve an implementation here.
            $tokens = $app['auth.password.tokens'];
    
            $users = $app['auth']->driver()->getProvider();
    
            $view = $app['config']['auth.password.email'];
    
            // The password broker uses a token repository to validate tokens and send user
            // password e-mails, as well as validating that password reset process as an
            // aggregate service of sorts providing a convenient interface for resets.
            return new \App\Services\PasswordBroker(
                $tokens, $users, $app['mailer'], $view
            );
        });
    }
    
    /**
     * Register the token repository implementation.
     *
     * @return void
     */
    protected function registerTokenRepository()
    {
        $this->app->singleton('auth.password.tokens', function($app)
        {
            $connection = $app['db']->connection();
    
            // The database token repository is an implementation of the token repository
            // interface, and is responsible for the actual storing of auth tokens and
            // their e-mail addresses. We will inject this table and hash key to it.
            $table = $app['config']['auth.password.table'];
    
            $key = $app['config']['app.key'];
    
            $expire = $app['config']->get('auth.password.expire', 60);
    
            return new DbRepository($connection, $table, $key, $expire);
        });
    }
    
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['auth.password', 'auth.password.tokens'];
    }
    

    1. 创建类\App\Services\PasswordBroker,在那里你可以覆盖 emailResetLink(),这一步没有什么神秘的。

    2. 在 config\app.php (App\Providers\PasswordResetServiceProvider) 的提供者数组中注册新的提供者。注释掉默认的(Illuminate\Auth\Passwords\PasswordResetServiceProvider)

关于php - 如何在 PasswordBroker Laravel 5 中覆盖 reset 和 validatePasswordWithDefaults,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30290721/

相关文章:

php - 如何使用 laravel Eloquent 地从数组数据更新 sql 中的多行

c - 在 C 中覆盖 getdirentries

scala - 如何访问 Scala 中的 "overridden"内部类?

php - wkhtmltopdf 为每个创建的 pdf 写入 apache 错误日志

php - simplexml_load_file() 有多快?

php - 运行 Laravel 照亮 Laravel 之外的数据库事务

php - artisan ,在数据库中创建表

java - 多个 toString 方法?

php - Laravel 路由 : How to create a link to a PDF file

php - 在 symfony 的两个表中使用具有不同字段的非相关表进行分页