The variables never reach PHP from the FETCH API - php

I have 3 files (HTML,JS and PHP) in the HTML save de info in variable called DatosPaciente in JavaScript
function Tomar_DATOS(){
DatosPaciente={
id:document.getElementById("paciente_id").value,
fecha:document.getElementById("fecha").value
};}
Then i use a function called Tiene_Cita_Hoy inside of a JS file
Tiene_Cita_Hoy(DatosPaciente)
in the JS file i try to use the Fetch API to send info to the PHP file
function Tiene_Cita_Hoy(Datos){
console.log(Datos);//"{id: "8", fecha: "2020/09/03"}" here everything is fine
fetch('tiene_cita.php',{
method: 'POST',
body: Datos
})
.then(res => res.json())
.then(data => {
console.log(data); //to see the result
})
}
then in a PHP file, then tried to receive the information via POST
$VALOR_id_paciente=$_POST['id'];
$VALOR_fecha=$_POST['fecha'];
and then I assign those values ​​to a query
$SQL="SELECT * FROM vhsagenda WHERE PACIENTE='".$VALOR_id_paciente."' AND FECHA='".$VALOR_fecha."'";
echo json_encode($SQL);//just to see what information have
but the result is always: SELECT * FROM vhsagenda WHERE PACIENTE='' AND FECHA=''
apparently the information never reaches the PHP file

I have made some proper way for this method to get working.
You need to make an object first, then pass it in 'for loop'. It will generate string like this for example (test=123&test_two=444)
async function catch_something(url, bodyContent = {test: 123, test_two: 444}){
let bodyContent_string = '';
if(bodyContent instanceof Object){
for(const form_key of Object.keys(bodyContent)){
if(form_key != Object.keys(bodyContent)[Object.keys(bodyContent).length - 1]){
bodyContent_string += `${form_key}=${bodyContent[form_key]}&`;
}else{
bodyContent_string += `${form_key}=${bodyContent[form_key]}`;
}
}
}
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: bodyContent_string
}).catch((error) => {
console.error('Error:', error);
});
if(!response.ok){
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}

You should send the parameters as a URL-encoded string.
function Tomar_DATOS(){
DatosPaciente = 'id=' + encodeURIComponent(document.getElementById("paciente_id").value) + '&fecha=' + encodeURIComponent(document.getElementById("fecha").value);
}

You've passed a plain object to the body parameter, but fetch doesn't know what to do with that data type (so it converts it to the useless string "[object Object]").
You should pass something that fetch knows how to convert into something supported by PHP instead.
e.g. a FormData object.
DatosPaciente = new FormData(document.getElementById("form_containing_your_inputs"));

Related

How to get file from Form Data in the server

I cant get the file data on the server. _$FILE says is empty. I do this trough ionic app. I send the information in http params.
cargarFoto(idnegocio,formData) {
let datos = new HttpParams()
.set("proceso", "subirImgNegocioApp")
.set("imgRestaurante", formData)
.set("idnegocio", idnegocio)
let headerOptions = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(this.path,datos, {
observe: 'response',
responseType: 'text',
headers: headerOptions
});
}
That is the code from my service where i send the form Data and other information.
But when i use $_FILES to get the file, it says is null or empty. What im doing wrong? Actually all the information is get on $_POST. I returned post to the app and this is what displays:
body: "{
"proceso": "subirImgNegocioApp",
"imgRestaurante": "[object FormData]",
"idnegocio": "4"
}"
I can suggest little different approach - send everything as form data:
sendSomething(someVar: string, files: File[]) {
const formData = new FormData();
for (const f of files) {
formData.append('file[]', f);
}
formData.append('someVar', someVar);
return this.http.post('/someUrl', formData, {
headers: new HttpHeaders({ enctype: 'multipart/form-data' })
});
}
Then in PHP:
$someVar = $_REQUEST['someVar']
And files (or one file) will be in
$_FILES['file']

