0

So when I put a route name with a single parameter it works flawlessly but when I pass named route with two parameters I get a 500 error in my console which looks like this:GET http://127.0.0.1:8000/admin/packages/package-programs/kathmandu/action?query= 500 (Internal Server Error).

<?php namespace App\Http\Controllers\AdminVisible; use Illuminate\Http\Request; use Illuminate\Support\Str; use App\Program; use App\Package; use DB; class PackageProgramController extends Controller { public function __construct() { $this->middleware('auth'); } public function index($packageSlug) { $showCounts = Program::count(); $packages = Package::firstOrFail(); return view('admin.pages.packageprogram',compact('showCounts','packageSlug','packages')); } function action($packageSlug,Request $request) { if($request->ajax()) { $output = ''; $query = $request->get('query'); if($query != '') { $data = DB::table('programs') ->where('id', 'like', '%'.$query.'%') ->orWhere('day', 'like', '%'.$query.'%') ->orWhere('Package_Type', 'like', '%'.$query.'%') ->orWhere('title', 'like', '%'.$query.'%') ->orderBy('id', 'desc') ->get(); } else { $data = DB::table('programs') ->orderBy('id', 'desc') ->get(); } $total_row = $data->count(); if($total_row > 0) { foreach($data as $row) { $packageProgram = ['packageProgram' => $row->id]; $route = route('PackageProgram.edit',['packageSlug' => $packageSlug, 'packageProgram' => $packageProgram]); $output .= ' <tr> <th scope="row"><input type="checkbox" name="ids[]" class="selectbox" value="'.$row->id.'" onchange="change()"></th> <td onClick="location.href=\''.$route.'\' " style="cursor: pointer">'.$row->id.'</td> <td onClick="location.href=\''.$route.'\' " style="cursor: pointer">'.$row->day.'</td> <td onClick="location.href=\''.$route.'\' " style="cursor: pointer">'.$row->title.'</td> <td onClick="location.href=\''.$route.'\' " style="cursor: pointer">'.$row->description.'</td> </tr> '; } } else { $output = ' <tr> <td align="center" colspan="12">No Data Found</td> </tr> '; } $data = array( 'table_data' => $output, 'total_data' => $total_row ); echo json_encode($data); } } public function create($packageSlug, Package $package) { return view('admin.create.createPackageProgram',compact('packageSlug','package')); } public function store($packageSlug,Request $request) { $packages = Package::where('slug', $packageSlug)->firstOrFail(); $data = request()->validate([ 'day' => 'required', 'title' => 'required', 'description' => 'required', ]); $packages->program()->create($data); switch ($request->input('action')) { case 'preview': return redirect()->intended(route('PackageProgram',$packageSlug))->with('message', 'Package Program has been added.'); break; default: return redirect()->back()->with('message', 'Package Program has been added.'); break; } } public function edit($packageSlug,Program $packageProgram,Package $package) { return view('admin.edit.editPackageProgram',compact('packageSlug','packageProgram','package')); } public function update($packageSlug, Program $packageProgram) { $data = request()->validate([ 'day' => 'required', 'title' => 'required', 'description' => 'required', ]); $packageProgram->update($data); return redirect()->intended(route('PackageProgram',$packageSlug))->with('message', 'Package Program has been updated.'); } public function delete(Request $request) { $data = request()->validate([ 'deleteSelected' => 'required', ]); $id = $request->get('ids'); $data = DB::delete('delete from programs where id in ('.implode(",",$id).')'); return redirect()->back()->with('message', 'Testimony has been deleted.'); } } 

My blade file looks something like this:

