@nickywan123 i think there are no cons in using that method. Because only the properties that the model defines in $fillable can be written en masse.
When to use $request->all()?
After submitting a form, there are two ways to retrieve the input from the controller:
Using $request->all():
user()->todos()->create($request->all());
Specifying each field:
$todos = new Todos;
$todos->title = $request->input('field_1');
$todos->description = $request->input('field_2)';
......
$todos->save();
The first way obviously only requires to write one line of code but is there any pros or cons or using either way?
No cons in using which method?
I get that the second method requires more line of code written but for the first method, we won't know what input fields are coming from the HTTP request unless we do a dd().
Wouldn't the second method also checks the $fillable property to make sure there's mass assignment?
no, $fillable checks only on create method. if you fear, use like
user()->todos()->create($request->only([
'title',
'description',
'user_id'
]))
In your way, the database column name has to match with the attributes, like 'user_id' should be of same name as 'user_id' in the db right?
So if I use request input and save it manually, then what happens when the column field does not exist in the table?
If I remember, it will throw the mass assignment error too.
No cons using $request->all()
Mass assignement is only when use an array. Assigning once property at time is not "mass" assignment. That is why @trin says.
dd() is only for debugging, in production is not used.
Sorry, i dont speak english so you i cannot understand the real sense of you reply.
Okay. Because I remember when I assign the input one by one and I did not put a column in my $protected model and it still shows mass assignment error. If that makes sense.
you understood correctly, the column names must match the passed parameters from the request and when you use $request->all() or $request->only(['title', 'description', 'user_id'])
if you have different parameter names, you can use
$todo = new Todos;
$todo->title = $request->input('name');
...
or
$todo = Todos::create([
'title' => $request->input('name')
])
usualy i use construction like
$todo = Todos::create(array_merge(
$request->only(['title', 'description']),
[
'user_id' => $request->input('user')
]
))
but no problem to use $request->all(), if your db columns name match request parameters name
Okay I understood now, if I use:
$todo = new Todos;
$todo->title = $request->input('description');
...
and description exist in the database column but not in $protected = ['address'], will it still throw any sort of error?
🤦♂️
sorry 4 my english.
no, you not understood.
method create can simplify code to create new model.
$todo = new Todos;
$todo->title = 123;
$todo->description = 456;
$todo->save();
can simplified to
$todo = Todos::create(['title' => 123, 'description' => 456]);
but only if title and description exists in $fillable array of model. if in $filleable you have only title, for example, you anyway create new $todo with create method, but description will not be setted. code run with zero error.
when you use $resquest->all(), you get an array with all http parameters (get/post/etc).
in your example
$todo = new Todos;
$todo->title = $request->input('description');
you create new Todos model and set title to $_REQUEST['description']
Okay but you mentioned this
if in $filleable you have only title, for example, you anyway create new $todo with create method, but description will not be setted. code run with zero error.
I think you mean you have $fillable = ['tite', 'description']
and then you create todo with create method like
$todo = Todos::create(['title' => 123]);
then it will no show error. Is that what you mean?
i mean if you have
protected $fillable = ['title'];
and you create model by
$todo = Todos::create(['title' => 123, 'description' => 456]);
your model will be created, but description will not be setted, because desciption not in $fillable
if
protected $fillable = ['tite', 'description'];
and
$todo = Todos::create(['title' => 123]);
model will be created too and description will be setted to null. if it possible in your db.
then in which scenario above will give error??
in both, if description cant be null.and in none, if can
I usually do this:
$todo = new Todos;
$todo->title = 123;
$todo->description = 456;
$todo->save();
It will give an error if description is not a column in db or another field with description_2 which is not nullable.
there is no good EXCUSE for using $request->all()
it's just lazy
why is that?
I've seen many said it's good refactoring.
^ https://www.youtube.com/watch?v=QQS5oEOguRU
This will help explain.
So the best way is to use $request->only([....]) or manual insertion to the db?
Just out of interest - who’s saying that $request->all() is a good refactor?
Honestly, I can’t think of a situation where I would do this or where I’d approve a PR where this is being done.
To me it looks like people are suggesting this to be a proper refactor because they think that less code is always better or so...
A request should always be validated before you use any of the data on your application. That goes even if you use $fillable in your model.
No matter if you use inline validation (validation in your controller) or a form request class, after validation never use request->all()
This is a bad practice in my book
$request->validate(['title' => 'required', 'body' => 'required' ]);
Post::create($request->all());
It's much better to just
Post::create($request->validate(['title' => 'required', 'body' => 'required' ]));
Or even better use a form request class for it
public function store(PostFormRequest $request)
{
Post::create($request->validated);
}
What about this?
$request->validate(['title' => 'required', 'body' => 'required' ]);
$post = new Post
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->save();
or
$request->validate(['title' => 'required', 'body' => 'required' ]);
Post::create($request->only(['title','body']));
for me, if i see any of this code, if means not validated and i don't trust the value
$request->only(['title','body'])
but if i see this, it mean i trust the value
$request->validated()
$request->validated()['title']
$request->validated()['body']
This
$request->validate(['title' => 'required', 'body' => 'required' ]);
$post = new Post
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->save();
Should in that case be
$postData = $request->validate(['title' => 'required', 'body' => 'required' ]);
$post = new Post();
$post->title = $postData['title'];
$post->body = $postData['body'];
$post->save();
And
$request->validate(['title' => 'required', 'body' => 'required' ]);
Post::create($request->only(['title','body']));
Should be
Post::create($request->validate(['title' => 'required', 'body' => 'required' ]));
However you do as you please and I'll go with this every day of the week.
public function store(PostFormRequest $request)
{
Post::create($request->validated);
}
$request->validate(['title' => 'required', 'body' => 'required' ]);
$post = new Post
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->save();
For the above, wouldn't it return to previous page if it doesn't pass the validate in 1st line of code?
For this :
public function store(PostFormRequest $request)
{
Post::create($request->validated);
}
For each form, we create a new request form?
For the above, wouldn't it return to previous page if it doesn't pass the validate in 1st line of code?
Throws a validation exception which is caught automatically and returned back with input.
For each form, we create a new request form?
Yes
I always set the model to $guarded = [];
That's crazy talk you say. Not really.
If you validate everything in the controller, like this:
$attributes = $request->validate([
'field_1' => 'required|min:3',
'field_2' => 'required',
// etc etc....
]);
Then you can drop it into your database like so:
Model::create($attributes);
No need to mass assignemnt protection, as you've validated everything in the controller first.
@djinfusion thats no different to this;
Post::create($request->validate(['title' => 'required', 'body' => 'required' ]));
except that you used a temporary variable.
That's pretty damn cool. I'll be using that from now on.
Please or to participate in this conversation.