How to generate and set username in Laravel eloquent? - php

I have some fields in user table:
id firstName lastName userName
Here I need to generate and save an userName automatically where the user will provide only firstname & lastName. I have tried something like this but not sure about the piece of code.
User.php
class User extends Authenticatable{
...
protected $appends = ['firstName', 'lastName', 'userName'];
protected $attributes = ['userName' => 'default'];
public static function boot()
{
parent::boot(); // TODO: Change the autogenerated stub
self::creating(function ($model) {
$randNum = rand(10, 99);
$userName = $model['firstName'] . $model['lastName'] . $randNum;
$model->userName = $userName;
});
}
}
So whenever I'm trying to migrate & seed it's showing
Field 'userName' doesn't have a default value
The seeder is
public function run()
{
DB::table('users')->insert([
'firstName' => 'Osman',
'sureName' => 'Rafi',
'email' => 'rafi.ogchy#gmail.com',
'password' => Hash::make('password'),
]);
}

What you're looking for is Model events.
First define a static boot method on your model. In there you can then run your username generation code.
class User extends Model
{
public static function boot()
{
parent::boot();
self::creating(function($model){
$randNum = rand(10, 99);
$userName = $model['firstName'] . $model['lastName'] . $randNum;
$model['userName'] = $userName;
});
}
}
This will intercept the creation of your model, and generate the username.

setUserNameAttributes function only works when you set username to model, not works automatically
you need to define setFirstNameAttribute function and inside it generate your username
Note: last word in function name is Attribute not Attributes*

Related

How to insert to database user with default value?

I want to register user and I have 3 fields in form; login, password and confirm_password. In database I have column login, password and role. So I want to insert database user which have default role User. This oode below show me error SQLSTATE[HY000]: General error: 1364 Field 'role' doesn't have a default value. How can I resolve this problem ?
You need to add/modify the Role column with your SQL Client, chances are you have not defined a default value to it, and the column is a "Not Null" one meaning you can't insert a row if this column is empty.
Another option is to have something like that with your create function :
$user = User::create([
'login' => $data['login'],
'password' => Hash::make($data['password']),
'role' => "User"
]);
If you create users only with role "User" you can add this line when you create user;
protected function create(array $data)
{
$user = User::create([
'login' => $data['login'],
'password' => Hash::make($data['password']),
'role'=>"User"
]);
$user->assignRole('role');
return $user;
}
Or you can use Observer:
class UserObserver
{
/**
* Handle the "User" created event.
*
* #param User $user
* #return void
*/
public function creating(User $user)
{
if (is_null($user->role)) {
$user->role= "User";
$user->save();
}
}
}
Controller Logic:
$user = User::create([
'login' => $request->login,
'password' => Hash::make($request->password)]);
Model Logic if you want to insert default value
class User extends Model
{
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->role='user';
});
}
}

How add to database hash password in Laravel?

I make validation form registration using Laravel 9 and now I want to add correct data to database. This is my code in controller
public function store(RegistrationRequest $request)
{
return redirect(
route(
'index.store',
['registration' => User::create($request->validated())]
)
);
}
But my problem is that I want to insert to database hash password. In model I have function which hash password but I don't know how to insert to database.
class User extends Model
{
use HasFactory;
protected $fillable = [
'login', 'password', 'email'
];
public function opinions()
{
return $this->hasMany(Opinion::class);
}
public function setPassword($value)
{
$this->attributes['password'] = bcrypt($value);
}
}
I will gratefull if some help me how resolve this problem.
Since you are using laravel 9 you have two option to store hashed password .Add this mutator in model
protected function password(): Attribute
{
return Attribute::make(
set: fn($value) => bcrypt($value),
);
}
Ref :defining-a-mutator
or older way is
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
Ref: Defining A Mutator

Larvel model to not auto generated Id if id is provided

