Laravel Eloquent: How to store model values before saving? - php

I have a custom function within one of my models. It looks like this:
public function newWithTeam($data, $team_id = false){
$levels = Permissions::get_levels();
$this->email = $data['email'];
$this->password = bcrypt($data['password']);
$this->username = $data['username'];
$this->save();
$profile = new Profile(['name' => $data['name'],'bio' => $data['bio']]);
$this->profile()->save($profile);
}
Here, you can see I store the email, password and username as object properties, before hitting save()
Instead, I'd like to do this in one line, something like:
$this->store(['email' => $data['email], 'password' => $data['password], 'username' => $data['username']]);
$this->save();
I am aware that the create() method exists, but when I use this, the following line
$this->profile()->save($profile); does not work properly. I think the create() function does not work the same as save() for some reason! Is there any equivalent to the store() function as above?

You can use the fill() method to achieve what you are looking for.
But before using it, you should know a few things.
Laravel models are protected against mass-assignment by security reasons, to use the fill() method you will need to define what properties of your model can be filled using the fillable or the guarded properties.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserModel extends Model
{
protected $fillable = ['email', 'password', 'username'];
public function newWithTeam($data, $team_id = false){
$levels = Permissions::get_levels();
$this->fill([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'username' => $data['username']
]);
$this->save();
$profile = new Profile([
'name' => $data['name'],
'bio' => $data['bio']
]);
$this->profile()->save($profile);
}
}
The fillable property functions like a white-list for mass-assignment. If you want the other way, you can use the guarded property that will function like a black-list. Which means that every column listed within the guarded property will not be available for mass-assignment and everything else will, it's your choice.
About your last statement, if you look at the implementation of the create() method you will find that it accepts a regular php array, while the save() method will accept an Eloquent Model instance. That's why create() will not work receiving your $profile variable.
I hope this helps.

The method that You're looking for is fill:
$this->fill([
'email' => $data['email'],
'password' => $data['password'],
'username' => $data['username']]
);
$this->save();
You can use it for both creating and updating.

You can use fill directly:
$this->fill($data);
$this->save();
It will use the array keys as object attributes, so make sure you'll use the same.
Also, make sure you have set the $fillable in your model (http://laravel.com/docs/eloquent#mass-assignment):
class x extends Eloquent {
protected $fillable = ['email','password','username'];
...
}

I'm not 100 % sure I understood you correctly, but it sounds like you want to make a oneliner update without screwing up the profile creation. In that case, you can simply use the update() method:
$this->update(['email' => $data['email], 'password' => bcrypt($data['password]), 'username' => $data['username']]);
That saves the new values for you.

So what happens when you run $this->create()? Are you getting an error?
Consider that create() will return the new object that you created so you could try:
$user = $this->create([
'email' => $data['email],
'password' => $data['password],
'username' => $data['username']
]);
$user->profile()->create([
'name' => $data['name'],
'bio' => $data['bio']
]);
Didn't test this so see how you get on and leave a comment if you have any further issues. Happy coding!

Related

How to obtain the user model's attributes in Laravel via class accessor

I am trying to create a customer at the same time as a user is created in the RegisterController (part of the Laravel Auth package), if that user registers as a customer. However, I have tried adding an 'accessor' to the User class by adding the following code to my User model, to access the user_id property, but the accessor does not seem to work as intended. (SEE: https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor)
public function getUserIdAttribute($user_id)
{
return $user_id;
}
Then I try to access it directly from the model in the RegisterController with this function:
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'utype' => $data['utype'],
]);
if ($data['utype'] == "customer") {
Customer::create([
'user_id' => $user->user_id,
]);
}
return $user;
}
For some reason, the $user->user_id returns NULL though. What is the issue? Why is the accessor not being applied properly?
With the help of #lagbox, I figured out what the issue was. Turns out, the column name was simply 'id'.

Create customer on laravel registration

All I want to do is to create a stripe customer account for every registered user on Laravel.
The problem I'm facing right now is that $new variable isn't passing to User::create function.
I'm trying to edit RegisterController.php, here is create() function I'm using:
public function create(array $data)
{
\Stripe\Stripe::setApiKey('sk_test_XXXXXXXXXXXXXXX');
$new = \Stripe\Customer::create([
'email' => $data['email'],
'name' => $data['name'],
'description' => "Contribee.com platform's user",
]);
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'stripe_code' => $new->id,
'password' => Hash::make($data['password']),
]);
}
I've tested this out in my other controller, and $new outputs generated ID. Everything worked fine.
https://laravel.com/docs/6.x/eloquent#mass-assignment
You may also use the create method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment by default.
Anything not permitted as fillable gets discarded.

Laravel 5 two questions

