How is this value failing my laravel date validation? - laravel-5.6

So I am posting to an api controller action, as we can see I have some basic validation:
public function store(Request $request) {
$fields = $request->except(['_token']);
$user = $request->user();
$request->validate([
'log_date' => 'required|date_format:"Y-m-d"',
'bill_time' => 'required|numeric',
]);
}
I constantly get: The log date does not match the format Y-m-d.
The date coming in is formatted by moment js and shows:
"2018-11-6"
So I am confused how is that not formatted properly?

When using Y-m-d, the d on that format mask applies the following:
Day of the month, 2 digits with leading zeros
So, the value being passed 2018-11-6 fails due to 6 not matching 06. Either use Y-m-j, where j is
Day of the month without leading zeros
Or adjust how moment is sending your value.
For full date reference, check http://php.net/manual/en/function.date.php

Related

How to insert date format YY-MM into database?

I have been trying to get the the Year and Month from the user and insert them into the database.
i am using input type month so that the user can send only the Year and the Month.
<input type="month" name="date_from"/>
<input type="month" name="date_to"/>
and this is my model
function setDateFromAttribute($value)
{
$this->attributes['date_from'] = \Carbon\Carbon::createDateFromFormat('Y-m', $value);
}
function setDateToAttribute($value)
{
$this->attributes['date_to'] = \Carbon\Carbon::createDateToFormat('Y-m', $value);
}
protected $fillable = [
'date_from',
'date_to',
];
and data is saved as 0000.00.00
the data type in my database for these two inputs is
timestamp
i do not know what i am doing wrong here. please help
I don't see createDateFromFormat as a valid Carbon method in the documentation https://carbon.nesbot.com/docs/
Likewise, there does not appear to be any createDateToFormat method.
Carbon::createFromFormat() returns a Carbon object, not a string or equivalent MySQL timestamp, so, assuming you change your code to be:
$this->attributes['date_from'] = \Carbon\Carbon::createFromFormat('Y-m', $value)->toDateTimeString();
It should provide the results you are looking for.
References:
Converting a carbon date to mysql timestamp.
#Ted Stresen-Reuter
Sorry for the late reply couldn't find a solution that works within the model. tried your method which i have tried before with minor changes.
thanks a lot for trying to help me.. i found a method to complete this inside the controller which i will not recommend, but this was the best i was able to find which works and i was on a tight schedule.
'date_from' => isset($date_from[$key]) ? date('Y-m-d h:i:s', strtotime($date_from[$key])) : '',
'date_to' => isset($date_to[$key]) ? date('Y-m-d h:i:s', strtotime($date_to[$key])) : '',
the type timestamp accepts at least dates in full formats. as i know how i pass the data from blade to the controller i was able to add a date method and within it a strttotime method to convert my YY-MM into YY-MM-DD and the date that is inserted by default will be 01.

Any reason why a model's fields not updating despite an update call?

