I have run into an issue with Laravel that hopefully someone could help explain. The fill command is not setting the properties of the model, and instead can only be used to save them to the database with the ->save() function. Is there a way to do fill where it actually sets the properties of the model from an array.
Example of problem below.
$comment = new comment();
$comment->fill(['name' => 'Bob']);
echo($comment->name); // Gives null/error.
$comment = new comment();
$comment->name = 'Bob';
echo($comment->name); // Gives Bob.
The reason is name filed is not fillable in comment model .To Solve this issue you have to add fillable for that field in comment model
protected $fillable = [
'name',
];
If you try to access non fillable field then it will return null.
If don't want to add it in fillable then you can use forceFill.
forceFill: Fill the model with an array of attributes with force mass assignment.
$comment = new comment();
$comment->forceFill(['name' => 'Bob']);
echo($comment->name);
Yes, you need to use fillable property of the model and need to add name inside fillable array. That's the recommended way to do it.
As suggested by John Lobo's answer, You can forcibly override that mechanism using forceFill or forceCreate.
Both ignores fillable property in the model. It may possible that you may have a column like is_admin and you do not want to update it but force will do it.
Notes :
The main problem with forceCreate or forceFill, is that we have to manage the foreign key assignment manually.
forceFill will do fill (properties) only. You need save method call to save the actual record while forceCreate will do fill (properties) and Save both together.
Related
Laravel Model allows two functions for inserting the values to the database table. They are
Create:
User::create(['id'=>1,'name'=>'stack']);
Insert:
User::insert(['id'=>2,'name'=>'overflow']);
I found they perform similar operations. What's difference between them?
insert() :
If you using insert() method you can't default created_at and updated_at database column
it will be null
DefaultUser::insert(['username' => $request->username, 'city' => $request->city, 'profile_image' => $request->profile_image]);
create() :
when we use create method you must define this model in fillable fields
Add in Your Model
protected $fillable = ['username','city', 'profile_image'];
Add your Controller
DefaultUser::create(['username' => $request->username, 'city' => $request->city, 'profile_image' => $request->profile_image]);
then we can use create method without **mass assignment error **
basically here , table defined fields are protected in your model
you should define which model attributes you want to make mass assignable. You may do this using the $fillable property on the model
The model does not have an insert, calling Model::insert results in a call to (the Query Builder) Builder::insert through the __call() magic method which then avoids the Eloquent benefits like setting the timestamps for created_at and updated_at fields.
It also avoids the Mass-assignment protection which Eloquent protects you from inserting unintentional data.
So I would always use create or setting each field separately (if you need to modify the incoming data) and call save() on the model instance.
Insert method :
The insert method accepts an array of column names and values.using this method you can insert data without specify fillable and guarded attribute on the model and here created_at and updated_at values put as NULL value by default.
User::insert(['userName'=>'manish','email'=>'test#gmail.com']);
Create method
The create method also used to insert a new model in a single line. It's instance will return you from that method. before using create() will need to specify fillable or guarded attribute on model its protect against mass-assignment by default and its auto fillable value for create_at and updated_at
User::create(['userName'=>'manish','email'=>'test#gmail.com'])
save()
save() method is used both for saving new model, and updating existing one. here you are creating new model or find existing one, setting its properties one by one and finally saves in database.
save() accepts a full Eloquent model instance
create()
while in creating method you are passing an array, setting properties in model and persists in the database in one shot.
create() accepts a plain PHP array
I have been trying to insert data using query into two columns of a table but there's something missing that its not sending data in the other column named booking_code.
It is inserting the booking_id into the table but not booking_code.
Here is the controller:
public function store(CreatePaymentRequest $request)
{
$input = $request->all();
$booking_id = $request->booking_id;
$booking_code = Booking::find($booking_id)->booking_code;
$this['booking_code'] = $booking_code;
$payment = $this->paymentRepository->create($input);
Flash::success('Payment saved successfully.');
return redirect(route('admin.payments.index'));
}
Please have a look at the Relevant Documentation Pages
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.
That means that you have to set, in Model, which fields you will allow to be "mass-assigned".
In your case, it will looks something like
class Booking extends Model
(...)
{
protected $fillable = ['booking_code', (...)];
}
(...)
In the code you provided though, I can't see how you build an $input variable so maybe the issue is there? Maybe it's just some typo.
I am using laravel 5.3 and in my custom model, I have some guarded fields like following.
protected $guarded = ['id', 'tnant_id', 'org_id', 'fac_id', 'slug', 'created_at', 'updated_at', 'deleted_at'];
Now When I try to add record using following.
CUSTOM::create(['tnant_id'=>123]);
It returns me following error.
Field 'tnant_id' doesn't have a default value.
Setting field default value in table will not work because each time I am passing value and it is giving error for all guarded fields.
So how I can add guarded fields value in database? In update query, It is allowing to update but on create it gives error.
You simply can't. Model::create(array $attributes = []) is using method fill(array $attributes = []), which, we may say, filter out all guarded attributes, so they will not be assigned. So in point of creation tnant_id will be null.
I come up with two ways of doing this:
A
create a new model instance
set your attribute
save (persist) it to dabase;
So:
$model = new Model;
$model->tnant_id = 123;
$model->save();
B
This is more likely update than create, but, might be useful for you.
Change your DB schema to allow null values for your attribute or put default value.
create model using Model::create()
set attribute & update.
So:
Assuming you are using migrations, in your migration file use:
Schema::create(..
$table->integer('trant_id')->nullable();
//OR
$table->integer('trant_id')->default(0);
...);
Note: It's hard to say which one is more suitable for you use-case, but I see your attribute is called trant_id, which is some form of relation I guess, so I suggest you to take look at Eloquent's relationship, which might be a better answer.
I have removed an element from the mass assignment array.
protected $guarded = ['id', 'status', 'org', 'params', 'last_visited_date'];
Because admin users need to be able to update the user model/record.
However now a user could pass through the element in a form and overwrite a field, this is undesirable.
What's the best way to tackle mass assignment on the mentioned user model?
Hopefully i dont have to have 2 user models?
Looks like i can just manually input
$input = $request->all();
$user->activation = $input['activation'];
$user->save();
When I try to persist form data, Laravel is throwing a mass assignment exception.
In the view I'm using {!! form::open(...) !!} which I know creates _token as a hidden field.
When the form data is sent to the controller, I'm using
$data = Input::all();
$order = Order::create($data);
$order->save();
Should I be adding a field for _token in my database? Or am I causing an error by doing something else wrong?
A mass assignment exception is usually caused because you didn't specify the fillable (or guarded the opposite) attributes in your model. Do this:
class Order extends Eloquent {
protected $fillable = ['field1', 'foo', 'bar'];
}
This way you also don't have to worry about _token because only the specified fields will be filled and saved in the db no matter what other stuff you pass to the model.
or
protected $guarded = array();
Make sure you are putting the $fillable or $guarded in the app\Order.php file and not the app\Http\Controllers\OrderController.php file.
To answer your initial question. You would want to do unset($request['_token']); before your create.