Type error: Argument 3 passed to App\Http\Middleware\UserAuthMiddleware::handle() must implement interface App\Contracts\UserAuth, none given, called in C:\wamp64\www\laravel\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php on line 148
I'm getting this error from inside a middleware, but when I'm use the given contract in my controllers, it works just fine. Does anyone have a clue what is happening?
Middleware file
namespace App\Http\Middleware;
use Closure;
use App\Contracts\UserAuth;
class UserAuthMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next, UserAuth $user)
{
return $next($request);
}
}
UserAuth service file
<?php
namespace App\Services;
use App\UsersModel;
class UserAuth implements \App\Contracts\UserAuth
{
public $username;
public $password;
public $perm_level = "admin";
public $guest = true;
public function load()
{
if (session()->has("user"))
{
$user = UserModel::where([
"username" => session("user"),
"password" => session("password")
])->first();
$this->username = $user->username;
$this->password = $user->password;
$this->guest = false;
}
}
public function isLogged()
{
return $this->guest;
}
}
AppServiceProvider register
public function register()
{
$this->app->singleton(\App\Contracts\UserAuth::class, \App\Services\UserAuth::class);
}
Routes
//REGISTRATION ROUTES
Route::get("/register", "User@register")->middleware("user_auth");
Route::post("/register", "User@save_user")->middleware("user_auth");
User controller with working contract
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\UsersModel;
use App\Contracts\UserAuth;
class User extends Controller
{
public function register(Request $request, UserAuth $user)
{
return view("registration.form", ["request" => $request]);
}
public function login(Request $request)
{
$user = UsersModel::where([
"username" => $request->username,
"password" => $request->password
])->first();
if ($user)
{
session(["user" => $user->username, "password" => $user->password]);
return back();
}
else return back()->with("login_attempt", "failed");
}
public function logout()
{
session()->forget("user", "password");
return back();
}
public function save_user(Request $request)
{
$errors = [];
//Data validation
$input = $request->all();
if ( in_array(null, $input) )
$errors["empty_fields"] = true;
if ( !preg_match("/[A-Za-z0-9 ]{3,16}/", $input["username"]) )
$errors["invalid_username"] = true;
if ( $input["password"] != $input["password_confirm"] )
$errors["unmatching_passwords"] = true;
if ( !preg_match("/[A-Za-z0-9\-\.]{3,16}@[A-Za-z0-9](\.[a-z0-9]){1,2}/", $input["email"]) )
$errors["invalid_email"] = true;
if ( UsersModel::where("username", $input["username"])->first() )
$errors["username_taken"] = true;
if (count($errors) > 0) return view("registration.form", ["err" => $errors, "request" => $request]);
else return view("registration.save", ["request" => $request]);
}
}
You are incorrectly trying to pass an ad-hoc paramter to the handle function in your middleware parameter.
When you define this:
public function handle($request, Closure $next, UserAuth $user)
That means that the middleware is expecting a parameter to be passed in there, it will not come from DI Container, hence the $user variable is null, failing to pass the type-hint constraint.
The parameters that are allowed here are only for "roles", you cannot pass something random and expect the DI container to resolve it.
I would suggest you try something like this instead:
public function handle($request, Closure $next)
{
if($request->user()->isLogged()) {
return $next($request);
} else {
return redirect('login'); // or whatever route
}
}
For this to work, you would need to define the isLogged
function as part of a Trait, that you would add to you App\User
model.
Please see:
https://laracasts.com/discuss/channels/laravel/pass-variable-from-route-to-middleware
https://laravel.com/docs/5.4/middleware#middleware-parameters