Jump to content

A Correct Way to Read via an AJAX or similar HTTP Request the Output of a PHP Routine


iwato

Recommended Posts

BACKGROUND:  I have created a PHP routine that gathers data from a MySQL database.  The data that it gathers depends  on the value of an HTTP request that uses the $_GET superglobal as its transfer mechanism.  The routine further organizes the retrieved information into a nested array such that each element of the array corresponds to a different table row, and each element of each nested array corresponds to a subset of the table fields.  Once the nested array has been completed the json_encode() function converts the array into a JSON string and readies it for transport.

The PHP

<?php
	if(isset($_GET['podType']) {
		define('_HOST_NAME','...');
		define('_DATABASE_NAME','...');
		define('_DATABASE_USER_NAME','...');
		define('_DATABASE_PASSWORD','...');
		$mysqli_obj = new MySQLi(_HOST_NAME,_DATABASE_USER_NAME,_DATABASE_PASSWORD,_DATABASE_NAME);
		if($mysqli_obj->connect_errno) {
			die("ERROR : -> ".$mysqli_obj->connect_error);
		}
		$tbl_name = 'rss2_podcast_item';
		$podcast_items = [];
		$result_obj = $mysqli_obj->query("SELECT * FROM " . $tbl_name);
		while($row = $result_obj->fetch_assoc()) {
			foreach($row as $key => $value) {
				$item_arr[$key] = $value;
			}
			$items[] = $item_arr;
		}
		//Creates a nested array whose subarrays consist of the four indicated elements.
		foreach ($items as $sub_arr => $element) {
			$podcast_item[] = $element['podcast_no_item'];
			$podcast_item[] = $element['item_title'];
			$podcast_item[] = $element['item_description'];
			$podcast_item[] = $element['item_pubdate'];
			$podcast_items[] = $podcast_item;
			$podcast_item = [];
		}
		echo json_encode($podcast_items, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_NUMERIC_CHECK);
	}
?>

The Javascript

<script>
	$(document).ready(function() {
		$('li.podDex').each(function(){
			var podType = $(this).attr('id');
			//Causes the weight of the font to change when the mouse passes over the text.
			$('#'+podType).mouseover(function() {
					$(this).css({"cursor": "pointer", "font-weight":"800"});
				})
				.mouseout(function() {
					$(this).css("font-weight", "normal");
			});
			//Causes the weight of the font to change, displays the hidden text to appear in the #main <div> element, and brings about a change in color.
			$('#'+podType).mouseover(function() {
					$(this).css({"cursor": "pointer", "font-weight":"800"});
				})
				.click(function() {
					$.getJSON({
						url: "../exp1/ajax_data.php",
						data: podType,
						success: function(json_data){
							var data_array = $.parseJSON(json_data);
							alert(data_array[0]['podcast_no_item']);
						}
					});
				})
				.mouseup(function() {
					$(this).css({"color": "#fadb9d","font-weight": "normal"});
				$('body, html').animate({scrollTop: $('#main').offset().top},800);
			});
		});
	});
</script>

The HTML

					<ul>
						<li id='linear' class='podDex'>Linear Analysis</li>
						<li id='clausal' class='podDex'>Clausal Analysis</li>
						<li id='inversion' class='podDex'>Socratic Inversion</li>
						<li id='chronology' class='podDex'>Chronology</li>
					</ul>

The Console Error Message is

Quote

"Failed to load resource:  The server responded with a status of 404  (Not Found)

You are welcome to try it yourself.  Please go to Grammar Captive and click on any of the four designated <li> elements.

QUESTION:  What might be causing the $.getJSON() call to fail?  

NOTE:  A similar, but not identical, result occurs on my local  test server.

Link to comment
Share on other sites

OK.

Here are the two paths:

... /experimentation/exp2/podcast_index.php

.../experimentation/exp1/ajax_data.php

The value of the URL property of the AJAX object in podcast_index.php is

url: "../exp1/ajax_data.php",

I have checked the spelling of each folder and file.  I find nothing wrong.  Any other ideas?

This is what the Javascript Console returns as part of the error message.

http://www.grammarcaptive.com/podcasting/experimentation/exp2/[object Object]

Is $.getJSON looking for a JSON object as the value of a defined variable, when indeed, I am only echoing the JSON string?  If this is the problem what form should the variable  take?  Can I use a PHP variable?  Must it be a Javascript variable?  How should I set the datatype of the $.ajax() or $.getJSON() PlainObject to correspond?

Truly, I do not know how AJAX retrieves its desired information.  Does it scan the entire page looking for a variable name?  Does it look for some sort of page output?  Or, does it simply read everything of the designated data type regardless if it is needed?  None of the literature that i have read tells what truly happens once the designated URL has been accessed.

Edited by iwato
Link to comment
Share on other sites

When you see "[object Object]", that means you're trying to print an object (or otherwise use the object in a string context).  When Javascript converts an object to a string that's what the result is.  So, wherever that URL is being built, you're trying to append an entire object to the end of it.

Link to comment
Share on other sites

Are you suggesting that the PHP echo statement produces an object?  I just replaced the following with the code that follows.

FOLLOWING CODE

echo json_encode($podcast_items, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_NUMERIC_CHECK);

CODE THAT FOLLOWS

<?php
		...

		$json_data = json_encode($podcast_items, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_NUMERIC_CHECK);
?>
		<script>
			var json_data = '<?php echo $json_data; ?>';
		</script>
<?php

Still no change: the alert does not appear and the error message along with the accompanying URL remain the same.

Roddy

Link to comment
Share on other sites

No, it isn't PHP, that's Javascript which does that.  When you print an object from PHP it does something else, that output is coming from Javascript.  Find the part where that URL is actually built.  If it's somewhere in the JSON structure, find it and see what's being appended to the URL and if it needs to be something else.

Link to comment
Share on other sites

This is all that I am doing.

					$.getJSON({
						url: "../exp1/ajax_data.php",
						data: podType,
						success: function(json_data){
							var data_array = $.parseJSON(json_data);
							alert(data_array[0]['podcast_no_item']);
						}
					});

I read this in simple English as, "Send an HTTP request with the value of podType to '../exp1/ajax_data.php'. Discover  a variable called json_data in ajax_data.php" .  Read the value of json_data into the success call  function for further processing.   Convert the JSON string into a JSON object and extract from it the value of the first element of the first subarray of the Javascript array just created.

This too fails.

Is this the source of the problem?  Must this be stringified before it is sent back to the requesting file?

[[60,"New Title","Test","2017-06-19 17:26:41"],[51,"The First Tri-Lateral Attempt","Having rearranged the PHP code, the MySQL database will not be updated until all mandatory elements have been completed and the submit button is depressed.","2017-06-18 09:50:37"],[52,"Cooperation","New description","2017-09-24 11:00:17"],[52,"New Title","New description","2017-06-18 09:56:36"],[53,"Experiment One","Test","2017-06-18 10:24:49"],[54,"Experiment Two","Test","2017-06-18 10:31:48"],[54,"Experiment Two","Test","2017-06-18 10:31:48"],[55,"Experiment Three","Test","2017-06-18 11:10:56"],[55,"Experiment Three","Test","2017-06-18 11:10:57"],[55,"Experiment Three","Test","2017-06-19 08:43:49"],[55,"Experiment Three","Test","2017-06-19 08:43:49"],[57,"Eureka_3","I have found it.","2017-09-24 11:03:50"],[58,"Is it ready?","It sure looks like it.","2017-06-19 15:44:59"],[58,"Is it ready?","It sure looks like it.","2017-06-19 17:21:11"],[60,"New Title","Test","2017-06-19 17:24:23"],[60,"New Title","Test","2017-06-19 17:26:41"],[60,"New Title","Test","2017-08-18 08:21:45"],[63,"Test","Test","2017-08-18 08:21:27"],[64,"Podcast #64","Practice Podcast","2017-08-18 08:21:04"],[65,"Transition Without End","There is a time for everything including a time to end.","2017-08-18 08:20:42"],[60,"New Title","Test","2017-06-19 17:26:41"]]

 

Edited by iwato
Link to comment
Share on other sites

If that function is supposed to receive a JSON string, then you shouldn't wrap the response inside script tags in PHP.  Output only the JSON data if that's what the callback function expects.  If you try to parse the script tags and variable declaration it's going to be a JSON parse error, because the script tags and variable declaration are not part of JSON.

Also, if podType is a scalar or primitive value, like a string ID, then you aren't passing it right, you need to give it a name.  Right now you're just sending a value.  I believe you can do that like this:

data: {varName: podType}

Then, in PHP, you would look up $_GET['varName'] or $_POST['varName'] (I think that getJSON sends a get request, but I might be wrong) to look up the value that was passed, in this case the value of the podType variable.  Each thing that gets passed in a get or post request needs both a name and value.

There's still a piece missing, though.  If this is the URL with the problem:

http://www.grammarcaptive.com/podcasting/experimentation/exp2/[object Object]

Then you must be building that URL somewhere, and I haven't seen the code that does that.

Link to comment
Share on other sites

1) No.  I am not building the URL,  I am simply entering it as a relative path.

