I tried to get an success response from my ajax recall but it failed.
When I open the dev tool in chrome I can see the response and it is composed of my json response and also the class name which is triggered in my .php file. This throwns then an exception in my console.
This are the script how I made the call, triggering by a click of a button.
jquery.backend.js
$('#save-config-map').on('click', function () {
$.ajax( {
url: '../../ajax/ajax_config_map.php',
success: function (response) {
console.log(response.error);
}
});
});
ajax_config_map.php
require_once($_SERVER['DOCUMENT_ROOT'] . 'loader.php');
use Db\DatabaseConfigMap;
$insertDataConfigMap = new DatabaseConfigMap();
$result = $insertDataConfigMap->insertConfigDataAllDB();
$results = array(
'error' => $result
);
echo json_encode($results);
DatabaseConfigMap.php
namespace Db;
use \PDO;
use PDOException;
class DatabaseConfigMap extends DatabaseMain {
public function __construct() {
parent::__construct();
}
public function insertConfigDataAllDB()
return 'Test';
}
}
DatabaseMain.php
namespace Db;
use \PDO;
require_once(DATABASE_DIR);
class DatabaseMain
{
protected string $servername;
protected string $dbname;
protected string $username;
protected string $password;
public function __construct() {
$dsn = sprintf("mysql:host=%s;dbname=%s;charset=%s", DB_HOST, DB_DATABASE, DB_CHARSET);
$this->conn = new PDO($dsn, DB_USERNAME, DB_PASSWORD);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}
loader.php <-- loading all my classes
$rootDir =CLASSES_DIR;
$autoload = function($className) use($rootDir){
var_dump($className);
$fileName = '';
if($lastNameSpacePosition = strpos($className,'\\')){
$namespace = substr($className, 0,$lastNameSpacePosition);
$className = substr($className,$lastNameSpacePosition+1);
$fileName = str_replace('\\',DIRECTORY_SEPARATOR,$namespace).DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className);
if(is_file($rootDir.$fileName.'.php')){
require_once $rootDir.$fileName.'.php';
}
};
spl_autoload_register($autoload);
I cut some code where I insert the data in my database. This code works very well but as I said, the response is:
string(20) "DB\DatabaseConfigMap"...{error: 'Test'}
error: "Test"
Thanks for all the help
Marcus
I used the dev tool from chrome to analyse the error and checked the board and google for solution.
You need to specify in ajax that the response will be in json format
$.ajax({
url: 'example.com',
data: {
// key and values
},
dataType: 'json', // your case requires datatype json
})
specify the dataType: 'json' in
$.post({
url: ``,
data: data_to_backend,
dataType: 'json', // the return type format from backend
})
put this before your echo json_encode($x) for 200 response
header("HTTP/1.1 200 OK");
Related
I have a web app (built using ExtJS) where I let users update their basic info. I don't have problems with most of the update routine. However, when I tried updating a user with an ñ in their name, the PHP changed this to the Unicode u00f1.
For example, I pass the name Añana, which PHP shows is Au00f1ana, where "u00f1" replaced "ñ".
I already tried setting the charset to utf-8, htmlspecialchars, mb_convert_encoding, utf8-decode, and html_entity_decode, but none worked.
What I did to get around this problem is to use strpos and substr_replace to just replace the utf code with the original character.
if(strpos($my_string, 'u00f1') !== FALSE){
$start_index = strpos($my_string, "u00f1");
$last_name = substr_replace($my_string, "ñ", $start_index, 5);
}
elseif(strpos($my_string, 'u00F1') !== FALSE){
$start_index = strpos($my_string, "u00F1");
$last_name = substr_replace($my_string, "Ñ", $start_index, 5);
}
For more context, this is the store I use:
Ext.define('AppName.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'AppName.model.model_for_store',
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json',
'Ext.data.writer.Json'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
remoteFilter: true,
remoteSort: true,
storeId: 'MyStore',
batchUpdateMode: 'complete',
model: 'AppName.model.model_for_store',
proxy: {
type: 'ajax',
batchActions: false,
api: {
create: 'folder/folder/create.php',
read: 'folder/folder/read.php',
update: 'folder/folder/update.php',
destroy: 'folder/folder/delete.php'
},
url: '',
reader: {
type: 'json',
keepRawData: true,
messageProperty: 'message',
rootProperty: 'data'
},
writer: {
type: 'json',
writeAllFields: true,
encode: true,
rootProperty: 'data'
}
}
}, cfg)]);
}
});
And this is the start of the PHP file that gets triggered for update:
<?php
require_once('../db_init.php');
require_once '../lib/response.php';
require_once '../lib/request.php';
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('default_charset', 'utf-8');
header("content-type: text/html; charset=UTF-8");
error_reporting(E_ALL);
define('CHARSET', 'ISO-8859-1');
define('REPLACE_FLAGS', ENT_COMPAT | ENT_XHTML);
class my_object{
//..... variables
}
$request = new Request(array());
if(isset($request->params)){
$array_r=$request->params;
$inputData->last_name=($array_r->last_name);
$inputData->first_name=($array_r->first_name);
$inputData->middle_name=($array_r->middle_name);
}
else{
//echo "Update of User failed";
$res = new Response();
$res->success = false;
$res->message = "Update User Failed!";
$res->data = array();
print_r($res->to_json());
}
?>
And as a reference, here's my Request.php file
<?php
class Request {
public $method, $params;
public function __construct($params) {
// $this->restful = (isset($params["restful"])) ? $params["restful"] : false;
$this->method = $_SERVER["REQUEST_METHOD"];
$this->parseRequest();
}
protected function parseRequest() {
// grab JSON data if there...
$this->params = (isset($_REQUEST['data'])) ? json_decode(stripslashes($_REQUEST['data'])) : null;
if (isset($_REQUEST['data'])) {
$this->params = json_decode(stripslashes($_REQUEST['data']));
} else {
$raw = '';
$httpContent = fopen('php://input', 'r');
//print_r($httpContent);
while ($kb = fread($httpContent, 1024)) {
$raw .= $kb;
}
$params = json_decode(stripslashes($raw));
if ($params) {
$this->params = $params->data;
}
}
}
}
?>
Although I've checked ExtJS's documentation, and for the encode property in the JSONWriter, it says:
Configure `true` to send record data (all record fields if writeAllFields is true) as a JSON Encoded HTTP Parameter named by the rootProperty configuration.
So my model data is being sent as a JSON Encoded HTTP Parameter, and the PHP is able to parse it because the rootProperty is data, which matches line 19 in my request.php file:
$this->params = (isset($_REQUEST['data'])) ? json_decode(stripslashes($_REQUEST['data'])) : null;
I think the json_decode(stripslashes(...)) is the one causing ñ` to be converted to the utf-8 equivalent, and the stripslashes removed the leading backslash we usually see with the utf-8.
I have a feeling there's a better way to write this that won't convert the ñ to utf-8.
Does anyone have a better solution to this one?
Solved it. The problem was the stripslash in the request.php file.
When ExtJS sends the data through the Store, I use encode, which puts it as an encoded JSON parameter. Normally it wouldn't be a problem when the request.php file gets it and runs json_decode, given that there were no escaped special characters. The problem is when I hit the ñ, it was converted to \u00f1, and the leading slash was trimmed. json_decode presumably did not recognize it again since there was no leading slash.
Major credits to IMSoP in the comments for the lead.
Method to get Data: I am trying to get data with axios. But there is no result is coming and also there is no error!!!!!
getTodoList() {
axios({
method: 'GET',
url: 'api/todos.php'
}).then(function(res){
console.log(res);
})
}
It is giving me this Result:
api.todos.php
<?php
class Todo {
private $connection_string ;
public function __construct() {
// connection code. Connection is okay.
}
public function fetchTodo() {
$sql = "SELECT * FROM todo ";
$result = mysqli_query($this->connection_string, $sql);
}
}
$todo = new Todo;
$todo->fetchTodo();
?>
What is the problem, I can't understand!!
I'll assume you want your API to return JSON data.
As you can see from your screenshot, your PHP code is currently sending a (empty) HTML response: headers: { [...] content-type: "text/html; charset=UTF-8", [...] }. That is the default for PHP, if you intend to output JSON you will have to explicitly send the correct header.
Since your function is named fetchTodo() I will only make it fetch the data and deal with outputting it as JSON somewhere else.
<?php
class Todo {
private $connection_string ;
public function __construct() {
// connection code. Connection is okay.
}
public function fetchTodo() {
$sql = "SELECT * FROM todo ";
$result = mysqli_query($this->connection_string, $sql);
// add this line
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
}
}
// tell whoever requested this API that we're going to send JSON data
header("Content-Type: application/json");
$todo = new Todo;
// output whatever fetchTodo() returns as JSON
echo json_encode($todo->fetchTodo());
?>
Note that this does not handle any query errors. I'll assume your connection code sets error reporting up properly. If you don't already have one, you might consider adding a global error handler to send a JSON response if things break, perhaps something like this.
I am trying to display records from query in a table and on button clicked to make an ajax call to download the information in an xml format. The query is executed from method inside a class and the ajax request makes call to a different method inside the same class. The first method fills two private properties inside the class and the second property(the one called through the ajax request) must read the properties and fill the data inside table and make the file downloadable. When I try to read the properties from the same class though I get nulls and the foreach returns an error.
This is my ajax request(downloaderScript.js):
;
$("#downloadBtn").click(function (event) {
event.preventDefault();
event.stopPropagation();
$.ajax({
url: 'allClients.php',
type: 'post',
data: {action: 'downloader'},
complete: function (result) {
console.log(result);
},
error: function () {
console.log('Error');
}
});
});
This is the class from which I call the first and the second methods:
class HttpHandlerClient extends HttpHandlerAbstract
{
private $clientsService;
public $storedClientsHeadings;
public $storedClientsData;
public function viewAllClients()
{
$data = $this->clientsService->getAllClients(clientEntity::class);
if(isset($data)) {
$this->storedClientsHeadings = ["Client Names:", "Delivery Address:", "Phone number:"];
$this->storedClientsData = $data;
$this->render('allClientsView', $data);
}
else
{
$this->redirect('clientAdd');
}
}
public function downloader()
{
header("Content-Type: text/plain");
var_dump($this->storedClientsHeadings);
foreach ($this->storedClientsHeadings as $arrayName)
{
echo implode("\t", $arrayName)."\r\n";
}
/**
* #var clientEntity $clientData
*/
foreach ($this->storedClientsData as $clientData)
{
echo implode("\t", $clientData->getClientName())."\r\n";
echo implode("\t", $clientData->getAddressForDelivery())."\r\n";
echo implode("\t", $clientData->getPhone())."\r\n";
}
$filename = "clients_".date("Y-m-d").".xls";
header("Content-Disposition:attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
}
And this is the php file that i use between my ajax request and the php class(The file name is: allClients.php, in common.php I make an instance of the class HttpHandlerClient):
require_once 'common.php';
if(isset($_POST['action'])){
$myHttpHandlerClient->downloader();
} elseif (isset($_GET['typer'])) {
$myHttpHandlerClient->viewClientByNumber($_GET['typer']);
} else {
$myHttpHandlerClient->viewAllClients();
}
Sorry if my question is trivial, I even started doubting that after require_once I re-run the code in common.php, making a new instance of HttpHandlerClient and because of this I get nulls in the properties. But when I was reading the documentation in php's site I did not read such a thing. Any help will be appreciated, thanks.
It sounds like what may be happening is that there is a disconnect between the javascript initially loading and then more markup being added to the DOM.
The page loads up which runs your javascript. At this point the JS only knows what is currently on the page.
Your make the first call which changes the DOM. Your javascript does not know about these changes.
You try to reference something that has not been recognized by your initial load of the Javascript.
After you make the call that changes the DOM, you may have to reinitialize your JS to recognize the changes.
Good luck
I have button on html like this:
<button class="uk-button uk-button-primary uk-modal-close confirm-rules" type="button" onclick="sendStatus('accept_rules')">Rozumiem</button>
and I want to do it when I click on the button, the function in php will be called.
I try do this by ajax like this:
<script type="text/javascript">
function sendStatus(status) {
$.ajax({
method: "POST",
url: "Controllers/Core/Dashboards/Admin/Dashboard.php",
data: { status: status }
}).done(function( msg ) {
alert("Cookie saved:" + msg );
});
}
</script>
The problem is with php file, because it's look like this:
<?php
declare(strict_types=1);
namespace App\Controllers\Core\Dashboards\Admin;
use App\Controllers\Controller;
use App\Core\SessionManagement;
use App\Core\Request;
use App\Core\Cookies;
class AdminDashboard extends Controller
{
private $cookies;
/**
* AdminDashboard constructor.
* #param Cookies $cookies
*/
public function __construct(Cookies $cookies)
{
$this->cookies = $cookies;
}
public function acceptDashboardBox()
{
if ( isset($_POST['status']) )
{
$this->cookies->add( $_POST['status'], 'true', 'time() + (365 * 24 * 60 * 60)');
}
}
/**
*
*/
public function index() : void
{
Controller::renderView('Core/Dashboards/Admin/Dashboard');
}
}
Button must run function acceptDashboardBox() on class AdminDashboard.
How i can do this?
When calling your file Controllers/Core/Dashboards/Admin/Dashboard.php, nothing will happen because nothing calls the function acceptDashboardBox() or anything else in this file.
Please always make sure that your PHP Classes do have the name of the file that you are currently in (PSR-4). The name of your class is AdminDashboard, so call your file AdminDashboard.php to avoid confusion. Also it is common practice to use Event Listeners for click events instead of calling a function onclick=.
To let PHP only call your function acceptDashboardBox() you would need a new endpoint/file that does that same as your function and nothing else.
I would suggest you return a json with a status and catch exceptions that set the status if one occurs to something that indicates an error occurred. You can check the json in your javascript and check if the operation was successful or not. Something like:
{
status: "success"
}
OR
{
status: "failure"
}
would do the deal.
Angular 6 :
import {Injectable} from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class GetData {
constructor( private http: HttpClient ) { }
post( ) {
data = [ {username : 'test',password : '1234' }];
return this.http.post('login.php' , data );
}
}
PHP : login.php
<?php
$username = $_POST['username'];
$password = $_POST['password'];
?>
How can i get data from Angular 6 that is [Object] into $username , $password
**
"$_POST" and "$_REQUEST" is not available for me.
**
Try this:
import {Injectable} from '#angular/core';
import { HttpClient,HttpParams } from '#angular/common/http';
#Injectable()
export class GetData {
constructor( private http: HttpClient ) { }
post( ) {
let data= new HttpParams()
.append("username", "test")
.append("password", "1234")
return this.http.post('login.php' , data );
}
}
For some reason Angular seems to send POSTs that end up in php://input instead of $_POST, and then you can json_decode them into an object and use them.
On the Angular side - I'm just tossing data at the server, I care not about the response... tried getting it going without the whole subscribe() thing but it wouldn't POST at all for me at that point... Note taht there is a private http: Http in the constructor for the TS file/component/class this is in...
postChatMessage(room: string, user: string, msg: string, timestamp: number) {
var cmsg = new ChatMessage(room, msg, user, timestamp);
return this.http.post(BASEURL + "/chat", cmsg)
.subscribe(
(v) => {},
response => {},
() => {}
);
}
The PHP on the back end that handles the POST that sends - yes, I'm being lazy and just storing the whole JSON string sent plus a few other things, but easier for me to deal with for a quick school thing -
if (($_SERVER['REQUEST_METHOD'] == "POST") &&
(strpos($_SERVER['REQUEST_URI'], "/json_service/chat") === 0)) {
$d = file_get_contents("php://input");
$d = json_decode($d);
$d->timestamp = time();
$q = "insert into json_chat values(?,?,?,?)";
$a = array(null, time(), $d->room, json_encode($d));
$res = executeQuery($q, $a);
print(json_encode(array($res[0]))); // boolean fwiw
exit;
}