laravel retrieving request input returns null - php

Sorry if this question is asked elsewhere, but I've searched everywhere but couldn't find the answer. Well, I'm facing this problem on Laravel 5.0, when i try to get a variable from a request, Im getting null value on Production Server but im getting an empty string on the Development Server. The value is not present on the request, ie the field was empty when the form was submitted. eg.
// ProductController
public function store(Request $request) {
// this field is actually empty in the submitted form
$price = $request->price;
// when it gets to the server this is how this value looks like :
// $price in production server : null
// $price in development server : ''
}
When i try to save the object to a database like
Product::save($request->only('name', 'price'));
I get this error(only on production server)
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'price'
cannot be null
NOTE that the price column has 'default 0' on mysql table
Why is this happening?
UPDATE:
All this time i thought the request->input() method returned empty string('') if the field was not present. but just know i looked at the laravel source to see this :
public function input($key = null, $default = null)
{
$input = $this->getInputSource()->all() + $this->query->all();
return array_get($input, $key, $default);
}
here it returns null as the default value. then why am i getting empty string on development server?

This is happening because mysql inserts the default value if you don't define anything. In this case Laravel sends a value, which is null. You should not use Request::only, instead use an array.
It's always good to be specific, it makes your code readable and consistent.

Input Trimming & Normalization
By default, Laravel includes the TrimStrings and ConvertEmptyStringsToNull middleware in your application's global middleware stack. These middleware are listed in the stack by the App\Http\Kernel class. These middleware will automatically trim all incoming string fields on the request, as well as convert any empty string fields to null. This allows you to not have to worry about these normalization concerns in your routes and controllers.
If you would like to disable this behavior, you may remove the two middleware from your application's middleware stack by removing them from the $middleware property of your App\Http\Kernel class.
From: https://laravel.com/docs/5.4/requests#input-trimming-and-normalization

Related

Laravel 5.8 request value is null instead of default value

