Laravel Calling Multiple Controllers from Form Submit - laravel

I want to submit a form, and once that submit button is pressed, I run a bit of code.
During this 'bit of code', part of its job will be to create a student, and also create a lunch order. (information pulled from the form).
From what I've been reading, I should be aiming to use CRUD, which would mean I should have a Student Controller and a LunchOrderController.
I want to call the #store method in each controller.
If I was doing it the 'bad' way, the form would have [action="/students" method=POST]. And in that route, it would then call /lunchorder/ POST, and then return to a page (redirect('students')).
However, as above, I don't want to call a controller from a controller. Therefore, the initial [action="/students" method=POST] should be something else instead, and this new entity will then call the StudentController, then call the LunchOrderController, then redirect('students').
But, I don't know what this new entity is, or should be, or how to link to it.
It is just a new route to a new controller which is ok to call other controllers from?
Or is there some other place I should be sending the form data to (maybe models?), to them call the controller? Or am I way off base and need to take some steps back?
I'm fairly new to Laravel but am wanting to use best practice as much as possible. All my reading of other posts don't seem to explain it enough to get my head around how its meant to work.
Edit: Some code to give an idea of what I'm getting at.
Student_edit.blade.php
<form action="/student" method="POST">
{{ csrf_field() }}
<label>First Name</label><input name="firstname" value="">
<label>Last Name</label><input name="lastname" value="">
<label>Lunch Order</label>
<select name="lunch_value" id="">
<option value="1" >Meat Pie</option>
<option value="2" >Sandwich</option>
<option value="3" >Salad</option>
<option value="4" >Pizza</option>
</select>
<input type="submit" value="Submit" class="btn btn-primary btn-lg">
</form>
web.php
Route::resource('/students', 'StudentController');
Route::resource('/lunchorder', 'LunchOrderController');
Studentcontroller
public function store(Request $request)
{
Student::create(request(['firstname', 'lastname']));
LunchOrderController::store($request, $student_id); //<- This isn't the correct syntax
return redirect('/students');
}
LunchOrderController
public function store(Request $request, $student_id)
{
LunchOrder::create(array_merge(request(['lunch_value']), ['student_id' => $student_id]));
return null;
}

Personally I would create a 'Logic' Directory as: app/Logic. Some people prefer Repositories etc, but this is my preference.
For your specific requirement I'd create the following file:
app/Logic/StudentLogic.php
StudentLogic
<?php
namespace App\Logic\StudentLogic;
use App\Student;
use App\LunchOrder;
class StudentLogic
{
public function handleStudentLunch(Request $request): bool
{
$student = Student::create(request(['firstname', 'lastname']));
if(is_null($student)) {
return false;
}
LunchOrder::create(array_merge(request(['lunch_value']), ['student_id' => $student->id]));
return true;
}
}
StudentController
public function store(Request $request)
{
$logic = new StudentLogic();
$valid = $logic->handleStudentLunch($request);
if($valid) {
return redirect('/students');
}
abort(404, 'Student Not Found');
}
ASSUMPTIONS
Student is stored under App/Student & LunchOrder is stored under App\LunchOrder
You will also need to use App\Logic\StudentLogic in StudentController
The reason I'd split this out into a Logic file is because I do not like 'heavy' controllers. Also, I'm not entirely sure what you're trying to acomplish here, but creating a student on the same request you create a LunchOrder seems like you're asking for trouble

Related

Why is there nothing in my userConsul model