Ajax Call Back and Laravel

I have created an API which my AJAX post send values to it. AJAX does post and my laravel API does process the values. My issues is with the callback returning the value back to my AJAX post. My AJAX doesn't return the results in the success section when I do console log. I would like the results from my api to can use data to make my condition. At the moment, the console log doesn't even return a value. But in my chrome inspector under preview it shows the response from my API but not in the success section.
AJAX
var fname = "Joe";
var lname = "Test";
var processUrl = "api.example.com/z1";
$.ajax({
type: 'POST',
url: processUrl,
data: {"name": fname,"surname": lname},
dataType: 'json',
success: function(res){
console.log(res);
if(res.length >= 1){
$('#display').val(res.name);
}
}
});
PHP
public function checkResults(Request $request){
$name = $request->name." ".$request->surname;
$result = array();
$result['name'] = [$name];
return response()->json($result,201);
}
For first it will be good to return with 200 OK response code (instead of 201).
Note: If you want to just immediately get the answer for your question only, you can see the last part of this answer (usage of "done/fail" construct instead of "success/error").
Additional:
There is many patterns which are used by Client(Frontend)<->API<->Server(Backend) developers.
Approximately all APIs built without any 500 server error codes. But there is exists also many differences between APIs structures.
One of them is to send response like this (this is the only one example of response):
return response()->json([
'success' => true, // true or false
'message' => "Message about success!",
], 200); // 200, 401, 403, 404, 409, etc
The other approach is to always sending 200 OK, but message can be also about error:
return response()->json([
'success' => false, // true or false
'code' => 404,
'message' => "Resource not found!",
], 200);
This kind of methods will written under try{}catch() and will return only 200, but that messages can imitated also as an error (as in example).
The other (appropriate approach for you) is to change your Frontend AJAX functionality like this:
$.ajax({
type: 'POST',
url: processUrl,
data: {
{{--_token: "{{ csrf_token() }}",--}}
name: fname,
surname: lname
},
dataType: 'json'
}).done(function(res) {
console.log(res);
if(res.length >= 1) {
$('#display').val(res.name);
}
}).fail(function(jqXHR, textStatus, errorThrown) {
console.log("Error: " + textStatus);
});
AJAX .done() function replaces method .success() which was deprecated in jQuery 1.8. This is an alternative construct for the success callback function (like before: "success: function(){...}").
AJAX .fail() function replaces method .error() which was deprecated in jQuery 1.8. This is an alternative construct for the complete callback function (like before: "error: function(){...}").
Note: .error() callback is called on HTTP errors, but also if JSON parsing on the response fails. This is what's probably happening if response code is 200/201 but you still are thrown to error callback.
I believe this is happening because you are sending status code 201 (Created), but you need to send status code 200 (OK) to trigger the success callback.
public function checkResults(Request $request){
$name = $request->name." ".$request->surname;
$result = array();
$result['name'] = [$name];
return response()->json($result,200);
}
I couldn't find it specifically in the jQuery docs, but this SO question addresses it.
Due to the asynchronous nature of Ajax calls, do not put them in the normal execution flow of your program. See this post to get more insight.
A quick fix for your problem is to include the ajax call in a function and call that function anytime you want to interact with the server asynchronously.
var fname = "Joe";
var lname = "Test";
var processUrl = "api.example.com/z1";
ajaxCall();
function ajaxCall() {
$.ajax({
type: 'POST',
url: processUrl,
data: {"name": fname,"surname": lname},
dataType: 'json',
success: function(res){
console.log(res);
if(res.length >= 1){
$('#display').val(res.name);
}
},
error: function() {
console.log('error');
}
});
}
In addition, include an error function in the ajax call settings to handle cases where the ajax request fails. See this answer for alternative styles of doing this.

How to send both a file and JSON data to the server