2) Also, because $.getJSON() appears to be  a special case of $.ajax(), I should think that it follows the same rules for the data parameter.  This is what it says for the parameter for $.ajax(). 

Quote
  • data
    Type: PlainObject or String or Array
    Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See processData option to prevent this automatic processing. Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below).

So, I believe you are correct about the reformatting of the value that I enter for the data parameter. 

3) You wrote:

Quote

If that function is supposed to receive a JSON string, then you shouldn't wrap the response inside script tags in PHP.  Output only the JSON data if that's what the callback function expects.

Yes, but how to I output the JSON string.  Originally, I did it as a PHP echo statement. 

I understand far too poorly what $.ajax() does when the dataType is 'JSON'.  I changed the data parameter to read 

					$.getJSON({
						url: '../exp1/ajax_data.php',
						data: {'podType': podType},
						success: function(jsonData){
							var data_array = $.parseJSON(jsonData);
							alert(data_array[0]['podcast_no_item']);
						}
					});

and the data file to read

<?php
	if(isset($_GET['podType']) {
		define('_HOST_NAME','baha.lunarbreeze.com');
		define('_DATABASE_NAME','thege0_grammarcaptive');
		define('_DATABASE_USER_NAME','thege0');
		define('_DATABASE_PASSWORD','Liberty2015');
		$mysqli_obj = new MySQLi(_HOST_NAME,_DATABASE_USER_NAME,_DATABASE_PASSWORD,_DATABASE_NAME);
		if($mysqli_obj->connect_errno) {
			die("ERROR : -> ".$mysqli_obj->connect_error);
		}
		$tbl_name = 'rss2_podcast_item';
		$podcast_items = [];
		$result_obj = $mysqli_obj->query("SELECT * FROM " . $tbl_name);
		while($row = $result_obj->fetch_assoc()) {
			foreach($row as $key => $value) {
				$item_arr[$key] = $value;
			}
			$items[] = $item_arr;
		}
		//Creates a nested array whose subarrays consist of the four indicated elements.
		foreach ($items as $sub_arr => $element) {
			$podcast_item[] = $element['podcast_no_item'];
			$podcast_item[] = $element['item_title'];
			$podcast_item[] = $element['item_description'];
			$podcast_item[] = $element['item_pubdate'];
			$podcast_items[] = $podcast_item;
			$podcast_item = [];
		}
		$json_data = json_encode($podcast_items, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_NUMERIC_CHECK);
	}
?>
<script>
	var jsonData = '<?php echo $json_data; ?>';
	jsonData = JSON.stringify(jsonData);
</script>
  1.  

Edited by iwato
Link to comment
Share on other sites

I also tried this

<?php
...
?>
<script>
	(function jsonOutput() {
		var jsonData = '<?php echo $json_data; ?>';
		jsonData = JSON.stringify(jsonData);
		return jsonData;
	})()
</script>

but still, the error message and associated link remain unchanged.

Edited by iwato
Link to comment
Share on other sites

Yes, I have cleared the cache.

You are welcome to try it at http://www.grammarcaptive.com/podcasting/experimentation/exp2/podcast_index.php

Find the <div> entitled Navigation Bar and click on any of the menu items.  Each will send a different value for podType, but the if condition that controls the PHP in the data file does not care what it receive, just so long as it is something.

Roddy

Edited by iwato
Link to comment
Share on other sites

I even found a missing parenthesis in the condition expression of the if-statement and fixed that.  Still, the error message remains the same.

 

 

Link to comment
Share on other sites

Although I am happy to report that I have managed to rid myself of the Object: object and am likely now in communication with the data file, I am still unable to achieve the desired result -- namely, the Javascript alert ( ) and more positive feedback from the introduction of the  console.log( ) method.

I believe that there were several coding mistakes that were bringing about the original error message including a missing parenthesis in the condition of the data file's if-statement and my treatment of the $.getJSON arguments.   I have switched to the $.ajax( ) method, as its format provides me with greater flexibility and a clearer picture of what I am actually trying to achieve.  Further, I have move the Javascript outside of the PHP routine in the requested data file.

In addition, I have checked to insure that the desired JSON object actually exists and  have displayed the result below.  The check was made by turning off the $_GET request and running a simple echo statement of the result.

In addition, please find below the PHP file that generates the JSON string and the AJAX triggered by a click function using the $.ready( ) method.

<?php
	ini_set('display_errors', 1);
	ini_set('display_startup_errors', 1);
	error_reporting(E_ALL);
	if(isset($_GET['podType'])) {
		define('_HOST_NAME','...');
		define('_DATABASE_NAME','...');
		define('_DATABASE_USER_NAME','...');
		define('_DATABASE_PASSWORD','...');
		$mysqli_obj = new MySQLi(_HOST_NAME,_DATABASE_USER_NAME,_DATABASE_PASSWORD,_DATABASE_NAME);
		if($mysqli_obj->connect_errno) {
			die("ERROR : -> ".$mysqli_obj->connect_error);
		}
		$tbl_name = 'rss2_podcast_item';
		$podcast_items = [];
		$result_obj = $mysqli_obj->query("SELECT * FROM " . $tbl_name);
		while($row = $result_obj->fetch_assoc()) {
			foreach($row as $key => $value) {
				$item_arr[$key] = $value;
			}
			$items[] = $item_arr;
		}
		//Creates a nested array whose subarrays consist of the four indicated elements.
		foreach ($items as $sub_arr => $element) {
			$podcast_item[] = $element['podcast_no_item'];
			$podcast_item[] = $element['item_title'];
			$podcast_item[] = $element['item_description'];
			$podcast_item[] = $element['item_pubdate'];
			$podcast_items[] = $podcast_item;
			$podcast_item = [];
		}
		$json_data = json_encode($podcast_items, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_NUMERIC_CHECK);
	}
?>
<script>
	(function jsonOutput() {
		var jsonData = '<?php echo $json_data; ?>';
		jsonData = JSON.stringify(jsonData);
		return jsonData;
	})()
</script>
				.click(function() {
					$.ajax({
						url: '../exp1/ajax_data.php',
						dataType: 'JSON',
						data: {'podType': podType},
						success: function(jsonData){
							var data_array = $.parseJSON(jsonData);
							document.console && console.log(data_array);
							alert(data_array[0]['podcast_no_item']);
						}
					});
				})
[
	[60,"New Title","Test","2017-06-19 17:26:41"],
	[51,"The First Tri-Lateral Attempt","Having rearranged the PHP code, the MySQL database will not be updated until all mandatory elements have been completed and the submit button is depressed.","2017-06-18 09:50:37"],
	[52,"Cooperation","New description","2017-09-24 11:00:17"],
	[52,"New Title","New description","2017-06-18 09:56:36"],
	[53,"Experiment One","Test","2017-06-18 10:24:49"],
	[54,"Experiment Two","Test","2017-06-18 10:31:48"],
	[54,"Experiment Two","Test","2017-06-18 10:31:48"],
	[55,"Experiment Three","Test","2017-06-18 11:10:56"],
	[55,"Experiment Three","Test","2017-06-18 11:10:57"],
	[55,"Experiment Three","Test","2017-06-19 08:43:49"],
	[55,"Experiment Three","Test","2017-06-19 08:43:49"],
	[57,"Eureka_3","I have found it.","2017-09-24 11:03:50"],
	[58,"Is it ready?","It sure looks like it.","2017-06-19 15:44:59"],
	[58,"Is it ready?","It sure looks like it.","2017-06-19 17:21:11"],
	[60,"New Title","Test","2017-06-19 17:24:23"],
	[60,"New Title","Test","2017-06-19 17:26:41"],
	[60,"New Title","Test","2017-08-18 08:21:45"],
	[63,"Test","Test","2017-08-18 08:21:27"],
	[64,"Podcast #64","Practice Podcast","2017-08-18 08:21:04"],
	[65,"Transition Without End","There is a time for everything including a time to end.","2017-08-18 08:20:42"],
	[60,"New Title","Test","2017-06-19 17:26:41"]
]

I look forward to a speedy remedy of my ignorance.

Finally, I have replaced the deprecated jQuery .parseJSON() function with the Javascript JSON.parse() function.

Roddy

 

Edited by iwato
Link to comment
Share on other sites

No.  I am not building the URL,  I am simply entering it as a relative path.

OK, apparently this is a communication issue.  That URL IS getting built somewhere, unless you manually typed "[object Object]" onto the end of the URL, which seems like kind of a strange thing for someone to do.  So it really, really sounds like Javascript is building that URL and trying to append an object onto the end of it.  But I'll leave it up to you to work backwards how that URL ends up on the page to figure out why that's happening.  Because my ~20 years of working with Javascript are telling me exactly what's going on, but I haven't seen the code which is actually doing it yet.  If you want to disagree with me, that's fine, but I can't help you.

Yes, but how to I output the JSON string.  Originally, I did it as a PHP echo statement.

That should be fine.  That's what echo is for.  If the Javascript expects JSON, then only output JSON.  Don't output HTML tags or other Javascript code, that's not JSON.  Right now your PHP code is outputting HTML script tags and various other Javascript code, and that's a problem if you're trying to parse JSON.  This should only be a data exchange between PHP and Javascript, all you need is the actual JSON data, nothing else.  Anything else will cause a problem.

Link to comment
Share on other sites

Good morning!

Firstly, I receive a parse error when I echo the PHP variable $json_data without the Javascript.

In contrast, I receive no error message when I use the Javascript.  I believe now that the problem is with the success function.

Find below the two key functions that together produce no error, but still do not produced the expected result -- namely, the alert and a value in the console window.

<script>
	(function jsonOutput() {
		var jsonData = '<?php echo $json_data; ?>';
		jsonData = JSON.stringify(jsonData);
		return jsonData;
	})()
</script>

and

						success: function(jsonData){
							var data_array = JSON.parse(jsonData);
							document.console && console.log(data_array);
							alert(data_array[0]['podcast_no_item']);
						}

and still again,

[
	[60,"New Title","Test","2017-06-19 17:26:41"],
	[51,"The First Tri-Lateral Attempt","Having rearranged the PHP code, the MySQL database will not be updated until all mandatory elements have been completed and the submit button is depressed.","2017-06-18 09:50:37"],
	[52,"Cooperation","New description","2017-09-24 11:00:17"],
	[52,"New Title","New description","2017-06-18 09:56:36"],
	[53,"Experiment One","Test","2017-06-18 10:24:49"],
	[54,"Experiment Two","Test","2017-06-18 10:31:48"],
	[54,"Experiment Two","Test","2017-06-18 10:31:48"],
	[55,"Experiment Three","Test","2017-06-18 11:10:56"],
	[55,"Experiment Three","Test","2017-06-18 11:10:57"],
	[55,"Experiment Three","Test","2017-06-19 08:43:49"],
	[55,"Experiment Three","Test","2017-06-19 08:43:49"],
	[57,"Eureka_3","I have found it.","2017-09-24 11:03:50"],
	[58,"Is it ready?","It sure looks like it.","2017-06-19 15:44:59"],
	[58,"Is it ready?","It sure looks like it.","2017-06-19 17:21:11"],
	[60,"New Title","Test","2017-06-19 17:24:23"],
	[60,"New Title","Test","2017-06-19 17:26:41"],
	[60,"New Title","Test","2017-08-18 08:21:45"],
	[63,"Test","Test","2017-08-18 08:21:27"],
	[64,"Podcast #64","Practice Podcast","2017-08-18 08:21:04"],
	[65,"Transition Without End","There is a time for everything including a time to end.","2017-08-18 08:20:42"],
	[60,"New Title","Test","2017-06-19 17:26:41"]
]

And, still again, if there is doubt or a need for further experimentation.

You are welcome to try it at http://www.grammarcaptive.com/podcasting/experimentation/exp2/podcast_index.php

Edited by iwato
Link to comment
Share on other sites

Firstly, I receive a parse error when I echo the PHP variable $json_data without the Javascript.

In contrast, I receive no error message when I use the Javascript.  I believe now that the problem is with the success function.

Well, you're wrong.  If you're going to use it as JSON, then it needs to be JSON, that's about as simple as it gets.  If you want to fix the parse error, great, we can do that if we see what data you're trying to parse, and what the error message is.  But let's not make incorrect assumptions about what the problem is.  There's no reason to assume anything, everything can be tested.

 

Quote

Find below the two key functions that together produce no error, but still do not produced the expected result -- namely, the alert and a value in the console window.

 

I know exactly why it's not producing the expected result, because you're trying to pass a bunch of HTML tags and Javascript code to a JSON parser.  That's the reason.  But, like I said, there is no reason to make assumptions.  Add some debugging code to your success function and you'll see exactly what it's trying to do:

 

success: function(jsonData){
  console.log('Success callback');
  console.log(jsonData);
  var data_array = JSON.parse(jsonData);
  console.log(data_array);
  alert(data_array[0]['podcast_no_item']);
}

 

When I run your page right now, your success function doesn't even get called, and there's a PHP error message in the response.  I can put a breakpoint on the ajax call to verify that it sends the ajax request, but if I put a breakpoint inside the success function it never gets hit, that function never gets called.  I assume that's because jQuery tries to parse the response as JSON and fails, since it is not JSON, and thus it never calls success.  The ajax method will also accept functions for error which it will call if the request failed, and there's another one called complete that it calls after either success or error.  Right now your success function isn't being called at all, and I assume it's because of the bad data.

Link to comment
Share on other sites

The problem has been resolved by echoing a JSON string produced with json_encode( )  and eliminating the JSON.parse function in the success function.  Apparently the new version of $.ajax( ) parses incoming data strings automatically.

Try it and see:  You are welcome to try it at http://www.grammarcaptive.com/podcasting/experimentation/exp2/podcast_index.php

Link to comment
Share on other sites

That looks better, yes.  You're only sending JSON data, and like you've learned when you specify to jQuery that the data type is JSON, it will automatically parse it and fire the success function only if that worked.  If you did not specify a data type of JSON then it would return the response as a string.

You can also build that array in PHP so that it is an associative array with string names for the keys instead of numbers, and in Javascript that can be decoded as an object with named properties.  So you could have data_array[0].id, data_array[0].title, etc.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...