Laravel & Ajax return array response no parsing - ajax

Currently I'm trying to pull some data via ajax and I'm not getting the data to appear properly.
In my ajax call I have this:
$.ajax({
url:"{{ route('pricing.fetch') }}",
method:"POST",
data:{select:select, value:value, _token:_token, dependent:dependent, productId:productId},
success:function(result)
{
$("ul[data-dependent='quantity']").html(result);
This works as expected. The problem is I'm trying to return data from different tables in my db. So I'm trying to do it by changing my result in ajax to this.
$("ul[data-dependent='quantity']").html(result.productQuantities);
The reason for me wanting to do this is because I have multiple drop downs I need. So I would also like to do another one like this:
$("ul[data-dependent='quantity']").html(result.productPaperStock);
my controller code is like this:
$data = Product::with(['productQuantity', 'productPaperstock'])->where('ID', $productId)->first();
// pull the quantity for this product
$productQuanties = $data->productQuantity;
$productPaperStock = 'hello';
$output = '';
foreach($productQuanties as $productQuantity)
{
$output .= "<li><span>" . $productQuantity->quantity_name . "</span></li>";
}
return response()->json["productQuanties" => $productQuanties, "productPaperStock" => $productPaperStock]);
I'm not sure what I'm doing wrong but using this example above I get a 500 error.

You need to set dataType: json option in your ajax request, and then in your controller, you can return json response.
Also, you are missing the starting brace in your controller code. The correct code is
return response()->json(["productQuanties" => $productQuanties, "productPaperStock" => $productPaperStock])
(Note that ...storage/logs/laravel.log is an awesome place to get insights into what's screwing your app:))

Related

How to setup url in JavaScript to pass multiple parameter to controller in Laravel without using request

I setup the url by JavaScript to call a function in controller with only one parameter($RoleID) like this
$(document).on('change','#role',function(){
$RoleID = $(this).val();
let $url = '{{route("Admin.role.permission.LoadMember",':id')}}'
$url = $url.replace(':id', $RoleID);
$.ajax({
url:$url,
success:function(data)
{
$('#member').append(data);
}// end fucntion success
});
});
It works ok, Now I would like to do the same with more than one parameter without using Request
I tried like this
document.getElementById('function').addEventListener('change', function(e) {
if (e.target.name==='function') {
$FncID = e.target.value;
let $url = '{{route("Admin.role.permission.LoadActionsInRolePermissions",'[$ModuleID,$RolID,$FncID]')}}';
$.ajax({
url:$url,
success:function(data)
{
$('tbody').html(data);
//$('#member').append(data);
}// end fucntion success
});
}
})
But unfortunately, It is not work. Pls help me.
Thank in advance
You haven't shown us how you defined the route, nor what laravel version you're using, but I highly suggest taking a read on the docs on how route parameters work.
As example, say this is your LoadMember route:
Route::get('permission/load-member/{id}', [PermissionController::class, 'loadMember'])->name('Admin.role.permission.LoadMember')
Then, as follows:
{{route("Admin.role.permission.LoadMember",['id' => ':id'])}}.
By passing an associative array with key => value assignment, Laravel knows where to place the given values in the url.
For a multi-parameter route, it works exactly the same:
Route::get('permission/load-actions-in-role-permissions/{moduleId}/{rolId}/{fncId}', [PermissionController::class, 'loadActionsInRolePermissions']) ->name('Admin.role.permission.LoadActionsInRolePermissions')
{{route("Admin.role.permission.LoadActionsInRolePermissions",'['moduleId' => $ModuleID, 'rolId' => $RolID, 'fncId' => $FncID]')}}
Also, may I suggest using camelCase for variable names, and kebab-case or snake_case for route naming? It highly improves readability and future developers who might work on your project will have a better guess at how your route structure works.

Issue with Integers passing data from Vue to Laravel using FormData

I am successfully updating a database using Vue 2 to a Laravel 8 Controller using Axios. However, I am stuck when attempting to pass an integer to my database.
My database has a column, 'number_of_searches' and it must be an integer.
Laravel Migration looks like this:
$table->integer('number_of_searches')->nullable();
And the model looks something like this:
class Product extends Model
{
protected $fillable = [
'product_title',
'number_of_searches' => 'integer',
];
}
My Vue updateProduct() function used FormData and appends the values coming from the form. It looks like this:
updateProduct(product){
let data = new FormData();
data.append('_method', 'PATCH');
data.append('product_title', product.product_title);
data.append('number_of_searches', product.number_of_searches);
axios.post('/api-route-to-update/product_id/', data)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
My update controller looks like this:
public function update(Request $request, $product_id){
$product = Product::findOrFail($product_id);
$product->update($request->all());
$product->save();
}
I can have as many input fields as I need and it works perfectly as long as they are strings. However, when I use a number input field in my component such as:
<input v-model="product.number_of_searches" type="number" min="1" max="999">
The generated json that will pass from axios into my controller looks like this:
{ "id": 5, "product_title": "The Product Title will work great", "number_of_searches": "222"}
You will notice that 'number_of_searches' is passed as a string, hence my database fails because it is the wrong datatype, it requires an integer. After reading the documentation and other threads, it seems that FormData will always return strings and that I must just deal with this on the server side.
So what I did is, I went into my back-end updateProduct() method and attempted to modify the Request.
First I tried a few methods such as:
//this one
$requestData = $request->all();
$requestData['number_of_searches'] = 123;
//also this one
$request->merge(['number_of_searches' => 123]);
//and this
$data = $request->all();
$data['number_of_searches'] = 123;
After countless hours, I am unable to modify the original request. After doing some research, it seems that requests are protected and cannot be modified, which makes sense. Therefore I attempted to create a new request that clones $request->all(), like this:
$new_request = new Request($request->all());
$new_request->merge(['number_of_searches' => 123]);
But I have failed to force to override 'number_of_searched'
My question is:
Should I stay away from FormData completely in this case? What method do you suggest to pass forms that have integers or floats or other datatypes through axios or fetch? Or what am I doing wrong? I find it hard to believe that FormData would only send strings (making parseInt useless before using axios). I'm sure I am doing something wrong from origin.
On the other hand, maybe I need to completely change my approach in my Controller when receiving the data. I am working on an app with a lot of fields and I love $request->all() because it simplifies what I am trying to do. I wouldn't mind using intval on the server side and that's it, but it seems overly complicated.
On the Vue side, you can use the number modifier on v-model to make sure it's not casting the value to a string:
v-model.number="product.number_of_searches"
On the request side, you can use $request->merge to override the value in a request
$request->merge([
'number_of_searches' => (int) $request->get('number_of_searches');
]);
At the model side in the updating hook within the boot method you can ensure the value is being casted as an int when saving:
static::updating(function ($model) {
$model->number_of_searches = (int) $model->number_of_searches;
});
This should give you the end to end.

simple json response with cakephp

I trying to pass some json to a controller in cakePHP 2.5 and returning it again just to make sure it is all going through fine.
However I getting no response content back. Just a 200 success. From reading the docs I am under the impression that if I pass some json then the responseHandler will the return json as the response.
Not sure what I am missing.
Data being passed
var neworderSer = $(this).sortable("serialize");
which gives
item[]=4&item[]=3&item[]=6&item[]=5&item[]=7
appController.php
public $components = array(
'DebugKit.Toolbar',
'Search.Prg',
'Session',
'Auth',
'Session',
'RequestHandler'
);
index.ctp
$.ajax({
url: "/btstadmin/pages/reorder",
type: "post",
dataType:"json",
data: neworderSer,
success: function(feedback) {
notify('Reordered pages');
},
error: function(e) {
notify('Reordered pages failed', {
status: 'error'
});
}
});
PagesController.php
public function reorder() {
$this->request->onlyAllow('ajax');
$data = $this->request->data;
$this->autoRender = false;
$this->set('_serialize', 'data');
}
UPDATE:
I have now added the following to the routes.php
Router::parseExtensions('json', 'xml');
and I have updated my controller to
$data = $this->request->data;
$this->set("status", "OK");
$this->set("message", "You are good");
$this->set("content", $data);
$this->set("_serialize", array("status", "message", "content"));
All now works perfectly.
A proper Accept header or an extension should to be supplied
In order for the request handler to be able to pick the correct view, you need to either send the appropriate Accept header (application/json), or supply an extension, in your case .json. And in order for extensions to be recognized at all, extension parsing needs to be enabled.
See http://book.cakephp.org/...views.html#enabling-data-views-in-your-application
The view only serializes view vars
The JSON view only auto-serializes view variables, and from the code you are showing it doesn't look like you'd ever set a view variable named data.
See http://book.cakephp.org/...views.html#using-data-views-with-the-serialize-key
The view needs to be rendered
You shouldn't disable auto rendering unless you have a good reason, and in your case also finally invoke Controller:render() manually. Currently your action will not even try to render anything at all.
CakeRequest::onlyAllow() is for HTTP methods
CakeRequest::onlyAllow() (which btw is deprecated as of CakePHP 2.5) is for specifying the allowed HTTP methods, ie GET, POST, PUT, etc. While using any of the available detectors like for example ajax will work, you probably shouldn't rely on it.
Long story short
Your reorder() method should look more like this:
public function reorder() {
if(!$this->request->is('ajax')) {
throw new BadRequestException();
}
$this->set('data', $this->request->data);
$this->set('_serialize', 'data');
}
And finally, in case you don't want/can't use the Accept header, you need to append the .json extension to the URL of the AJAX request:
url: "/btstadmin/pages/reorder.json"
and consequently enable extension parsing in your routes.php like:
Router::parseExtensions('json');
ps
See Cakephp REST API remove the necessity of .format for ways to use the JSON view without using extensions.
Output your json data
public function reorder() {
$this->request->onlyAllow('ajax');
$data = $this->request->data;
$this->autoRender = false;
$this->set('_serialize', 'data');
echo json_encode($data);
}

JQuery (Mobile) /Ajax Undefined returned variable

Despite many questions regarding this I cannot seem to find some code that works for my situation, every time I run this code I end up with an undefined variable instead of the desired returned JSON.
My AJAX code is:
$.ajax({
data: {"serial":account},
url: 'http://127.0.0.1/MobilePHP/findCustomerName.php',
dataType: 'json',
success: function(data){
window.alert(data);
}
});
And my PHP code is:
<?php
header("Access-Control-Allow-Origin: *");
header('Content-type: application/json');
include 'dbConfig.php';
include 'connectDB.php';
//$account = $_POST['serial'];
$account = 14;
$sth = mysql_query("SELECT customer_name AS Name FROM customer_details WHERE auto_id = $account ");
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
$rows ['CustomerName'][] = $r;
}
echo json_encode($rows);
include 'closeDB.php';
?>
And my JSON from my console is:
{"CustomerName":[{"Name":"Tullaroan"}]}
I am really unsure of why I cannot access these variables as it seems to return the right JSON on the console.
Inside the success function, data is an object with a single property: CustomerName. To access that, you use data.CustomerName. That property is itself an array, so you'll need to access elements inside it using their index.
In your example, you have a single object in the array, so to access that object you'd do data.CustomerName[0]. That object also has a single property: Name, so to get the actual name out you'd do: data.CustomerName[0].Name, which would return "Tullaroan".
It might be easier to visualise the breakdown of the data object like this:
data = {"CustomerName":[{"Name":"Tullaroan"}]}
data.CustomerName = [{"Name":"Tullaroan"}]
data.CustomerName[0] = {"Name":"Tullaroan"}
data.CustomerName[0].Name = "Tullaroan"

Using the return json code

I'me trying to use ajax with php, I have the follogin script in php :
<?php
// this file get the POST infor sent by a AJAX request and will return the value is succesful.
$price['name'] = "Called";
$price['Wheel'] = 75.25;
$price['Tire'] = 50.00;
echo json_encode($price);
?>
and I'm calling this code from my main page in the following way :
$.post("ajax/profileMod.php", {
'lname':lname,
'fname':fname,
'mname':mname,
'language':language,
'title':title,
'ptype':ptype,
'vip':vip,
'vreason':vreason
})
// Retreive the data from the php script
.done(function(data) {
// php code : echo json_encode(array("name"=>"Called!"));
alert(data);
}, "json");
// Stop original behavior
return false;
});
The returniong result from the alert is the following test :
{"name":"Called",Wheel":75.25,"Tire":50}
How can I change this result so I may use it in the following way in javascript EX:
alert(myresult['Name']) ; Would give me "Called".
So I basicly would like a associative array in javascript, but I read somewhere on this forum that you can't have associative array in Javascript, only object...
Please help!
Pass "json" as the last parameter to .post() to tell jQuery to parse the response as JSON.
(or, fix your server to return the correct Content-Type of application/json, and jQuery should do that automatically)
You will then get a Javascript object, allowing you to write
alert(result.name);

Resources