tl;dr:
Using Angular 6 on the front end and PHP with Phalcon on the backend, I can send JSON data or a File with no problem but I am having a problem sending both in the same request.
Previously I was sending JSON data to the server using something like this
const HTTP_OPTIONS = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
}),
observe: 'response'
};
post(endPoint: string, body: object): Observable<any> {
return this.http.post<any>(this.apiUrl + endPoint, body, HTTP_OPTIONS)
.pipe(
tap(result => this.log(JSON.stringify(result, null, 2))),
catchError(this.handleError('post', []))
);
}
And I was able to get the data from PHP using Phalcon with
$app = new \Phalcon\Mvc\Micro();
$app->post('/upload', function() use ($app) {
$input = $app->request->getJsonRawBody();
// $input now contains my JSON data
});
Some time later, I needed to send a file so I used this answer with some minor modifications:
postFile(fileToUpload: File, endpoint: string): Observable<any> {
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
return this.httpClient
.post(endpoint, formData, { headers: {'Authorization': this.jwt} }).pipe(
tap(result => this.log(JSON.stringify(result, null, 2))),
catchError(this.handleError('post', []))
);
}
And I received my file with no problems using the documentation as a guide:
$app->post('/uploads', function() use ($app) {
if ($app->request->hasFiles() == true) {
foreach ($app->request->getUploadedFiles() as $file) {
$file->moveTo('files/' .$file->getname());
}
} else {
$app->response->setStatusCode(400)->sendHeaders();
$app->response->setJsonContent(['error' => 'no file']);
return $app->response;
}
});
The problem: Now I would like to send both a file and some JSON data at the same time. I can always just upload the file and then send the data separately but I don't think that's the right way to do it. I don't want to make more than the minimum number of network calls.
What I've tried: Using the file upload code and simply appending another field to my FormData object with my JSON data
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', JSON.stringify(data));
and a variation of that
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', new Blob([JSON.stringify(data), {type: 'application/json'}]);
Either way, on the backend I can get the file but $app->request->getJsonRawBody and $app->request->getRawBody are empty.
I also tried using the original JSON-sending code and just changing a bit to include the file but with no success.
post(fileToUpload: File, data: CustomData): Observable<any> {
this.messageService.add('uploaded file');
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', JSON.stringify(data), 'data');
return this.http
.post(this.apiUrl + 'uploads/', {'data': data, 'file': fileToUpload}, HTTP_OPTIONS).pipe( // file is empty on the server like this
tap(result => this.log('POST file :\n' + JSON.stringify(result, null, 2))),
catchError(this.handleError('post', [], 'fileUpload'))
);
}
I can easily send either my JSON data or the file but not both.
I searched the Phalcon documentation and several QAs on sending files and/or JSON with Angular but I cannot figure out how to make this work.
You are sending json as text in post request, so instead of $app->request->getJsonRawBody you should try something like
$rawJson=$app->request->getPost('data');
$object=json_decode($rawJson);
you can get your json as #Błażej Kowalczyk said
$this->request->getPost()
and you can check for files and get them
if ($this->request->hasFiles()) {
foreach ($this->request->getUploadedFiles() as $file) {
// $file is an instance of Phalcon\Http\Request\File
var_dump($file->getName());
}
}
check these pages for more information
https://docs.phalconphp.com/3.4/en/api/phalcon_http_request
https://docs.phalconphp.com/3.4/en/api/phalcon_http_request_file

Update view angular array push

