I get a 404 error when I try to insert user's details into multiple tables during registration
my user model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
class User extends Authenticatable
{
use Notifiable;
use HasRoles;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username','accno', 'email', 'password', 'role', 'status', 'activation_code'
];
protected $guarded = [];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
// a mutator for the email attribute of our model with email validation check and check to avoid duplicate email entries.
protected $table = 'users';
public $timestamps = false;
public $incrementing = false;
public function setEmailAttribute($email)
{
// Ensure valid email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \Exception("Invalid email address.");
}
// Ensure email does not exist
elseif (static::whereEmail($email)->count() > 0) {
throw new \Exception("Email already exists.");
}
$this->attributes['email'] = $email;
}
public function setPasswordAttribute($password)
{
$this->attributes['password'] = Hash::make($password);
}
public function profiles()
{
return $this->hasOne(profiles::class);
}
public function accounts()
{
return $this->hasOne(accounts::class);
}
public function transactions()
{
return $this->hasMany(transactions::class);
}
}
I try refactoring by separating my validation code from my logic using RegisterUserTrait
<?php
namespace App\Traits;
use App\User;
use App\Profile;
use App\Account;
use Keygen;
trait RegisterUser
{
public function registerUser($fields)
{
$user = User::create([
'username' => $fields->username,
'accno' => $this->generateAccountNumber(),
'email' => $fields->email,
'password' => $fields->password = bcrypt(request('password')),
'roles' => $fields->roles,
'activation_code' => $this->generateToken()
]);
Profile::create([
'accno' => $user->accno,
'username' => $user->username,
'acc_type' => $fields->acc_type,
'firstname' => $fields->firstname,
'lastname' => $fields->lastname,
'nationality' => $fields->nationality,
'occupation' => $fields->occupation,
'address' => $fields->address,
'city' => $fields->city,
'state' => $fields->state,
'zipcode' => $fields->zipcode,
'phoneno' => $fields->phoneno,
'dob' => $fields->dob,
'gender' => $fields->gender,
'martial_status' => $fields->martial_status,
'user_image' => $fields->user_image,
]);
Account::create([
'accno' => $user->accno,
'username' => $user->username,
]);
return $user;
}
then storing the data using my registrationController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Http\Requests\RegistrationRequest;
use App\Traits\RegisterUser;
class RegistrationController extends Controller
{
use RegisterUser;
public function show()
{
return view('auth/register');
}
public function register(RegistrationRequest $requestFields)
{
//calling the registerUser method inside RegisterUser trait.
$user = $this->registerUser($requestFields);
return redirect('/login');
}
}
but when I register the user, the data is only saved in the create_user_table and return a 404 page not found error. How can I save the data to the selected table and redirect to the login page?
As fa as i can see this is not true for foreign key relations in User Model
public function profiles()
{
return $this->hasOne(profiles::class);
}
public function accounts()
{
return $this->hasOne(accounts::class);
}
public function transactions()
{
return $this->hasMany(transactions::class);
}
it should be as follows;
public function profiles()
{
return $this->hasOne(Profile::class);
}
public function accounts()
{
return $this->hasOne(Account::class);
}
public function transactions()
{
return $this->hasMany(Transaction::class);
}
Try this
public function registerUser($fields)
{
$user = User::create([
'username' => $fields->username,
'accno' => $this->generateAccountNumber(),
'email' => $fields->email,
'password' => $fields->password = bcrypt(request('password')),
'roles' => $fields->roles,
'activation_code' => $this->generateToken()
]);
$user->userprofile =Profile::create([
'accno' => $user->accno,
'username' => $user->username,
'acc_type' => $fields->acc_type,
'firstname' => $fields->firstname,
'lastname' => $fields->lastname,
'nationality' => $fields->nationality,
'occupation' => $fields->occupation,
'address' => $fields->address,
'city' => $fields->city,
'state' => $fields->state,
'zipcode' => $fields->zipcode,
'phoneno' => $fields->phoneno,
'dob' => $fields->dob,
'gender' => $fields->gender,
'martial_status' => $fields->martial_status,
'user_image' => $fields->user_image,
]);
$user->useraccount = Account::create([
'accno' => $user->accno,
'username' => $user->username,
]);
return $user;
}
If you are using a voyager package then there is a log file where you will find error messages that can help you understand the exact problem .
the log interface existe in voyager admin panel in :
Tools => Compass => Logs
look at this image :
Try this in your User model
protected static function boot()
{
protected static function boot()
parent::boot();
static::created(function ($user){
$user->profiles()->create([
'accno' => $user->accno,
'username' => $user->username,
.... => ....
]);
$user->accounts()->create([
'accno' => $user->accno,
'username' => $user->username,
]);
});
}
An error 404 is often a problem with a route.
As requested by Christos Lytras in a comment, we need to see your routes/web.php and the output of php artisan route:list to verify.
I believe the redirect in your registrationController is not pointing to a valid url:
return redirect('/login');
Without seeing your routes I can't say for sure but if your login route name is defined, you can do:
return redirect()->route('login');
Please share your routes file to confirm.
create() method is used for mass assignment. you will need to specify either a fillable or guarded attribute on the model. So check the fillable attribute on Profile and Account Model.
Related
thanks for helping
I have some error when insert data i nto database, that is guard does not exit when I try to register by using this controller
namespace App\Http\Controllers;
use App\Models\MemberExtra;
use App\Models\User;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered;
class RegisterController extends Controller
{
public function __construct()
{
$this->middleware('guest');
}
public function index(){
return view('users.register');
}
protected function validator(array $data)
{
return Validator::make($data, [
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'referrer_id' => 'required',
'position' => 'required',
'username' => 'required',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$ref_id = $data['referrer_id'];
$poss = $data['position'];
$posid = getLastChildOfLR($ref_id,$poss);
return User::create([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'referrer_id' => $data['referrer_id'],
'position' => $data['position'],
'username' => $data['username'],
'join_date' => Carbon::today(),
'posid' => $posid
]);
}
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
MemberExtra::create([
'user_id' => $user['id'],
'left_paid' => 0,
'right_paid' => 0,
'left_free' => 0,
'right_free' => 0,
'left_bv' => 0,
'right_bv' => 0,
]);
updateMemberBelow($user['id'], 'FREE');
return $this->registered($request, $user) ?: redirect()->route('home');
}
}
when register , show this error
and I refresh the page , user data is inserted into database but MemberExtra data still not insert
And this guard does not exist error happen again and again whenever register.
How can fix this error
Can someone help me
In your controller I didn't see the RegistersUsers trait which have guard function.
You have missed to write below in your controller. By default this function exist in RegistersUsers this trait
/**
* Get the guard to be used during registration.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard('your guard name');
}
Modify my registration blade. I added 2 additional functions that trigger the registration of the user. The data I needed are being saved to the appropriate tables but I am having this error,
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must
implement interface Illuminate\Contracts\Auth\Authenticatable, boolean
given, called in
E:\wamp64\www\aftscredit-appzcoder\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RegistersUsers.php
on line 35
Here's my Registration controller
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Referral;
use App\CollectorMember;
use App\HasRoles;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest');
}
public function index(Request $request)
{
$referral = '';
$keyword = $request->get('search');
$referral = Referral::where([
['code', $keyword],
['status', 0]
])->first();
if (is_null($keyword))
return view ( 'Auth.register');
elseif ($referral)
return view ( 'Auth.register', compact('referral', $referral))
->withDetails ( $referral )
->withQuery ( $keyword );
else
return view ( 'Auth.register')->withMessage ( 'The code you provided is not EXISTING or not AVAILABLE.' );
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$user_id = $user->id;
Referral::find($data['referral_id'])->update ([
'status' => 1,
'date_used' => $data['referral_date_used']
]);
return CollectorMember::create ([
'collector_id' => $data['referral_generate_by'],
'borrower_id' => $user_id,
'referral_id' => $data['referral_id'],
]);
}
}
What's causing this? thanks in advance!
Try opening the RegistersUsers trait and look at line 35. A user is not being created.
The original Laravel controller code to create a user is as follows:
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
Note how the DocBlock indicates an instance of User must be returned. This is key because the the actual code that completes the registration, within the trait, assumes a a valid User model instance.
It's sometimes helpful to step through the code and understand what Laravel is doing for you, behind the scenes.
I'm using the default laravel authentication. Every user who registeres in my site needs a activation pin. The valid PINs are stored in a different table. Whenever a user registeres, I want to test if the PIN is valid or not. So, is there any method that I can override in RegisterController that executes before regstering the user?
Yes. You can override protected register method in RegisterController. This is a simple solution. I do this to validate params, save a new user, and force return JSON in one of my projects.
For example:
protected function register(Request $request)
{
$validator = Validator::make($request->all(), [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|unique:users',
'phone' => 'required',
'pin' => 'required'
]);
//Check your PIN here, if it's wrong, append errors array
if ($validator->fails())
throw new ValidationFailed($validator->errors());
User::create([
'first_name' => $request->input('first_name'),
'last_name' => $request->input('last_name'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
]);
return ResponseJSON::make(trans('responses.registered'));
}
You can add a validation rule for validating the pin in the validator method like this :
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'pin' => [
'required',
Rule::exists('pins')->where(function ($query) {
$query->where('Some condition');
}),
],
]);
}
I assume you have a table for pins called pins
extend the register function in user class:
public function register(Request $request)
{
event(new \App\Events\NewUserRegistered(Auth::user()));
return redirect($this->redirectPath());
}
NewUserRegistered:
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class NewUserRegistered extends Event
{
use SerializesModels;
public $userID;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $userID)
{
//get whatever is massed in here's value in the id column
$this->id = $userID;
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return [];
}
}
Hello everyone who's trying to help,
im trying to create the factory file to seeding my database and i have a question how can i insert a foreign key from a table already seeded ?
and the factory code is to have all in same file? any good pratice to this ?
Files
Model User
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $table = 'user'; //name of the table in database
protected $primaryKey = 'Id'; //Primary Key of the table
/**
* Relations between tables
*/
public function GetLoginInfo()
{
return $this->hasMany('App\Models\LoginInfo', 'UserId');
}
public function getStatus()
{
return $this->belongsTo('App\Models\AccountStatus');
}
}
Model Account status
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AccountStatus extends Model
{
protected $table = 'account_status'; //name of the table in database
protected $primaryKey = 'Id'; //primary Key of the table
public $timestamps = false; //true if this table have timestaps
/**
* Relations between tables
*/
public function GetUsers()
{
return $this->hasMany('App\Models\Users', 'StatusId');
}
}
factory file:
<?php
/** #var \Illuminate\Database\Eloquent\Factory $factory */
//Factory for Account Status table
$factory->define(App\Models\AccountStatus::class, function (Faker\Generator $faker) {
return [
'Description' => $faker->word,
];
});
//Factory for user table
$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
return [
'Username' => $faker->unique()->userName,
'Password' => bcrypt('test'),
'Email' => $faker->unique()->safeEmail,
'Name' => $faker->name,
'StatusId' => Factory(App\Models\AccountStatus::class)->create()->id,
];
});
This is what im trying to do as you can see : Factory(App\Models\AccountStatus::class)->create()->id but don't work
$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
return [
'Username' => $faker->unique()->userName,
'Password' => bcrypt('test'),
'Email' => $faker->unique()->safeEmail,
'Name' => $faker->name,
'StatusId' => factory(App\Models\AccountStatus::class)->create()->id,
];
});
i see an uppercase F in factory..
$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
$accountStatus = factory(App\Models\AccountStatus::class)->create()
return [
'Username' => $faker->unique()->userName,
'Password' => bcrypt('test'),
'Email' => $faker->unique()->safeEmail,
'Name' => $faker->name,
'StatusId' => $accountStatus->id,
];
});
Edit (Improvement)
If you have one model that depend on another model. you can do it this way, using a callback function to create with the related.
Like this
$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
return [
'Username' => $faker->unique()->userName,
'Password' => bcrypt('test'),
'Email' => $faker->unique()->safeEmail,
'Name' => $faker->name,
'StatusId' => function () {
return factory(App\Models\AccountStatus::class)->create()->id;
}
];
});
One thing you need to keep in mind is that this will go to an endless loop if the related(Status Model) has a model that depends on the parent(User Model).
I am using Laravel 4.2 and I'm trying to auth my own model (I don't use User model).
The problem appears when pass the mail and password, then I use the method Auth::attempt and enters to else (that it corresponds to the error)
Usuario Controller
class UsuarioController extends BaseController{
function doLogin(){
$userdata = array(
'Correo' => Input::get('correo'),
'Contrasena' => Input::get('contrasena')
);
if(Auth::attempt($userdata)){
echo 'SUCCESS!';
}else{
echo 'Error!';
}
} ...
Usuario Model
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Usuario extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'Usuario';
protected $primaryKey = 'idUsuario';
protected $fillable = array(
'Nombre',
'Apellido',
'Rol',
'Correo',
'Contarsena',
'Cumpleanos',
'Foto',
'Pais',
'Comuna',
'Profesion_idProfesion',
'Institucion_idInstitucion',
'remember_token'
);
function profesion(){
return $this->belongsTo('Profesion', 'idProfesion');
}
public function getPasswordAttribute()
{
return $this->Contrasena;
}
public function setPasswordAttribute($Contrasena)
{
$this->Contrasena= $Contrasena;
}
public function getReminderEmail()
{
return $this->Correo;
}
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword() {
return $this->Contrasena;
}
}
Auth.php
return array(
'driver' => 'eloquent', //database or eloquent
'model' => 'Usuario',
'table' => 'Usuario',
'username' => 'Correo',
'password' => 'Contrasena',
'reminder' => array(
'email' => 'emails.auth.reminder',
'table' => 'password_reminders',
'expire' => 60,
),
);
Usuario Table
The application never crash but in the If Condition always enter to the ''else'' returns Error!
You have a typo in your fillable array:
protected $fillable = array(
'Nombre',
'Apellido',
'Rol',
'Correo',
'Contarsena',
'Cumpleanos',
'Foto',
'Pais',
'Comuna',
'Profesion_idProfesion',
'Institucion_idInstitucion',
'remember_token'
);
Contarsena should be Contrasena
And your auth array should contain a email and password key:
$userdata = array(
'correo' => Input::get('correo'),
'password' => Input::get('contrasena')
);
try
dd(DB::getQueryLog());
to get the the SQL executed. That makes troubleshooting easier.
My guess is that there's no 'password' field, which the attempt method will automatically hash