Laravel 5 Modify Mass Assignment - laravel-5

How I can change the fillable attribute of a model on the fly?
For example, I have User model with,
protected $fillable = ['name', 'email', 'password']
When updating the user, I want to exclude 'email' from mass assignment so that the email is not changed on update.

Mass assignment doesn't mean all the field listed in fillable will be auto filled.
You still have control over what to save in the table.
So if you do:
$user = User::find(1);
$user->email = 'email#emails.com';
$user->save();
Only email will be saved in the example above while name and password remains the same

Related

Save HasMany and asscoiate BelongsTo in Eloquent

There is following table structure:
Users
HasMany Pages
Pages
BelongsTo User
HasMany Notes
Notes
BelongsTo User
To create a note I do:
$note = new Note([
'page_id': $this->page->id,
'user_id': auth()->id(),
'title': 'Foobar'
]);
$note->save();
Easy. Because of mass assignment vulnerability I want to avoid having foreign keys inside fillable of the note model. The code changes to:
$note = $this->page->notes()->create([
'title': 'Foobar'
]);
$note->user()->associate(auth()->user());
$note->save();
Fuzzy. For this to work I have to make the user_id of note nullable in the migration. This feels wrong because a note should never exist without a user. How would you solve this problem?
You can do this instead:
$note = new Note([
'title' => 'your_title_here' //works if title is in the fillable attributes
]);
$note->page()->associate($this->page);
$note->user()->associate(auth()->user());
$note->save();
Here, you don't need any nullable column and there are no risks about mass assignment.
Another advantage, there is only one database query instead of two when you are doing create first then another save.

Laravel do I have to worry about mass assignment when setting field by field

I am a bit confused when it comes to laravels mass assignment.
I know that I can protect fields using:
protected $fillable = [
'username', 'email', 'password'
];
and be protected here:
$flight = App\Flight::create(Input:all);
or
$flight->fill(['name' => 'Flight 22']);
But I only create or update Models like this:
public function createUser(NewUserRequest $request, User $newUser)
{
$newUser->insertUser($request);
}
insertUser looks like this:
public function insertUser($request)
{
$newUser = $this;
$newUser->user_type = (int) $request->input('user_type');
$newUser->username = $request->input('username');
$newUser->email = $request->input('email');
if ($request->filled('password')) {
$newUser->password = bcrypt($request->input('password'));
}
if ($request->filled('facebook_id')) {
$newUser->facebook_id = $request->input('facebook_id');
}
$newUser->save();
return $newUser;
}
As you can see I always pick what fields I want to insert and what data should be inserted. So do I really need to set my $fillable when I dont use the create() or fill() methods?
The purpose of mass assignment protection is to protect developers who source model properties direct from user input, for example:
Example::create($request->input());
Without mass assignment protection a user who knows about the underlying application architecture could inject values into fields they're not expected to have access to, e.g if your User field has an is_admin value they could change their is_admin to 1 instead of 0.
Mass assignment protection is only required when working with unsanitized user input and mass assignment protection is only enabled by default when mass assigning. You have 3 options for a secure application:
Make use of mass assignment and whitelist each property in $fillable
Assign values individually so there is no mass assignment protection, e.g: $user->name = 'John Doe'
Disable mass assignment protection and do not mass assign from user input, e.g:
protected $guarded = [];
Example::create($request->only('name', 'age'));
Example::create(['name' => $request->name, 'age' => $request->age]);
You do not need need to disable mass assignment protection in your example because you are not mass assigning values, you're assigning a value to each property individually. You can determine if you are using mass assignment by asking yourself "Am I passing in an array of properties and their values?".
You can learn more about mass assignment in the Eloquent documentation.

-Laravel 5.2 insert logged in users foreign key automatically into product table when creating product

i've been working on a CRUD system lately, what i want is that when a logged in user creates a product on my website his name will automatically be inserted as a foreign key into my product table.
this is my Product model i've made for it.
//inkoopprijs = sell price
//verkoop prijs = buy price
//naam = product name
protected $fillable = ['naam', 'inkoopprijs', 'verkoopprijs','users_id','created_at', 'updated_at'];
protected $table = "product";
this is my ProductController store function
public function store(Request $request)
{
$product = Product::create($request->only(['naam', 'inkoopprijs', 'verkoopprijs', 'users_id']));
return redirect(route('product.index'));
}
You can do this with Eloquent events like so:
Product::creating(function ($product) {
$user = auth()->user();
$product->users_id = $user->id;
});
You can access the current logged in user with Auth::user(); or auth()->user();
We can also access the identifier with Auth::id();
Product::create([
'naam' => $request->get('naam'),
'inkoopprijs' => $request->get('inkoopprijs'),
'verkoopprijs' => $request->get('verkoopprijs'),
'users_id' => \Auth::id()
]);
I hope this is what you meant.
You can use users id as hidden field in the form but need to consider the security aspects of using users id in the form. It depends on where you are using. May be you can use this method is the user is already authenticated.
<input type="hidden" name="users_id" value="{{Auth::user()->id}}">

Laravel Column Manually Added Cannot be Updated

So I have been searching but I couldn't find the correct answer to this.
I have an existing User table and added a birthdate column via SQL. The column value is being retrieved through user->birthdate but I cannot seem to save the values when i assign them. Is there anything I need to update on Laravel side?
I already tried recreating the model through artisan make:model User
I can assign other values and they are being saved except for the newly added column
$user = User::find($id);
$user->birthdate = $birthdate; //NOT BEING SAVED
$user->name = $name; //VALUE IS BEING SAVED
$user->save();
Retrieving is no problem
$user = User::find($id);
echo $user->birthdate; // Echoes successfully
Any help would be greatly appreciated
In the user model you need to add birthdate to fillable array
protected $fillable = ['name', 'email', 'birthdate', 'password'];

Mass assignment enter value in guarded field

Is it possible to fill a guarded field with the ::create method from Elequent models,
If my User model is like so:
$guarded=['password','id']
$fillable=['username']
Is it possible to do this?
User::create(['username'=>'mynewusername','password'=hash::make($password)])
No - you cannot do that.
But you could do this
$user = User::create(['username'=>'mynewusername']);
$user->password = Hash::make($password);
$user->save();

Resources