Passing ID from Laravel show to Datatables route - php

I believe I am close but struggling on how to pass a given ID from my show method into the associated showdata one so that datatables can manifest with the associated data for just that ID.
The code works when I hardcode an ID or just remove the where statement altogether. My objective is to have the datatable manifest associated items for just a given collection.
Routes:
Route::resource('collections', 'CollectionsController');
Route::get('collectionsdata/{id}', 'CollectionsController#showdata');
Show.blade.php:
var id = {{ $collection->id }}
$(function () {...
$('#item-table').DataTable({
//processing: true,
serverSide: true,
ajax: "/collectionsdata/"+ id,
columns: [
//{data: 'id', name: 'id'},
{data: 'id', name: 'id'},
{data: 'collection_id', name: 'collection_id'},
{data: 'type_id', name: 'type_id'},
{data: 'collection.title', name: 'collection.title'},
{data: 'type.name', name: 'type.name'},
{data: 'updated_at', name: 'updated_at'},
]
});
Collections Controller:
public function show(Collection $collection)
{
$collection->load('items.type')->get();
//dd($collection);
return view ('collections.show', compact('collection'));
}
public function showdata()
{
$data = Item::with('collection', 'type')->where('collection_id', $id);
return Datatables::of($data)->make(true);
}
SHOW itself function well, var id works well in the blade - I think I am just missing something in the controller to take in the id and ultimately create the desired query on $data for return to the datatable.

Yes. You are missing the Request $request in your show method to retrieve the $id from the route.
use Illuminate\Http\Request;
public function showdata(Request $request)
{
$collection_id = $request->id;
$data = Item::with('collection', 'type')->where('collection_id', $id);
return Datatables::of($data)->make(true);
}
You can also retrieve id directly from the controller instead of using $request.
public function showdata($id)
{
$data = Item::with('collection', 'type')->where('collection_id', $id);
return Datatables::of($data)->make(true);
}

You only have to have one parameter in showdata that is one for id you are passing from URL
public function showdata($id)
{
$data = Item::with('collection', 'type')->where('collection_id', $id);
return Datatables::of($data)->make(true);
}

Related

How to implement DataTable with parameter 'id' in Laravel (DataTables)?

I am trying to pass the ID value from the blade file into ajax so it the data table will be routed and will call the ProductActivities function in ProductController.
Here's my snippet code for show() function in ProductController:
public function show($id)
{
$product = Product::find($id);
$data = Product::with(['user_modify'], 'id', $product->user_modified)
->where('product_id', '=', $id)->first();
$category = Category::select('category_name')
->where('category_id', '=', $data->product_type)
->pluck('category_name')
->first();
if($data->count() > 0){
return view('product.view', compact('data', 'category'));
}else{
Toastr::error('Product cannot be retrieved.', 'Error');
return view('product.index');
}
}
And here's the snippet code of JavaScript for the DataTable initialization in view.blade.php file:
#push('js')
<script>
$(function () {
$("#prod_log_tbl").DataTable({
responsive:true,
stateSave:false,
scrollY:true,
autoWidth: false,
ajax: {{ url('product/activities', [Request::segment(3)]) }},
order:[0, 'desc'],
searchable: false,
sortable:false,
fixedColumns: true
});
});
</script>
#endpush
line of code for route in web.php:
Route::get('product/activities/{id}', 'Master\ProductController#ProductActivities')->name('product/activities/{id}');
snippet code for the ProductActivities() function in ProductController:
public function ProductActivities($id)
{
$dataAct = Activity::all()->where('subject_id', '=', $id);
return Datatables::of($dataAct)->make(true);
}
And here's the result of my current progress:
In the screenshot of result the URL that ajax shows has additional values after the ID which I think causes of the DataTable error.
I don't know How I am getting this error? How can I implement the passing of ID from the view blade file through DataTable ajax into the ProductController?
P.S. I use Yajra/DataTable package for Laravel.
I think you do not need php echo in you Ajax url, route helper syntax is
{{ route('routeName', ['id' => 1]) }}
you need route name and parameter, another way is using url helper
{{ url('product/activities/', [Request::segment(3)]) }}
Beside this if you want to use model refer documentation, using first() will give you only one object, you need a collection, better considering get().

Creating a record to laravel databse with vue.js doesn't work

I'm trying to create a new record to my database using Vue.js in laravel, my API, data is okay. But I get that strange error when I click create on my site.
Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, string given, called in C:\Users\PC\Desktop\Productivity\gitdemo\students\vendor\laravel\framework\src\Illuminate\Database\Query\Grammars\Grammar.php on line 884
I also have delete function that works perfectly, but this doesn't work... Form inputs have v-model, that seems alright, but it still doesn't work.
My create method on vue.js
addStudent() {
axios.post(`api/students/create`, {data:this.students});
}
Getting records in vue.js
data() {
return{
students: [],
}
},
created() {
axios.get(`api/students`).then(response =>{
this.students = response.data.data;
})
},
Controller
public function store(Request $request)
{
Student::create($request->all());
return view('welcome');
}
Route (in api.php)
Route::post('students/create', 'StudentController#store');
Student Model
use SoftDeletes;
protected $dates = ['birth_date'];
protected $guarded = [];
Students array in data has all of the v-model namings
You should not directly pass $request->all() to create method. Based on what you send from front end to back end, do this:
$r = $request->all();
$students = $r['data'];
Student:create($students);

Store pivot table values on creation in Laravel with Ajax input

I'm learning Laravel by creating a recipe website.
The idea is a user creates a recipe which includes a title, description and number of portions (and tags), and then is directed to a new view in which they add the ingredients.
I've got this working, and the user can successfully create the recipe and the ingredients, which are being written to their respective tables, but I'm unable to attach/sync them.
Relevant parts of the models:
Recipe Model:
class Recipe extends Model
{
public function ingredients(){
return $this->hasMany('App\Ingredient', 'recipe_ingredients');
}
}
Ingredient Model:
class Ingredient extends Model
{
public function recipe(){
return $this->belongsTo('App\Recipe', 'recipe_ingredients');
}
}
Ingredients Controller
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($recipe_id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}
If I remove the $recipe->ingredients()->attach($recipe_id); the ingredients save to the ingredients table, but I can't get the recipe_id and ingredient_id to save in the recipe_ingredients table`.
I think I'm using the attach wrong, but I could be wrong.
Note:
Not that I think it makes any difference, but I'm submitting the data via Ajax.
Script:
$(document).ready(function(){
$("#submit").click(function() {
var name = $("#ingredientName").val();
var token = $("#token").val();
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: "post",
data: "name="+name,
dataType:'json',
url: "{{ route('ingredients.store', ['id' => $recipe->id]) }}",
success:function(data){
console.log(data);
$("#msg").html('<div class="alert alert-success my-0">'+data.name+' added</div>');
$("#msg").toggleClass("invisible")
$("#msg").fadeOut(2000);
$("#ingredientsTable").append('<tr><td scope="col" class="align-middle">'+data.name+'</td></tr>');
}
});
})
})
Revised Controller
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($ingredient->id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}
Table migration
public function up()
{
Schema::create('recipe_ingredients', function (Blueprint $table) {
$table->integer('recipe_id')->unsigned();
$table->foreign('recipe_id')->references('id')->on('recipes');
$table->integer('ingredient_id')->unsigned();
$table->foreign('ingredient_id')->references('id')->on('ingredients');
});
}
You're using the wrong ID when trying to attach the Ingredient to the Recipe:
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($recipe_id);
In the last line, you already have the Recipe, so passing $recipe_id (which I actually don't see defined anywhere) is not the correct logic.
What you need to do is pass the Ingredient you want to attach:
$recipe->ingredients()->attach($ingredient->id);
That should correctly set the relationship.
As shown by the example here: https://laravel.com/docs/5.6/eloquent-relationships#updating-many-to-many-relationships
You should be attaching the ingredients instead of the recipe:
$recipe->ingredients()->attach($ingredient_id);
-- edit --
You also have your Ingredient model as:
class Ingredient extends Model
{
public function ingredient(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
}
}
However, you should have this instead:
public function recipes(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
}
After making lots of little tweaks and changes, the following finally worked for me:
Recipe /model:
class Recipe extends Model
{
public function ingredients(){
return $this->hasMany('App\Ingredient', 'recipe_ingredients', 'recipe_id', 'ingredient_id');
}
Ingredient Model:
class Ingredient extends Model
{
public function recipes(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients', 'ingredient_id', 'recipe_id');
}
**IngredientsController#Store: **
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$ingredient->recipes()->attach($recipe->id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}

Resource index parameters

I've wrote a controller to have it's index to output the DataTables plugin data.
A excerpt:
public function index() {
return Datatable::collection(\App\Slip::where('paid', '=', false)->get())
...
->make();
}
and the route:
Route::resource('api/slip', 'SlipsController');
everything works fine, the problem is that this index return only items with paid = false that's right for one view, but for the other view I need all items/rows.
so what's the best practice to make index function cover both cases (all and those with paid = false)?
A post param is the first thing that comes to my mind, but the data is loaded by the DataTables plugin.
Why not?. You need detect your specified view and send some extra param in ajax-request. Like:
$('...').DataTable({
....
"ajax": {
'type': 'GET',
'url': "....",
'data': {paid: false},
},
....
});
Now in action:
public function index(Request $request) {
$paid = $request->input('paid');
$items = [];
if ($paid){
$items = \App\Slip::all()->get();
}else{
$items = \App\Slip::where('paid', '=', false)->get();
}
return Datatable::collection($items)
...
->make();
}

pass a data key value from a json post request to routes to controller

my json post request has a data key named "id", now how im going to pass it from routes to my controller?
my json post request
$.post("/employees", {id:"1"}, function(response){
if(response.success)
{
var branchName = $('#branchname').empty();
$.each(response.employees, function(){
$('<option/>', {
value:$(this).user_no,
text:$(this).firstname
}).appendTo(branchName);
});
}
}, 'json');
as you can see from my json post request i have put a key value name id
my routes
Route::post('employees', [
'as' => 'employees', 'uses' => 'mot#getemployee'
]);
and my controller
public function getemployee($id){
$employees = employees::where("branch_no", $id)->lists('firstname', 'user_no');
return response()->json(['success' => true, 'employees' => $employees]);
}
as you can see, I have an argument $id, it supposedly, its where the key value named id from the json post request will be put and be used from the query stuff.
Since you're using $.post in your jQuery code, the {id: ...} parameter passed as a POST data, which means that instead of having:
public function getemployee($id){
You should have:
public function getemployee() {
$id = (int)$_POST['id']; //notice that int casting
#KhanShahrukh has a good point. Consider using the following instead of the traditional POST variable:
<?php
namespace App\Http\Controllers;
use Request;
....
....
class ... extends ... {
public function ...() {
if(Request::ajax()) { //Prevent direct access
$id = Request::input('id;);
Regarding the second issue (which mentioned in the comment), $(this) won't refer to the object. In order to access the object's properties, you should add parameters to the function() in your $.each function. (Manual)
So instead of:
$.each(response.employees, function(){
$('<option/>', {
value:$(this).user_no,
text:$(this).firstname
You should have:
$.each(response.employees, function(firstname, user_no){
$('<option/>', {
value: user_no,
text: firstname

Categories