How to execute PHP and SQL sessions inside Ajax?
I've been asking similar questions here today, but I'm seeing I think the issue is with how I am calling my data?
I'm trying to replace a nav bar with ajax that will load contents into a div.
The nav bar is this:
<ul>
<li><a href="javascript:void(0)" onclick="getData('/includes/view-monthly-calendar-ajax.php', 'targetDiv')">Monthly</a></li>
<li><a href="javascript:void(0)" onclick="getData('/includes/agenda-ajax-include.php', 'targetDiv')">Daily</a></li>
<li><a href="javascript:void(0)" onclick="getData('/includes/hello-include.php', 'targetDiv')">Admin</a></li>
<li><a href="javascript:void(0)" onclick="getData('/includes/view-monthly-calendar-ajax.php', 'targetDiv')">Help</a></li>
</ul>
Then I have this to replace the div:
<div id="targetDiv"></div>
the getData function is an innerHTML request:
<script language = "javascript">
function getData(dataSource, divID)
{
$.ajax({
url: dataSource,
dataType: 'html',
success: function(data) {
$('#' + divID).html(data);
}
});
}
</script>
When I click the nav links, the HTML loads into the div, but the contents of my include files also contain PHP functions and jQuery that needs to execute when being loaded and they are just ignored. I've seen this question asked a lot here, but these seem to only relate to jQuery?
To be clear, when I click the nav links, I get a 200 OK in firebug console, but only HTML is coming back and populating div.
Here is my most recently cleaned include file with changes from Jonathan's suggestions. At this point, I am getting output up the the </tr>
after the help button (line 15) but no output past that...
<?php
session_start();
?>
<table width='100%' border='0'>
<tr class='twentyfivepxheight'><td></td></tr>
<tr>
<td width='40%' valign='top'>
<div class='left_agenda_items'>
<table width='80%' align='center' border='0'>
<tr class='twentyfivepxheight'>
<td align='left' class='title5 bottompadding unselectable'>Daily Agenda<a href="javascript:void(0)" class="supernote-click-note1">
<img src="/images/help-sm.jpg" alt="Help Button" /></a>
</td>
</tr>
<?php
$numric_time = getNumericTime($_SESSION['userData']['timezone']);
$query = "SELECT * FROM events WHERE date(convert_tz(StartDate,'+00:00','". $numric_time."'))='$currentDate' AND UserID='" . $_SESSION['userData']['UserID'] ."' ORDER BY StartTime";
$result = mysql_query($query);
if(mysql_num_rows($result))
{
while($row = mysql_fetch_assoc($result))
{
$eventID = $row['EventID'];
$eventName = $row['EventName'];
$startDate = $row['StartDate'];
$description = $row['Description'];
$assignedTo = $row['AssignedTo'];
$PTLType = $row['PTLType'];
$parentEventID = $row['ParentEventID'];
$textclass = "greentext unselectable";
$text = "Main event";
//$url = SITE_URL ."/agenda-view-event.php?eventID=$eventID&date=$currentDate&day=$i&type=A&date=$currentDate";
$url = SITE_URL ."/agenda-view-event.php";
if($PTLType == 2) // To do's
{
//$divRed[] = $eventID;
$url = SITE_URL ."/agenda-view-timeline.php";
$textclass = "redtextDaily unselectable";
$text = "To do";
$html_todos .= '
<tr id="redtext' . $eventID . '">
<td id="rowbox'.$eventID.'" class="'. $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'parentEventID='.$parentEventID.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">
' . $eventName . ' - (' . $text . ')
</td>
</tr>';
}
elseif($PTLType == 3) //开发者_开发技巧Completed
{
//$divBlue[] = $eventID;
$url = SITE_URL ."/agenda-view-timeline.php";
$textclass = "blueTextDaily unselectable";
$text = "Completed";
$html_completed .= '<tr id="bluetext' . $eventID . '"><td style="display:none;" id="rowbox'.$eventID.'" class="' . $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'parentEventID='.$parentEventID.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">' . $eventName . ' - (' . $text . ')</td></tr>';
} else { //main events
//$divMainEvent[] = $eventID;
$html_main_events .= '<tr id="mainEvent' . $eventID . '"><td id="rowbox'.$eventID.'" class="' . $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'date='.$currentDate.'\', \'day='.$i.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">' . $eventName . ' - (' . $text . ')</td></tr>';
}
}
echo $html_main_events . $html_todos . $html_completed;
} else {
?>
<tr>
<td>
<span class="a_dateformat">You have no agenda items due today!</span>
</td>
</tr>
<?php
}
?>
</table>
</div>
<input type="hidden" id='lastselected' value='' style="" />
</td>
<td class='verticalborder'> </td>
<td width='59%' valign="top" align="center">
<div id="agendaLoader" style="display:none;">
<img src="images/ajax-loader-orange.gif" alt="wait" />
</div>
<div id="agendaViewDiv" style="display:none;"></div>
</td>
</tr>
<tr>
<td colspan="3">
</td>
</tr>
</table>
But see how I commented out the jQuery to make it work?
If that is not commented out, I don't get any output. The problem is that I need that jQuery to properly build the page.
For anybody who stumbles across this "answer," please note that it was not intended to be so broken-up. Each portion of this answer was added at a later date following exchanges with the OP in the comments. The items on top are the latest additions whereas the furthest items down were earlier additions.
Jonathan Sampson
Call to undefined function
Because this page is typically included, and not called directly, there may be some things that won't be available when requested. You indicated in the comments that the function getNumericTime()
doesn't exist, and is causing an error.
You'll want to make it exist, but you don't want to just redeclare it, or else that will cause problems for you when you request this page as an include-file to another page that already has that function. So what you'll want to do is check whether the function exists, and create it if it doesn't.
if (!function_exists("getNumericTime")) {
function getNumericTime($foo) {
// get the function logic and place it here
}
}
Now, when you call the include-file directly, the function will be created if it doesn't exist. When you call the old-fashioned way, with this file being included, the if-statement will simply skip pass the new function declaration, since the function already exists.
If this function exists within a functions file, you can include it, but be sure to use include_once()
instead of include()
. include_once()
will not include the file if it's already be included once before. Given the fact that this page is occasionally in another environment where the functions include has already taken place, we want to be sure not to include it again, so we use the include_once()
method.
Missing connection and selection...
You're attempting to perform queries, yet there's no database connection on this page. There is also no mysql_select_db()
call to select from a specific database. Without these, your queries won't succeed and your data won't be returned.
// Our connection to mysql
$conn = mysql_connect($host, $user, $pass) or die(mysql_error());
// Which database we're using
mysql_select_db($dbname) or die(mysql_error());
Once that connection is made (within index.php, for example) we could do an include:
include("foo.php");
The contents of foo.php now have a connection opened so they can perform queries, call stored-procedures, etc. This is only the case because it's being included into a page that has an open-connection.
If we were to access foo.php directly, which is what you're doing with your ajax-request, we wouldn't get the results we want, because foo.php doesn't provide its own database connection - it depends on index.php (which it is often times included into) to provide that connection.
From PHP to HTML to PHP...
One thing that often times causes problems outputting HTML progressively through a PHP Script. Often times you'll see numerous echo
statements followed by HTML strings that are littered with back-slashes to escape certain output. Not only is this tedious to write, but it's a pain to search when problems arise. HTML rarely needs to be within PHP. When you need to output HTML, get out of your PHP tags for a moment:
<?php
$result = mysql_query($sql) or die(mysql_error());
if (mysql_num_rows($result)) {
while ($row = mysql_fetch_assoc($result) { ?>
<tr>
<td>Data Here</td>
<td><?php print $row["foo"]; ?></td>
</tr>
<?php }
} else { ?>
<tr>
<td>No records found</td>
</tr>
<?php }
?>
Notice how it's easier to tell when my HTML is wrong someplace, and it's easy to jump from writing markup to writing PHP. Ideally, you wouldn't even do it this way, but this is an improvement over what you currently have.
Properly using $_SESSION
After giving a look at your code, I noticed that you're calling values out of $_SESSION
, or trying to at least. You can only do this if you have called session_start()
at the top of the page. Your code lacks this, which may be the reason you're not getting anything back as an integral part of your SQL Queries is missing. Add the following to the very top of your script:
<?php session_start(); ?>
PHP Code Not Executing?
If your PHP isn't executing, there's a problem with the script or the server, but not with jQuery. Check to make sure you have both the opening and closing PHP tags in the script you're requesting:
<?php
/* and */
?>
Simplifying things
You could simplify and clean up your code a bit too. First of all, let's create a new nav-bar:
<ul id="nav">
<li><a href="index.php">Index</a></li>
<li><a href="about.php">About</a></li>
<li><a href="contact.php">Contact</a></li>
</ul>
Note how I'm linking directly to the files, and not using any javascript to cancel out my clicks. This way, when a user stumbles onto my site without javascript enabled, they're not faced with a broken website, they can still get around.
Without interspersing javascript in our HTML, we'll bind up some logic to these nav-links:
$(function(){
// Attach logic to all links
$("#nav a").click(function(e){
// Prevent link from redirecting page
e.preventDefault();
// Load next page into #targetDiv
$("#targetDiv").html("").load($(this).attr("href"));
});
});
And that's it. You're done.
This answer is in response to the follow part of the question:
When I click the nav links, the HTML loads into the div, but the contents of my include files also contain
PHP functions andjQuery that needs to execute when being loaded and they are just ignored.
Note that the JavaScript that gets returned from XMLHttpRequestObject.responseText
will not execute when inserted into the DOM text with innerHTML
as you are doing.
You may want to check the following Stack Overflow post for a couple of solutions around this issue:
- Can scripts be inserted with innerHTML?
However, if you are using jQuery, you can replace all the code in getData()
with the following:
function getData(dataSource, divID)
{
$.ajax({
url: dataSource,
dataType: 'html',
success: function(data) {
$('#' + divID).html(data);
}
});
}
When the jQuery ajax()
method is called with the dataType: 'html'
option, included script tags are automatically evaluated when inserted in the DOM. You may want to check the following Stack Overflow post for further reading on this:
- When loading an html page via ajax, will script tags be loaded?
精彩评论