I have a time tracking application where every time that a new Time Entry is about to be added, I must first verify that all the previous time entries have been closed (meaning that an ending date has been set) and throw and error message using the validate() method.
I don't know how feasable this is or how to do it, reading the documentation it seems that most custome rules require that an attribute be given, but in this case it's more about validating the logical requirements rather than the form of the post request.
When I receive a post request I fetch all previous time entries which come before the post request starting time and have not yet been given an ending time.
Ideally, if I get any time entries returned I would throw an error saying 'You need to close the previous time entry before opening a new one'.
For more clarity, here is what I want to do in code :
$timeEntry= new TimeEntry;
$openTimeEntries = $timeEntry->Where('start_time', '<', $request->startTime)->Where('end_time', 0)->get();
$count = $openTimeEntries->count();
$request->validate([
'comment' => 'string',
'candidateId' => 'required',
'startTime' => 'required|date',
'endTime' => 'date|nullable|after:startTime',
'CustomeTimeEntryRule' => $openTimeEntries->count() > 0, // If false I want this rule to add the message to the validate error array
]);
CodePudding user response:
You are on the right track.
However, If you really customize validation you should create a request for here you can read more about it.
Simply call php artisan make:request TimeEntryStoreRequest
public function rules()
{
return [
'CustomeTimeEntryRule' => $openTimeEntries->count() > 0,
];
}
/**
* @return array|string[]
*/
public function messages(): array
{
return [
'CustomeTimeEntryRule.*' => 'Custom message',
];
}
However, if it is not a form input from a user I think you should check it inside your controller not in the form.
Also you can simplify your code like this:
use App\Models\TimeEntry;
$openTimeEntriesCount = TimeEntry::select('id')->where('start_time', '<', $request->startTime)->where('end_time', 0)->count();
CodePudding user response:
A simple way to do this is to merge the custom attribute to the request :
$timeEntry= new TimeEntry;
$openTimeEntries = $timeEntry->Where('start_time', '<', $request->startTime)->Where('end_time', 0)->get();
$count = $openTimeEntries->count();
$request->merge([
'CustomeTimeEntryRule' => $count,
]);
Then we can validate the attribute using the in rule, which will return a custom validation message which we can specify as a second argument, when the count is not equal to 0:
$request->validate([
'comment' => 'string',
'candidateId' => 'required',
'startTime' => 'required|date',
'endTime' => 'date|nullable|after:startTime',
'CustomeTimeEntryRule' => 'in:0',
], [
'CustomeTimeEntryRule.in' => 'You need to close the previous time entry before opening a new one'
]);