I am trying to handle the push update in Angular in the view but it has been impossible for me. I know the following:
I have an array, this array is called marca1 and it receives all the objects that the get request that I make to the server and it shows in the view with ng-repeat.
When I send the post request to save a new data, it gets a response from the server that I save it in an object called pepa.
I use the push function for my fix to refresh the view, but that does not work.
Why can it be failing? How can I fix it?
This is my code:
miAppAngular.controller('marca',function($scope,$http,$location,$routeParams,configuracionGlobal){
$scope.config = configuracionGlobal;
$scope.marca1=[];
$http.get( configuracionGlobal.api_url + "/marca/listaMarca.php")
.then( function(respuesta){
$scope.marca1=respuesta.data;
});
$scope.nuevaMarca = function ( ){
$scope.newMarca={
'nombre':$scope.nombreMarca
}
$scope.pepa={};
//
$http({
url: configuracionGlobal.api_url + "/marca/nuevaMarca.php",
method: "POST",
data: $scope.newMarca,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(
function(respuesta){
$scope.pepa= respuesta;
$scope.marca1.push($scope.pepa);
$('#modalMarca').modal('hide');
}
)
}
Try to run getMarca after posting:
$scope.getMarca = function() {
$http.get( configuracionGlobal.api_url + "/marca/listaMarca.php")
.then(function(respuesta)
{
$scope.marca1=respuesta.data;
});
}
In your .then() of your post, at the end call: $scope.getMarca()
This shall update the array $scope.marca1.
The response returned after a POST is usually used for checking; whether it was a success or failure (or to return custom values from backend).

$http headers is not a function - angularjs

I am posting data to Dynamics CRM via SOAP on my PHP server with cURL. After this is done it is giving the entity GUID in the form of a HTTP Response header. When attempting to access this via my angular factory and $http.
My header is exposed and is able to be viewed in Chrome Developer tools and gives me the GUID I need.
The code for accessing the promise data is as follows:
$http({
method: 'POST',
url: url,
data: formData,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function (data, headers) {
var array = [];
array.data = data;
array.headers = headers('EntityId');
console.log(array.headers);
deferred.resolve(array);
})
return deferred.promise;
//etc
The error I get is:
headers is not a function()
I can however, access some header result such as a status 200 code by using:
array.headers = headers;
But I need to access my custom header. Any ideas on how I can achieve this?
As per Deprecation Notice on https://docs.angularjs.org/api/ng/service/$http
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
the preferred way would be:
$http.get('/someUrl')
.then(function(response){
var array = [];
array.data = response.data;
array.headers = response.headers('EntityId');
});
As Andy said already, headers is the 3rd parameter of the success callback. So you will have to do this:-
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
})
I wasn't going to add this as an answer but doing this as I wanted to add that headers is indeed a function.
In my project, I did the below and saw function logged out as type in console. The function returns the value of the header item corresponding to the name passed, if no parameters are passed, returns an object containing all headers.
login(user) {
return this.$http.post(this.url, user)
.success((data, status, headers, config) => {
console.log(typeof headers, 'headers'); => prints function
console.log(headers(), 'headers'); => if you don't pass anything, returns an object containing all headers.
return response;
});
}
Excerpt from the angular code.
function headersGetter(headers) {
var headersObj;
return function(name) {
if (!headersObj) headersObj = parseHeaders(headers);
if (name) {
var value = headersObj[lowercase(name)];
if (value === void 0) {
value = null;
}
return value;
}
return headersObj;
};
You parameters for success are incorrect. headers is the third parameter.
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Check "Usage" section in https://docs.angularjs.org/api/ng/service/$http for reference.
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise.
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers –{function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Angular version == 1.3.5 , Suppose header value has been set "X-AUTH-TOKEN = 'eyJwYXNzd29yZCI6ImFkbWlu'" in Application Security class after authentication.
$scope.postData = "{\"username\" : username , \"password\": password ,\"email\" :email}";
$http({
method: 'POST',
url: '/API/authenticate',
data: postData,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Login-Ajax-call": 'true'
}
})
.then(function(response) {
if (response.data == 'ok') {
$cookies['X-AUTH-TOKEN']=response.headers('X-AUTH-TOKEN');
// below put,put,putObject Cookies value is valid for Angular version >= 1.4
// $cookies.putObject('X-AUTH-TOKEN',response.headers('X-AUTH-TOKEN');
window.location.replace('/');
}
else {
// Error Message...
}
});

Categories