Martin Martin - 1 month ago 8
PHP Question

Bind doesn't work on User model

I have an interface called TFA and a implementation called GoogleTFA. But everytime that I try to use TFA on my User model I get this error:


Type error: Argument 1 passed to App\Models\User::toggleTFA()
must implement interface App\Contracts\TFA, none given


This is my method:

public function toggleTFA(TFA $tfa)
{
/**
* If we're disabling TFA then we reset his secret key.
*/
if ($this->tfa === true)
$this->tfa_secret_key = $tfa->getSecretKey();

$this->tfa = !$this->tfa;
$this->save();
}


and this is my bind on AppServiceProvider.php:

public function register()
{
/**
* GoogleTFA as default TFA adapter.
*/
$this->app->bind('App\Contracts\TFA', 'App\Models\GoogleTFA');
}


Any idea why I'm having this behaviour?. If I type hint TFA $tfa on any method of my controllers it works but I'm trying to keep my logic on models. Thanks in advance.

Answer

DI won't work for every method. Controllers methods will use this as Laravel resolves them for you.

One way to get this to work in your model would be to resolve it manually:

$tfa = app(TFA::class);

If you're using this in a few different methods I would move the above to it's own method.

Alternatively, you could create a Facade specifically for your TFA implementation (the below example is assuming you'll be just placing your facades in your App namespace):

Create the file app/Facades/Tfa.php and add the following to it:

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Tfa extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'App\Contracts\TFA';
    }

}

Then in your config/app.php add the following to the aliases array at the bottom:

 'Tfs' => App\Facades\Tfs::class,

This way you can just call getSecretKey from the Facade:

public function toggleTFA()
{
    /**
     * If we're disabling TFA then we reset his secret key.
     */
    if ($this->tfa === true)
        $this->tfa_secret_key = Tfa::getSecretKey();

    $this->tfa = !$this->tfa;
    $this->save();
}

Hope this helps!