In Laravel 5.3 I am, using Model events to take certain actions. For the most part, things are working fine, just one place in the program flow where data is not updating.
Here is the whole story:
I have a database structure with courses and weeks. So Course 1 with Week1, Week2, etc.
Then to repeat a given course I also have courseinstance and weekinstance which contain date info for given instances of courses and weeks.
I am using Angular in the backend to handle CRUD, and when I create a course it automatically creates a courseinstance where a start_date and end_date are null.
The code for that in the course API controller is
$thiscourse= \App\Courses::create(Input::all());
After that the course model executes this:
public static function boot() {
parent::boot();
static::created(function($course) {
// add first instance of this course - dates will be null at this point
$instance = new Coursesinstance;
$instance->course_id = $course->id;
$instance->save();
});
}
That is successful. Then in my backend, I add a week to the course (which is for descriptive data about the week's topic) and that creates a first instance of the week where there are a start and end date. In the API week controller first we have this:
$week = \App\Week::create(Input::all());
Then that triggers create event on the model and we go to:
static::created(function($week) {
// add first instance of this week
$instance = new Weekinstance;
$instance->week_id = $week->id;
$instance->weekstart = $week->weekstart;
$instance->zoomstart = $week->zoomstart;
$coursesinstance_id = DB::table('coursesinstance')
->select('id')
->where('course_id', $week->courses->id)
->first();
$instance->coursesinstance_id = $coursesinstance_id->id;
$instance->save();
});
This is a success, things looking fine in the database, all relationships proper, various id's just as they should be.
Now since a new week instance is created, we go to this in the Weekinstance model so that I can look at all weeks in the instance and update the course instance start and end dates.
static::created(function($weekinstance) {
// get all week instances corresponding to this course instance
$weekinstances = DB::table('weekinstance')
->select('*')
->where('coursesinstance_id', $weekinstance->coursesinstance_id)
->get();
$weekstarts=array();
foreach ($weekinstance as $instance)
{
$weekstart = $instance->weekstart;
$weekstarts[].=$weekstart;
}
$dates = array_map('strtotime', $weekstarts);
$startdate = min($dates);
$enddate = strtotime("+7 day", max($dates));
// update start and end date for the course instance
$result = \App\Coursesinstance::where('id', $weekinstance->coursesinstance_id)
->update([
'start_date' => $startdate,
'end_date' => $enddate
]);
});
And here is where things break down. The week is successfully created, the weekinstance is created, but the update call above just doesn't set the start_date and end_date of the courseinstance.
I have ran in a debugger, and at the moment of the update, all seems well. A $startdate and $enddate variable are created as timestamps, the where clause is indeed returning the course instance, the return result is a 1, so Laravel is not returning any errors, and in log file no issues. start_date and end_date are fillable on the model. Everything truly looks normal.
The date fields are are stored as TIMESTAMP in MySQL. It does not accept Unix timestamp's as an argument. So you must convert the timestamp's into the correct format, before updating. One way to do this:
->update([
'start_date' => Carbon\Carbon::createFromTimestamp($startdate),
'end_date' => Carbon\Carbon::createFromTimestamp($enddate)
]);
Ok, after spending so much time on this I finally realized the problem is that I was passing my timestamp values directly to the query builder. Little did I know that MYSQL expects a timestamp as a date string. I thought the data type datetime was meant for strings and that a timestamp, as name suggests, could be used for an actual timestamp. Crazy thinking, I know.
So here is how I had to create the "timestamps":
$startdate = date('Y-m-d H:i:s',min($dates));
$enddate = date('Y-m-d H:i:s',strtotime("+7 day", max($dates)));
So in other words, 180 degrees away from what I would consider logical based on definition of a timestamp.
Thanks,
Brian

Laravel price validation only accept positive number and not only 0

I want to validate a "price" field in Laravel.
The price should only contain numbers without (.) or (,) and cant start with 0 as well.
Eg
2500 // Pass
02500 // Fails
12.12 // Fails
12,12 / Fails
The rule I have now looks like this:
'price' => 'required|integer|not_in:0',
It seems to work with the example above, however I dont understand it. Why does not integer allow something like 0123 with a starting zero. I just want to make sure that my rule works as excpected and that I dont miss something
Thanks
This works for me:
'price' => 'required|numeric|gt:0',
You can format the input before sending it to the validator in your Request class.
public function formatInput()
{
$input = array_map('trim', $this->all());
$input['price'] = (int)($input['price']);
$this->replace($input);
return $this->all();
}
Then you can use
'price' => 'required|integer|min:0',
Hope this helps
if you're not sure about the rule "integer", you can use the regex expression validation as following :
'price' => 'required|regex:^[1-9][0-9]+|not_in:0',
I had some issue same way as you, and since then i always used the regex validation for this kind of requirements. Furthermore it allow you to take back the same regex if you want to make a front validation with js.
Here is the laravel function allowing to validate integers :
public function validateInteger($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_INT) !== false;
}
SO it's PHP itself that is concerned by this behavior. PHP tells us this thing about FILTER_VALIDATE_INT :
Validates value as integer, optionally from the specified range, and
converts to int on success.
No other informations are set by PHP about the "0" value, but it's known that this function doesn't consider numbers starting by "0".
Use regex rule to not allow for integer with starting 0
'price' => 'required|integer|not_in:0|regex:^[1-9][0-9]+',

CakePHP 3.0 - How do I return data from a deeper contain in the correct format?

I'm working with a user's profile that has a state id in it, so I have this query:
$user = $this->Users->find()
->where(['Users.id' => $this->Auth->user('id')])
->contain(['UserProfiles' => function ($q) {
return $q
->select(['city', 'address_one', 'address_two', 'zip'])
->contain(['States' => function ($q) {
return $q
->select(['id']);
}]);
}])
->select('first_name', 'last_name')
->first();
This returns all of my data correctly except for States - instead, I get this back:
state {"id":6}
It was a little odd, so on the front end I tried:
echo $user->user_profile->state; // yields the string {"id": 6}
echo $user->user_profile->state->id; // error: trying to access property of non-object
echo $user->user_profile->state['id']; // index error, doesn't exist
So what's the deal? Why is this returned in this fashion? I don't have anything on the column specifying it as json or anything strange; just normal cake-baked objects. How do I spit out the id?
I found the issue thanks to the comments. Although I was saving the id in state_id and containing based on that column, an old column that wasn't deleted yet (states) was a text field and messed up the return value of the states contain, since the contain was also named 'state.'
I went into the database, renamed 'state' to 'old_state', and the ids again return in the standard format.

How to show data from within a specific time period in codeigniter?

I am creating an archive view for my blog.
I have a url that looks the following:
www.mydomain.com/blog/archive/2012-May
How can I get all blog posts from the database that were created during May 2012???
I am using mysql datetime to store the date created. Format in DB: 2012-03-14 14:39:47
This is my code so far:
function get_archive_posts(){
$data = '';
//NEED TO GROUP AND GET BY DATE AND YEAR IN URL
$this->db->order_by('date','desc');
$query = $this->db->get('blog');
foreach ($query->result() as $row) {
$data[] = array(
'id' => $row->id,
'date' => $row->date,
'title' => $row->title,
'content' => $row->content,
'category' => $row->category,
'author' => $row->author
);
}
return $data;
}
How can I order by the month and year shown in the url and only show these posts???
To make monthly archive i think it will be good idea to store the month and year of the post in separate column of the table so we can easily fetch the data that fall within that month and year. I think with the current date format it will be not possible to check the month and year of the post so do one thing get the month and year from the post date and store them in table then compare the month and year with archive month and year. I think it will be far easy to do this in this way.
Hopefully this will help you.
Follow this hierarchi,
www.domain.com/blog/archieve/2012/may
and inside your blog controller create a function with variables. Such like:
function archieve($year='A_DEFAULT_VALUE_FOR_HERE', $month='A_DEFAULT_VALUE_FOR_HERE_TOO') {
//You can here use 3rd and 4th segments (example: $year=$this->uri->segment(3); $month=$this->uri->segment(4); ) as variables.
}

Resources