Newbie question here,
I'm having an employee/profile model, where I have a boot function to create a user on the creation of the employee model.
public static function boot()
{
parent::boot();
static::created(function($model)
{
$User = new \App\Models\User;
$User->id = $model->id;
$User->name = $model->first_name.' '.$model->last_name;
$User->email = $model->work_email;
$User->save();
});
while checking the DB i notice it's not picking the employee ID (UUID) and saving the same id as user ID
$User->id = $model->id;
what I'm doing wrong here ?
i have found that i can update it after saving
by adding
public static function boot()
{
parent::boot();
static::created(function($model)
{
$User = new \App\Models\User;
$User->id = $model->id;
$User->name = $model->first_name.' '.$model->last_name;
$User->email = $model->work_email;
$User->save();
$User->id = $model->id;
$User->save();
});
}
is there is way to do it without saving two times?
You are fundamentally misunderstanding how database relations should be created. You do not indicate that two entries are related by giving them the same ID.
You do it by creating a foreign key between the two tables in your migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->foreignId('employee_id')->constrained('employees');
$table->string('name');
$table->string('email');
});
}
And then creating a relationship in your ORM.
class User extends Authenticatable {
public function employee() {
return $this->belongsTo(Employee::class);
}
}
class Employee extends Model {
public function user() {
return $this->hasOne(User::class);
}
}
And then your event handler looks like this:
public static function boot()
{
parent::boot();
static::created(function ($model) {
$u = User::make([
'name' => $model->first_name . ' ' . $model->last_name,
'email' => $model->work_email,
]);
$u->employee = $model;
$u->save();
});
}
Now you have related user to employee, such that you can do things like this:
$user = User::find(123);
echo $user->employee->first_name;
Try using forceCreate(...) instead.
Save a new model and return the instance. Allow mass-assignment.
\App\Models\User::forceCreate([
"id" => $model->id,
"name" => $model->first_name . ' ' . $model->last_name,
"email" => $model->work_email,
]);
Addendum
Alternatively, you may use forceFill(...)
Fill the model with an array of attributes. Force mass assignment.
(new \App\Models\User)->forceFill([
"id" => $model->id,
"name" => $model->first_name . ' ' . $model->last_name,
"email" => $model->work_email,
])->save();
If you create a new user, you shouldn't add id. If you want to update an existing user, you should use for example find instead of creating a new model object

Laravel 5.2 - Using SetIdAttribute() Mutator To Set Other Value

I am currently creating a blog where each Post row in my database will have a unique hash attribute that is based of the post's id (incrementing, always unique).
This my Post model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Hashids;
class Post extends Model
{
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
if (! $this->exists) {
$this->attributes['slug'] = str_slug($value);
}
}
public function setIdAttribute($value) {
$this->attributes['id'] = $value;
$this->attributes['hash'] = Hashids::encode($value);
}
}
When I run this factory
$factory->define(App\Post::class, function (Faker\Generator $faker) {
return [
'title' => $faker->sentence(mt_rand(3, 10)),
'content' => join("\n\n", $faker->paragraphs(mt_rand(3, 6))),
'author' => $faker->name,
'category' => rand(1, 20),
];
});
The setIdAttribute($value) function is getting called, but my hash attribute is not being set. I am not sure if it is getting overwritten or what.
If I move the line
$this->attributes['hash'] = Hashids::encode($value);
to the function
public function setTitleAttribute($value)
and encode the title attribute it works fine, but I want to encode the 'id' attribute. Any idea how I would do this?
You can add the following to your model:
/**
* Events
*/
public static function boot()
{
parent::boot();
static::created(function($model)
{
$model->hash = Hashids::encode($model->id);
$model->slug = str_slug($model->title);
}
}
It's likely setIdAttribute($value) isn't being called until after the insert runs because it doesn't know the ID until then.
The real issue is you can't set a hash of the id in the same query because the id isn't going to be known (assuming it's auto_incrementing) until after the insert.
Because of this, the best you can probably do here is fire some code on the model's saved event.
In that model, you can probably do something like...
public static function boot()
{
parent::boot();
static::flushEventListeners(); // Without this I think we have an infinite loop
static::saved(function($post) {
$post->hash = Hashids:encode($post->id);
$post->save();
});
}

How to create new user in Laravel?

I created the model:
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class ClientModel extends Eloquent implements UserInterface, RemindableInterface {
protected $connection = 'local_db';
protected $table = 'administrators';
protected $fillable = ['user_id'];
public function getAuthIdentifier()
{
return $this->username;
}
public function getAuthPassword()
{
return $this->password;
}
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
public function getReminderEmail()
{
return $this->email;
}
}
When I try to use it like this:
ClientModel::create(array(
'username' => 'first_user',
'password' => Hash::make('123456'),
'email' => 'my#email.com'
));
It creates empty entry in DB...
I think you make it too complicated. There is no need to make it this way. By default you have User model created and you should be able simple to create user this way:
$user = new User();
$user->username = 'something';
$user->password = Hash::make('userpassword');
$user->email = 'useremail#something.com';
$user->save();
Maybe you wanted to achieve something more but I don't understand what you use so many methods here if you don't modify input or output here.
You are using create method (Mass Assignment) so it's not working because you have this:
// Only user_id is allowed to insert by create method
protected $fillable = ['user_id'];
Put this in your model instead of $fillable:
// Allow any field to be inserted
protected $guarded = [];
Also you may use the alternative:
protected $fillable = ['username', 'password', 'email'];
Read more about Mass Assignment on Laravel website. While this may solve the issue but be aware of it. You may use this approach instead:
$user = new User;
$user->username = 'jhondoe';
// Set other fields ...
$user->save();
Nowadays way :
User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
or even:
$arrLcl = [];
$arrLcl['name'] = $data['name'];
$arrLcl['email'] = $data['email'];
$arrLcl['password'] = $data['password'];
User::create($arrLcl);

Categories