When I submit the form I want to collect the userConsult information. I then call my repository and call the Insert method. inside the brackets I include e.g.
userRepo.insertoIntoDB(userConsult.getepidemiology);
(I have left the other get methods as it is so long.
I run this and when I check my database I notice that only the fields I didnt use userConsult have items inside.
I think there is something to do with my options/select tag however I am unsure why there is nothing inside it. It works fine when I use input tags. I am using thymeleaf.
The Insert function works fine if I give it test inputs myself.
Please see my code below:
<form method="POST" th:action="#{/saveConsultation}" th:object="${userConsul}">
<label for="epidemiology">EPIDEMIOLOGY:</label>
<select id="epidemiology">
<option th:each="data : ${consultationData}"
th:text="${data.epidemiology}"
th:value="${data.epidemiology}">
</select>
<a th:href="#{/saveConsultation/{id}(id = ${patient.patientNumber})}" type="submit">Submit</a>
<input type="reset" value="Reset diagnosis">
</form><br>
Consultation Controller:
#RequestMapping("/saveConsultation/{id}")
public String saveConsultation(#ModelAttribute("userConsul") userConsul userConsul,HttpSession session,Model model,#PathVariable("id") int patientID){
Object USER_SESSION = session.getAttribute("USER_SESSION");
if (USER_SESSION == null) {
session.setAttribute("message", "You need to login to access the Consultation page");
return "redirect:/login";
}
User OldUser = (User) USER_SESSION;
int userId = OldUser.getID();
userRepository.insertIntoUserCase(userConsul.getEpidemiology(),userConsul.getComplaints(),userConsul.getExamination(),userConsul.getDiagnosis1(),userConsul.getDiagnosis2(),userConsul.getDiagnosis3(),patientID,userId);
return "test";
}

Livewire Select2 Dynamic not updating public view

I am using a select2 component with wire:ignore and i want to update the select2 value dynamically after clicking a button. I set up this functionality with events and events work fine, so does the variable gets initialized as well. I am failing to update this public view of this select2.
my blade
<select class="select2-example form-control" id="subjects" wire:model.lazy="subjects" name="subjects">
</select>
#push('scripts')
<script>
$('#subjects').select2({
maximumSelectionLength: 1,
minimumInputLength:2,
tags: false,
placeholder: 'Enter Subject(s)',
.... // this all works great
});
$('#subjects').on('change', function (e) {
let data = $(this).val();
#this.set('subjects', data);
});
// my event listener and it is working as well
Livewire.on('editSubject', subject => {
console.log(subject);
#this.set('subjects', subject);
$('#subjects').val(subject);
$('#subjects').trigger('change'); //the public view doesn't get updated
})
</script>
#endpush
I so far tried with browser dispatch event as well. Nothing works. What would be the workaround for this? Any help is greatly appreciated.
in blade
<div class="col d-flex display-inline-block">
<label for="contact_devices">{{ __('Select Device') }}</label>
<select id="contact_devices" wire:model="selectedDevice" class="form-control contact_devices_multiple" multiple="multiple" data-placeholder="{{ __('Select') }}">
#foreach($devices as $device)
<option value="{{ $device->id }}">{{ $device->alias }}</option>
#endforeach
</select>
</div>
<script>
window.loadContactDeviceSelect2 = () => {
$('.contact_devices_multiple').select2({
// any other option
}).on('change',function () {
livewire.emitTo('tenant.contact-component','devicesSelect',$(this).val());
});
}
loadContactDeviceSelect2();
window.livewire.on('loadContactDeviceSelect2',()=>{
loadContactDeviceSelect2();
});
</script>
in component
public $selectedDevice;
protected $listeners = [
'devicesSelect'
];
public function devicesSelect($data)
{
dd($data);
$this->selectedDevice = $data;
}
public function hydrate()
{
$this->emit('loadContactDeviceSelect2');
}
Note: If some face the problem of real time validaiton while implementing the above mentioned solution as i have commented in the accepted answer above.
My Comments:
hey, I have implemented your solution its working great but there is
one problem, here is the scenario, I submit empty form and all the
validations gets triggered, when i start filling the form the error
starts to disappear but as soon as i change the select2 the validation
part $this-update($key, $value) function does not work. Can you please
tell me why real time validation is not working ? and how to fix it
please. thankyou – Wcan
Solution:
Use syncInput() function instead of assigning the value to country property. updated lifecycle hook will be trigerred automatically.
public function setCountry($countryValue)
{
// $this->country = $countryValue;
$this->syncInput('country', $countryValue);
}

Livewire - updated hook without render of complex data

I'm using Livewire for data table with a complex database query with pagination. In table are also checkboxes and after check/uncheck is quite annoying to wait for render method with fetching all necessary data witch are required only for first component load.
I know I can use defer flag for checkboxes but I need also do some action when is any checkbox checked/unchecked so I cannot use that flag. So my question is if I can use updated hook method for checkbox without loading data in render.
Here is my example code:
class LivewireComponent extends Component
{
public $arrayOfCheckboxes = [];
public function render(SomeService $service)
{
$data = $service->fetchComplexData->paginate();
return view('livewire.some-component', ['data' => $data]);
}
public function updatedArrayOfCheckboxes($value)
{
// if value is true/false then do some action
// do I really need to call render and fetch complex data again?
}
}
// livewire.some-component.blade.php
<div>
<table>
#foreach($data as $row)
<input type="checkbox" wire:model="arrayOfCheckboxes" value="{{ $row->someValue }}">
#endforeach
</table>
</div>

How to resolve issue from laravel 5

I am receiving this error when I try to get the value from database to edit bus type form text box.
Property [name] does not exist on this collection instance. (View: E:\fyp\resources\views\buses\editbustype.blade.php)
Here is the code for edit section of controller:
public function edit(addbustype $id)
{
$bustype = addbustype::find($id);
return view('buses.editbustype', compact('bustype','id'));
}
When I changed $id to any number (1) it gives me the perfect result for that id, but only for a single one. The code for edit bus type section is here:
<div class="form-group col-md-6">
<label for="name">Company Name</label>
<input type="text" class="form-control" name="name" placeholder="Company Name" value="{{$bustype->name}}">
</div>
Note That You Are Using Route Model Binding
Than You Are Trying To Get The addbustype With $id Watch is $id Now Become An Instance Of addbustype Model So It Well Give You An Error Because
$bustype Well Now Become A Collection Of addbustype Model
So You Have To Decide Eather Use Route Model Binding Or Simply Find Function
In Your Web.php Route
The Parameter Name Must Matches With Parameter Both On Route And Edit Function
Route::get('addbustype/{addbustype}','yourCountroller#edit')
public function edit(addbustype $addbustype)
{
return view('buses.editbustype', compact('bustype'));
}
Or Simply Use Find Method
public function edit($id)
{
$bustype = addbustype::find($id);
return view('buses.editbustype', compact('bustype','id'));
}
You Can Revel To Route Model Binding For More

How to use codeigniter built-in form validation functions in callback function?

Hi I am trying to validate a user registration form using codeigniter form validation class. In my form majority of the fields are validated using codeigniter form validation class. But one field 'email' field has to be validated via database whether the email entered by the user is available for registration or not. When I use callback function other field validations like required|trim|xss_clean|valid_email etc don't work.
I don't want to write code manually for each of the validation like valid_email that are already exist in CI. When I use callback function for this field the CI form validations don't apply.
Here is my code:
My Form:
<input type="text" name="first_name"/>
<input type="text" name="last_name"/>
<input type="text" name="email"/>
<input type="password" name="password"/>
<input type="password" name="cpassword"/>
Here is my controller:
$this->form_validation->set_rules('first_name','First Name','required|trim|xss_clean');
$this->form_validation->set_rules('last_name','Last Name','required|trim|xss_clean');
$this->form_validation->set_rules('email','Email','valid_email|xss_clen|required|callback_email_check');
$this->form_validation->set_rules('password','Password','required|min_length[6]|max_length[20]|trim|xss_clean');
$this->form_validation->set_rules('cpassword','Retype Password','callback_password_match');
My callback function for email_check:
public function email_check()
{
$email=$this->input->post('email');
if($this->home_mod->email_available($email))
{
$this->form_validation->set_message('email_check', 'Another user with this email is already registered. Please try different email');
return FALSE;
}
}
Now after all that, form validation rules valid_email|required etc don't apply.
What am I doing wrong?
All your code looks correctly formatted, but try returning true after the check if it passes. So like this:
public function email_check()
{
$email=$this->input->post('email');
if($this->home_mod->email_available($email))
{
$this->form_validation->set_message('email_check', 'Another user with this email is already registered. Please try different email');
return FALSE;
} return true; //Add here
}

Resources