I use Laravel 5.8, and I want simply use a default value for description if it's empty, and take summary.
// summary variable request is equal to "test"
$summary = $request->get('summary', null);
$request->get('description', $summary)
But, the field is present, empty, and description give me null instead of summary value. Summary value is "test".
To get information from a request you should use get(), input() or the name directly. There is no documentation for the get method on requests for recent Laravel versions. For the input method on Laravel 5.8 the documentation says
You may pass a default value as the second argument to the input method. This value will be returned if the requested input value is not present on the request
It says it only works if it is not present so I would do it as simple as this
$description = $request->description ? $request->description : $request->summary
It really depends on what you want to achieve after all this and how you want your data.
Possible Solutions
My first impressions were that the data may not be being sent through correctly but upon looking over your code again, I realized you are using the more deprecated function ->get('description').
Try using ->input('description) instead. I personally have never used ->get(), so maybe this could be the problem.
https://laravel.com/docs/5.8/requests

Laravel 5: how to reset builtin throttle / ratelimiter?

Im using Laravel's builtin throttle like this:
//File: Kernal
protected $middlewareGroups = [
'api' => ['throttle:10,3']
];
However, I would like to reset the count after certain action in one of my controllers (for example after successful login).
I can see this middleware uses RateLimiter and that has a public method called clear.
The problem is, how to use this? Because it depends upon the key from ThrottleRequests middleware.
To get the object of ThrottleRequests I need instance of RateLimiter
To get the object of RateLimiter, I need instance of Cache.
.
.
all in all, there is no end to how to use it..
Any idea?
Thanks
As your question is tagged with Laravel v5.5, here's what applies there:
For Login attempts specifically:
You can use the Illuminate\Foundation\Auth\AuthenticatesUsers trait in your controller, so you would have access to the clearLoginAttempts method, which calls the clear() method on the RateLimiter instance with the correct key without the need to provide the key.
Actually if you look at how Illuminate\Foundation\Auth\ThrottlesLogins::clearLoginAttempts() is implemented, you can see that the right key can be retrieved by $this->throttleKey($request), once your controller uses the AuthenticatesUsers trait.
In general:
You can always get the Illuminate\Cache\RateLimiter instance by using app(\Illuminate\Cache\RateLimiter::class), which would in turn contain all the configured limiters and the cache as well. The problem is that it is not possible to get the cache keys from this point of view. So you really have to find out where and how the key was set in the first place, so you can use the same key for the reset.
The standard ThrottleRequests middleware sets the key in the handle() method, but the actual key would depend on where and how your throttling is configured (e.g.: is it a named limiter or only set using the numeric parameters, was ->by(...) called on it to set the key explicitly etc.)
If you only need to find the key for one particular limiter, probably you can set a breakpoint in the handle() method and just check.
Your case
In your particular case, as it is not a named limiter, the handle() method will call resolveRequestSignature to get the key. I don't think you can easily access the Middleware instance from a Controller. What you can do is to check how that method generates the key and basically copy that piece of code to replicate the same keys, but I'd not recommend that as it is a dirty and fragile solution.
Ifyou check, you'll see the key can be reproduced as something like:
if ($user = $request->user()) {
$key = sha1($user->getAuthIdentifier());
}
elseif ($route = $request->route()) {
$key = sha1($route->getDomain().'|'.$request->ip());
}
But in more recent Laravel versions you can explicitly set the key which is much cleaner and reliable solution:
In Laravel 8
Now as the question is fairly old, most people would rather use the latest version of Laravel (v8 as of 2021/02/12), so for them the documentation includes the way to "segment" the limiters aka. become able to apply separate limit counters for different requests based on the request (or session data, etc.). In fact the by() method actually sets the key of the limiter. So you can set up one or more named limiters like:
RateLimiter::for('my_per_ip_limiter', function (Request $request) {
return Limit::perMinute(100)->by($request->ip());
});
This means the limiter named my_per_ip_limiter will use the IP as the key, so any time in your controllers you could call:
app(\Illuminate\Cache\RateLimiter::class)->clear($request->ip());
to reset the limiter for a particular IP. Or to get the number of attempts so far:
$attempts_so_far = app(\Illuminate\Cache\RateLimiter::class)->attempts($request->ip());
Indeed instead of IP you could use any variable of the request (or session or whatever).
However there is no way (I think) to differentiate between the named limiters. So if the same key is used for another limiter as well, their hits will be counted together* and clear together. So giving a name like my_per_ip_limiter to the limiter is only useful so you can assign that limiter to particular routes by the name, e.g.:
Route::post( 'login', 'Auth\LoginController#login' )
->middleware('throttle:my_per_ip_limiter');
But if you really need named limiters to reset individually, you have to use a unique key, for example prefixing it with something, e.g.:
RateLimiter::for('my_other_ip_limiter', function (Request $request) {
return Limit::perMinute(100)->by('other_'.$request->ip());
});
This can be cleared independently from the other one:
// reset my_other_ip_limiter, but not my_per_ip_limiter :
app(\Illuminate\Cache\RateLimiter::class)->clear('other_'.$request->ip());
*: By counted together I mean they would add up, so if you apply two of them to the same request, each single request will bump the counter by 2!

How to set default values of fields to empty instead of null

I am using Laravel 5.4 and building API for Android and Iphone. I have set default value to null in phpmyadmin but my mobile developers do not want null values in response. There are many APIs so I am looking for short and perfect method.
I tried to find something in Laravel model that can help me. I tried following code as well.
Also tried setting default value in phpmyadmin but it does not accepts default: "As defined" is equal to empty value.
Third option could be to loop through laravel Model response and convert null to empty or zero based on data type but that will increase processing time and will increase our most of work as well.
public static function boot() { parent::boot();
self::creating(function ($my_model) {
$my_model->some_prop = $my_model->some_prop >= 42 ? $my_model->some_prop: defaultValue();
});}
Is there something in Laravel in Model section or somewhere else where I can set default value to empty fields when field does contain any value or is there any other solution or suggestion means how I can handle this problem?

Laravel Carbon data missing when date is an empty string

In my model I have the following:
protected $dates = ['start_date'];
I am using an input field of type 'date' to select the date. If the user removes the date, its value becomes a null string "".
when updating my model, I get the following error:
exception: "InvalidArgumentException"
file: "C:\www\projects\crm\vendor\nesbot\carbon\src\Carbon\Carbon.php"
line: 582
message: "Data missing"
I can avoid this error by using a mutator like this:
public function setStartDateAttribute($value)
{
if ($value) {
$this->attributes['start_date'] = $value;
} else {
$this->attributes['start_date'] = null;
}
}
Question:
Is there a faster/better way than using a mutator to deal with storing an empty string as a date?
Looking into this a bit deeper:
Middleware updated in 5.4
Laravel 5.4 included two new middleware in the default middleware stack: TrimStrings and ConvertEmptyStringsToNull.
These middleware will automatically trim request input values and
convert any empty strings to null. This helps you normalize the
input for every request entering into your application and not have to
worry about continually calling the trim function in every route and
controller.
From: https://laravel.com/docs/5.4/releases#laravel-5.4
So, when I am grabbing the request object, an empty date field is converted to null. The database allows null on these fields and everything works correctly.
So, through the front end, date fields can be entered and removed without error. When updating manually to an empty string as per your request
\App\Yourmodel::find(7)->update(["your_date_field" => ""]);
I had the same data missing error.
Question is, do you specifically need to pass an empty string or is making the field nullable a better option for you?
\App\Yourmodel::find(7)->update(["your_date_field" => null]);

Laravel - populate array w/ default values | POST method

Q&A:
I would like to set some default values to avoid empty fields.
I want to set the default values in the Controller not the html
Forms placeholders don't work as filled field
I want to still be able to outputs the error if some of the key value is missing
I've found just the right way to acomplish this by using array merge:
array_merge($requested, $default)
The keys from the first array will be preserved! You should check php doc.
Then proceed (create & redirect).
Unspecified keys will throw errors, also you should check 'strict' => false in the config/database.php if you run into a problem.
{NameController.php}
$default = array(['image' => 'http://placehold.it/250x225']);
$request = request(['user' => request('user')]);
$input = array_merge($request, $default);
{Model}::create($input);
return redirect('{view}');
BE AWARE that this method leads to MassAssigmentExeption if you didn't set the $guarder or $protected fields in the {Model}.
I am new to stack so please tell me if something is wrong, thx.

Categories