Prevent data from being submitted in a form - laravel

I have a HTML form in my Laravel Blade view, with a leaflet map inside to show some data. The problem is, when I want to submit my form, this map is generating data and inserting it into the form, with the field name: "leaflet-base-layers_xx" where xx are random numbers that change everytime, so I can't just unset this data in my controller.
$data = $request->all();
unset($data['leaflet-base-layers_95']);
Is there any way I could prevent the map from submitting data. Or any way I could unset the field I want, knowing that it has a flexible name ?

You should be validating the request. This will not only validate the fields that you do want, but will also provide an easy way filter out any fields that you don't want or weren't expecting to receive.
For example, if your form should only have a title and body field
$data = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
Now $data will now only contain 'title' and 'body', no matter what other fields were submitted.
If you take this a step further and use a Form Request you can use $request->validated() method which again will only contain the validated fields and none of the other garbage you don't want.
$data = $request->validated();
Aside from this solving your problem, as a matter of good practice you should always only ever work with validated data. Passing unvalidated data around your app is a recipe for disaster.
Refs: https://laravel.com/docs/5.8/validation

Related

How to save the json array data in database in laravel?

does anyone know how to store the data in this format ["123"] in PHPMyAdmin?
Now the data I store into the database is only the value which is 123. I want to store the data like this ["123"]. Does anyone know how to do this?
Here is my code:
Company::create([
'companyID' => $people->people_id,
]);
To store data the way you want to, you need to change the datatype for the column of the table to json. It can be done in your migration file like:
$table->json('column_name');
After migrating your table you have to add casting for the specific column in your model file. It can be done as:
protected $casts = [
'column_name' => 'array',
];
Once you have done this, you can then store data as json in your database.
You can find more information about casting at Laravel Docs here.
https://laravel.com/docs/8.x/eloquent-mutators#array-and-json-casting
You can save text data in mysql table column. For this you should change your column type to text and follow the following code as reference.
You will have to change your array to json data and pass variable to create method as value. Remember that, for storing string value you will have to wrap value with quotations.
$data = json_encode([
123, "124", 134.4, "450"
]);
Company::create([
'companyID' => $data
]);

Is there an efficient way of adding user_id using updateOrCreate?

I'm trying to add/update responses from a multi-field form using updateOrCreate.
I'm avoiding having to write out the second argument in full for each field in the form by using $request->all. However, this approach so far is precluding me from adding the value for user_id that is needed for the record to be complete. That value (`$userId') is obtained in the controller as shown:
$userId = Auth::user()->id;
$cropid = $request->id;
Crop::updateOrCreate(['id'=>$cropid],$request->all());
Is there a way of retaining the $request->all approach AND adding the user_id value?
Thanks, Tom.
You can use array_merge to generate an array with both data:
$data = array_merge($request->all(), ['user_id' => $userId]);
Then you can use the generated $data in your updateOrCreate method:
Crop::updateOrCreate(['id' => $cropId], $data);

Laravel Coding Practice / Most Optimised Method to Store

Laravel documentation says one should store as follows:
public function store(Request $request)
{
// Validate the request...
$flight = new Flight;
$flight->name = $request->name;
$flight->save();
}
However, why not just as follows:
public function store(Request $request)
{
Flight::create($request->all());
}
The above example is quite easy, since it only has one field. But I imagine its rather tedious to do something with many fields and have to assign each one as opposed to just passing the whole $request as in the second example?
First option gives you better control as to what goes into new model. If you store everything from the request then user might inject fields that you don't want to be stored for a new model in your store method.
For example, your flight has column is_top_priority that is declared as fillable in your Flight model, but when creating new flight you want to set only name for you flight (and leave is_top_priority as null or maybe it has default value of 0 in your table). If you write Flight::create($request->all()); then user can inject <input name="is_top_priority" value="1"> and get advantage of your code.
That is why it is not recommended to use fill($request->all()). Use $request->only(...) or assign each needed field manually as provided in your first example.
For example your model have some fields like name, email, password,status and etc.
Request validate name, email and password and if you do this:
Flight::create($request->all());
Client can send with other fields status, but you change status manually. I do this:
Flight::create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => $request->get('password'),
'status' =>config('params.flight.status.not_active'),
]);

Show fields only on edit laravel backpack

I want to show certain fields only in edit screen. So In Crud controller I have given addField option like this
$this->crud->addField([ // Number
'name' => 'xyz',
'label' => 'XYZ',
'type' => 'number',
],'update');
By this way, I can see this field only in edit screen, however the changes I make are not saved. If I want to save then I have to mention in
protected $fillable = [xyz].
If I give it in fillable array,then that field will save but it will displayed for create screen also.
What I want is, in create screen I do not want to show certain fields, only in edit screen I wan to show those fields and on saving, it should be reflected in database.
Check the route in view then decide to show something or not
if (\Request::is('edit')) {
// show element
}

How can I paginate two Eloquent collections on a single page with Laravel?

I have two collections on a single page which should be both paginated. But pagination generates the same Parameter for both (?page=X).
How can I solve that kind of an issue?
You can change the param of either pagination by
Paginator::setPageName('someparam');
Read more about Pagination here In the section Customizing The Paginator URI
Note : You should do this before paginator is done i.e.,
$yourCollection = Model::paginate(10);
Example :
I assume you have two pagination like this
Paginator::setPageName('yourFirstParam');
$firstCollection = FirstModel::paginate(10);
Paginator::setPageName('yourSecondParam');
$secondCollection = SecondModel::paginate(10);
Where you use this to get in your view
Paginator::setPageName('yourFirstParam');
$firstCollection->links();
Paginator::setPageName('yourSecondParam');
$secondCollection->links();
There is a way to "automatically" set the page name (in a sense), which I'll get to in a bit.
First, if we go over the paginate method, you'll see that it accepts a pageName argument as its 3rd parameter:
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
Lets say you have a User and Post model. You can then do something like this in your controller:
$users = User::paginate(10, ['*'], 'users');
$posts = Post::paginate(10, ['*'], 'posts');
return view('example', compact('users', 'posts'));
It works like your normal pagination except the second argument specifies the columns you want to select and the third argument specifies the page name.
In your view, when you render your pagination links, you might run into a problem when you do this:
{!! $users->render() !!}
{!! $posts->render() !!}
While the pagination links will be rendered, when you click on a link to a posts page, the users query string parameter is gone. Therefore, the users are back to page one and vice versa.
To fix this, you can use the appends method to keep the query parameters for both models:
{!! $users->appends(['posts' => Request::query('posts')])->render() !!}
{!! $posts->appends(['users' => Request::query('users')])->render() !!}
All this works, but it's a bit ugly so how can we clean this up? You can create your own method to "automate" this process. In your model, you can add your own paginate method:
// Name it whatever you want, but I called it superPaginate lol
protected function superPaginate($perPage)
{
return $this->newQuery()->paginate(10, ['*'], $this->getTable());
}
This will automatically set the pagination name to the model's table name. So for the User model, the page name will be "users". For the Post model, the page name will be "posts".
There's still the problem with rendering links. You don't want to call appends all the time and specify the query parameters. To fix that, we can improve the superPaginate method into this:
protected function superPaginate($perPage, $columns = ['*'], $page = null)
{
$params = \Request::query();
return $this->newQuery()->paginate(10, $columns, $this->getTable(), $page)->appends($params);
}
Now, all you need to do is Model::superPaginate(10); and $models->render(). Everything should work properly.

Resources