@extends('layouts.app') @section('style') <link href="{{ asset('css/Admin/sql-data-viewer.css') }}" rel="stylesheet"> <style></style> @endsection @section('content') <section class="data-viewer"> <div class="d-flex justify-content-between px-3"> <h3 class="text-white">Select {{$package->Package_Name}} {{$package->Package_Type}} Days to change</h3> <a href="{{ route('PackageProgram.create',$packageSlug) }}"><button type="button" class="btn add-data text-white rounded-pill">Add Day &nbsp;<i class="fas fa-plus"></i></button></a> </div> <form> @csrf @method('DELETE') @if(session()->has('message')) <div class="alert alert-success"> {{ session()->get('message') }} </div> @endif <div class="d-flex justify-content-between selectDelete"> <div class="delete pl-3 mt-3 mb-3"> <label for="deleteSelected">Action:</label> <select name="deleteSelected" id="deleteSelected" class="@error('deleteSelected') is-invalid @enderror" name="deleteSelected" > <option disabled selected>---------</option> <option>Delete Selected Package Program</option> </select> <button formaction="{{ route('PackageProgram.delete',$package) }}" formmethod="POST" type="submit" class="go" id="deleleGo" onclick="deleteBtn()">Go</button> &nbsp;&nbsp;<span id="selected">0</span> of {{$showCounts}} selected @error('deleteSelected') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror <strong id="selectError">You must check at least one checkbox</strong> </div> <div class="search pr-3 mt-3 mb-3"> <label for="search">Search:</label> <input id="search" type="text" color="#000" class="rounded @error('search') is-invalid @enderror" name="search" value="{{ old('search') }}" autocomplete="search" placeholder="Search"> @error('search') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <table class="table table-hover table-striped table-dark"> <thead> <tr> <th scope="col"><input type="checkbox" id="checkHead" class="selectall"></th> <th scope="col">Id</th> <th scope="col">Day</th> <th scope="col">Title</th> <th scope="col">Description</th> </tr> </thead> <tbody></tbody> </table> </form> </section> @endsection @section('script') <script src="{{ asset('/js/sqlData.js') }}"></script> <script> $(document).ready(function(){ fetch_data(); function fetch_data(query = '') { $.ajax({ url:"{{ route('PackageProgram.action',$packageSlug) }}", method:'GET', data:{query:query}, dataType:'json', success:function(data) { $('tbody').html(data.table_data); } }) } $(document).on('keyup', '#search', function(){ var query = $(this).val(); fetch_data(query); }); }); function checkboxError(){ var number = document.querySelectorAll('.selectbox:checked').length; if(number == 0) { var a = document.getElementById("selectError").style.display = "block"; return false; } } window.addEventListener('DOMContentLoaded', (event) => { var deleteBtn = document.getElementById("deleleGo"); deleteBtn.onclick = checkboxError; }); </script> @endsection 

So my route file looks something like this:

 Route::prefix('package-programs')->group(function() { Route::get('/', 'AdminVisible\packagePackageProgramController@index')->name('PackagePrograms'); Route::get('/action', 'AdminVisible\packagePackageProgramController@action')->name('PackagePrograms.action'); Route::prefix('{packageSlug}')->group(function() { Route::get('/', 'AdminVisible\PackageProgramController@index')->name('PackageProgram'); Route::get('/action', 'AdminVisible\PackageProgramController@action')->name('PackageProgram.action'); Route::get('/create', 'AdminVisible\PackageProgramController@create')->name('PackageProgram.create'); Route::post('/create', 'AdminVisible\PackageProgramController@store')->name('PackageProgram.store'); Route::delete('/delete','AdminVisible\PackageProgramController@delete')->name('PackageProgram.delete'); Route::get('/{packageProgram}/edit', 'AdminVisible\PackageProgramController@edit')->name('PackageProgram.edit'); Route::patch('/{packageProgram}', 'AdminVisible\PackageProgramController@update')->name('PackageProgram.update'); }); }); 

It might be I do not know how to pass named route with two parameters but in my blade file, I been doing it like this, and there it works. Is it something different that must be done in the controller.