I'm laravel newbie and I have 2 questions:
1. How to set "From:" who in password reminder sent? Because nothing prints now:
2. How to insert custom value when registering?
I'm tried in AuthController but 0 emotions, nothing inserts:
Default:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
I' tried but not works:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'seo_name' => str_slug($data['name']),
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
But nothing happened. Why? Thanks in advance ;)
P.S I have seo_name row in PhpMyAdmin and I want when registration successfull insert for example:
name - Custom Name
seo_name - custom-name (str_slug function makes that string, but IDK how to insert..)
How to set "From:" who in password reminder sent? Because nothing prints now
In Laravel, you can make use of the SwiftMailer library by using the Mail class. This will give you access to commands such as $message->from('youremail#emailaddress.com', 'Firstname Lastname');
Here's an example -
Mail::send('emails.emailview', $data, function($message) {
$message->from('youremail#emailaddress.com', 'Firstname Lastname');
$message->to('to#emailaddress.com')->cc('anotherperson#emailaddress.com');
});
How to insert custom value when registering?
You'll have to update your User model with the new field in the $fillable property. This should reflect the name of the table that you've added for the new field.
class User extends Eloquent {
protected $guarded = array('id', 'password');
protected $fillable = array('name', 'seo_name', 'email');
}
for inserting the custom value the above mentioned method $fillable is required.Put $fillable on to your model and add the fields are to be needed to insert.
eg.
$this->db->table('tb_name')->create([name => $value,
address => $val,
...
]);
then you add protected $fillable = array('name', 'address', ...);

Laravel5 : Calling a static method on eloquent model not working

I have a static method in User model.
namespace Tol;
...
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
...
public static function signup(array $data)
{
$user = new User([
'email' => $data['email'],
'password' => Hash::make($data['password']),
'username' => $data['username'],
'type' => $data['type'],
]);
$user->save();
if ($user && $user->id) {
$profile = new UserProfile([
'first_name' => trim($data['first_name']),
'last_name' => trim($data['last_name']),
'gender' => $data['gender'],
]);
$user->profile()->save($profile);
EmailVerification::sendTo($user, 'signup');
}
return $user;
}
...
}
And I'm trying to call call this method simply from my controllers.
like this
$user = User::signup($input);
And it throws error like this:
I don't know why it is referring it as a method on the Builder class. The code is very simple and everything was working when it was Laravel 4.
Please help.
thanks
your code should have no problem, im afraid the problem is in your auth.php file, please ensure
'model' => 'App\User',
is set it to your model file in your case
'model' => 'Tol\User',
and to ensure your calling the right file you might want to give this a try
\Tol\User::signup($array);

Laravel model inheritance

I am using the Toddish/Verify library for Laravel as it includes 99% of what I need for my project. All I need is to add some fields.
I have added them in a migration, and I want to add them also to mass creation:
use Toddish\Verify\Models\User as VerifyUser;
class User extends VerifyUser
{
public function __construct () {
array_merge ($this->fillable, array(
'salutation', 'title', 'firstname', 'lastname', 'phonenumber', 'mobilenumber'
));
}
}
However, when I run my creation test:
public function testUserCreation () {
$user = User::create(
[
'username' => 'testusername',
'email' => 'email#test.com',
'password' => 'testpassword',
'salutation' => 'MrTest',
'title' => 'MScTest',
'firstname' => 'Testfirstname',
'lastname' => 'Testlastname',
'phonenumber' => 'testPhoneNumber',
'mobilenumber' => 'testMobileNumber',
]
);
$this->assertEquals($user->salutation, 'MrTest');
$this->assertEquals($user->title, 'MScTest');
$this->assertEquals($user->firstname, 'Testfirstname');
$this->assertEquals($user->lastname, 'Testlastname');
$this->assertEquals($user->phonenumber, 'testPhoneNumber');
$this->assertEquals($user->mobilenumber, 'testMobileNumber');
}
I get this:
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 users.username may not be NULL (SQL: insert into "users" ("updated_at", "created_at") values (2014-03-03 09:57:41, 2014-03-03 09:57:41))
in all tests that involve user creation, as if it had forgotten about the parents attributes when saving the model.
What am I doing wrong?
The problem is that you're overriding what I assume is the Eloquent constructor, so the values are never getting passed.
Change __construct to look like the following.
public function __construct(array $attributes = array())
{
parent::__construct($attributes);
array_merge ($this->fillable, array(
'salutation', 'title', 'firstname', 'lastname', 'phonenumber', 'mobilenumber'
));
}
The Model::create method will actually create a new instance of the model and pass the array into the __construct. You're overriding this and preventing it from passing the information through.
Note If you decide to override core methods like you've done here, always check inheritance and make sure you aren't breaking anything.

Categories