7
  • A little note about your middleware in construct, in your case you can and should assign auth middleware to route group like this Route::middleware(['auth'])->group(function () {... check here. That way your code is cleaner, more maintainable and more compliant with design patterns. About the question: your action function is assigned as get method in routes but you use Http\Request as a function param so change your route to post so that you can get request params from form and add uri param Route::post('/action/{your_param}',... Commented Aug 27, 2020 at 11:54
  • But than again check this it is bad design pattern to use post with uri args, i noticed that your form contains only query arg so make it get Route like so Route::get('/action/{slug}/{query}', ... Commented Aug 27, 2020 at 11:57
  • And again avoid mixing php+html, backend should only return data that frontend than processes however it wants with js it is more maintainable and good design pattern again. Commented Aug 27, 2020 at 11:59
  • @Arman what I have made is a live search with ajax I know some of my practice may be bad since I am new and learning but can you tell me how I can fix this or do it differently and better I will also paste my blade.file. But the problem is in my $route only because if I remove it works perfectly fine and I have it in other pages as well which has a single parameter route where it works perfectly. Commented Aug 27, 2020 at 12:27
  • $.ajax({ url:"{{ route('PackageProgram.action') }}", method:'GET', data: { 'slug': {{ $packageSlug }}, 'query': query },.. and change your route to Route::get('/action/{slug}/{query}', .. and function function action($packageSlug, $query) check with dd() if all args correct Commented Aug 27, 2020 at 12:34

1 Answer 1

2

First start from blade (please check comments):

@extends('layout') @section('content') <div class="row"> <table class="table table-hover table-striped table-dark" id="slugTb"> <thead> <tr> <th scope="col"><input type="checkbox" id="checkHead" class="selectall"></th> <th scope="col">Id</th> <th scope="col">Day</th> <th scope="col">Title</th> <th scope="col">Description</th> </tr> </thead> <tbody></tbody> </table> </div> @endsection @section('scripts') <script> $(document).ready(function() { var query = 'damnSon'; $.ajax({ url: "{{ route('test.action') }}", method: 'GET', data: { 'slug': '{{ $packageSlug }}', 'query': query }, dataType: 'json', }) .done(function(data) { console.log(data) //use console.log to debug $('#slugTb tbody').html(data.table_data); //set table id so that you don't miss the right one }) .fail(function(err) { console.log(err) //in case if error happens }) .always(function() { console.log( "complete" ); //result despite the response code }); }); </script> @endsection 

You used deprecated jquery method like success check
Better use this three: done,fail,always

Next route web.php:

Route::get('action', ['as' => 'test.action', 'uses' => 'TestController@action']); 

In your case better to use Request params bag so that you can add as much params as you want.

Next controller:

function action(Request $request) { $total_row = 1; $packageSlug = $request->get('slug'); //names that you set in ajax data tag: {'slug': '{{ $packageSlug }}','query': query} $query = $request->get('query'); $output = '<tr> <td align="center" colspan="1">' . $packageSlug . '</td> <td align="center" colspan="1">' . $query .'</td> </tr>'; $data = array( 'table_data' => $output, 'total_data' => $total_row ); return response()->json($data); } 

You should return something from the controller so blade can show that data and json encode it so that js could parse it. That is why return response()->json($data);

Other way:

route:

Route::get('/action/{slug}/{query}',['as' => 'test.action', 'uses' => 'TestController@action']); 

blade script:

<script> $(document).ready(function() { var query = 'damnSon'; $.ajax({ url: 'action/{{ $packageSlug }}/' + query, method: 'GET', dataType: 'json', }) .done(function(data) { console.log(data) //use console.log to debug $('#slugTb tbody').html(data.table_data); //set table id so that you don't miss the right one }) .fail(function(err) { console.log(err) //in case if error happens }) .always(function() { console.log( "complete" ); //result despite the response code }); }); </script> 

and controller:

function action($slug, $query) { $total_row = 1; $packageSlug = $slug; $query = $query; $output = '<tr> <td align="center" colspan="1">' . $packageSlug . '</td> <td align="center" colspan="1">' . $query .'</td> </tr>'; $data = array( 'table_data' => $output, 'total_data' => $total_row ); return response()->json($data); } 

Not recommended just because you manually type route in ajax request: url: 'action/{{ $packageSlug }}/' + query if your route changes you have to change it in js.

Sign up to request clarification or add additional context in comments.

2 Comments

You don't have to check if the request is ajax if($request->ajax()) unless you want to use that action function for other calls, but better to use separate methods for ajax calls and other types that is a good practice. Also strongly recommend reading official laravel documentation, everything there explained and have many routing, validation, eloquent etc. examples
Also note that in script tags you can use php(laravel) variable only in quotes '{{ $packageSlug }}'

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.