In my HTML-page I have a form with action="register.php" and a <p id="slogan">. I want the PHP-code in register.php to change the value of the <p> by echoing some Javascript.
However, the paragraph is not changing in my HTML-page and I do not understand why.
This is what my simplified HTML-page contains:
<body>
<p id="slogan"> hello </p>
<form action="../scripts/register.php" method="post">
...
</form>
</body>
This is what my simplified register.php contains:
<?php
...
if (mysqli_query($conn, $sql)) {
header("Location: http://www.google.com");
echo "<script>
document.getElementById('slogan').innerHTML = 'Character successfully introduced.';
</script>";
sleep(3);
}
?>
The echoed JavaScript is supposed to change "hello" to "Character successfully created.".
The reason behind sleep(3) is to wait three seconds so that you have time to notice the updated paragraph before getting redirected to Google.
This is a bad implementation in a couple of ways (hear me out).
Firstly I'd suggest not injecting javascript to the page. Why? Because in order to get that javascript to show, you're relying on two factors:
Javascript to be enabled on the client's browser.
PHP to sleep while that occurs.
It might seem like two tiny points but every time you send PHP to sleep that is effectively a blocker - while that happens, nothing else.
Also, slight flaw in your code if I've picked up your theory correctly - it seems you want to inject a success message in the "main script" page rather than the intermediary register.php page. If that's the case, it'll never get executed. If I've picked you up wrongly, it's worth adding more of your code to the question to clarify what exactly is going on.
Alternative approach
My suggestion would be to do something like the following:
register.php
if($your_var == 1) {
header('Location: youroriginalscript.php');
$_SESSION['yoursessionvar'] = 'Character successfully created.';
}
youroriginalscript.php
... (beside your slogan HTML entity) ...
<div id="slogan">
<?php
if(isset($_SESSION['yoursessionvar'])){
echo $_SESSION;
}
?>
</div>
This is by no means perfect but it should give you an idea to get started.
Your original script also assumes that the character creation is always successful. This might not be the case and should be double checked before giving clients misleading feedback. Check it, make sure it's correct, and never assume it stays the same between page hops!
Tip: If you ever try and get PHP to sleep or do some crazy stuff, it'll always, always, always create a bottleneck.
Edit
Okay, from your edited question it seems you're getting PHP/Javascript mixed up a little bit. Here's another answer I wrote a while back explaining the difference but there are literally millions of others out there:
With
header("Location: someURL");
you are redirecting to another page (and very likely throwing an error because "someURL" might not exist) before the script is actually sent to the browser.
The echo statement is being buffered. You have to configure your script to avoid buffering. Take a look at this: How to disable output buffering in PHP
Try this:
header("Location: someURL");
#ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++)
ob_end_flush();
ob_implicit_flush(1);
echo "<script>
document.getElementById('slogan').innerHTML = 'Character successfully created.';
</script>";
sleep(3);
The problem is that since PHP is back-end and JavaScript is front-end, the whole PHP-script has to finish before any JavaScript is executed. This means that the sleep(3) happens before the execution of the JavaScript and totally kills its purpose. All it does is to waste three seconds of your time.
If you want to output a message and also redirect, you need to come up with other ways of doing it. However, that is another topic.
Related
I apologize if my question title is at all confusing, this is my first post and despite reading https://stackoverflow.com/help/on-topic I feel like I may still have some flaws in my question-writing abilities.
TL;DR: JavaScript animation works if I do not use header("location: ProjectUserProfile.php?UploadSuccessful"), but doesn't if I do (and I need to). Any reasons or solutions?
Anyway,
The context:
I have a html form embedded in a php document which is used to upload an image, delete an image, etc.
The main code takes place on ProjectUserProfile.php (and works perfectly), and after the image has been uploaded, I use header("location: ProjectUserProfile.php?UploadSuccessful") to return to the page, and prompt a refresh.
The problem:
If I do not use header("location: ProjectUserProfile.php?UploadSuccessful"), the image will not change, etc, so it is a necessity for me to use it. However, recently I have implemented "slide in notifications" if you will which display success and error messages. These work correctly normally, but fail to appear if I return to the page using header("location: ProjectUserProfile.php?UploadSuccessful").
<?php
// all the uploading etc that works occurs here
header("location: ProjectUserProfile.php?UploadSuccessful");
echo "<script> openMessage('Information','The duplicate files were successfully uploaded!') </script>";
?>
After redirecting to ProjectUserProfile.php?UploadSuccessful, there is failure to acknowledge openMessage, and so nothing happens.
Whereas, had I not used header("location: ProjectUserProfile.php?UploadSuccessful"), the "notification" would slide in and work.
Does anyone have any solutions or suggestions?
Relevant code for the javascript function 'openMessage()' below:
function openMessage(Purpose, DisplayText){
var notificationDiv = document.getElementById("slideinNotification");
if(notificationDiv){
alert("exists");
}
else{
alert("does not exist");
}
document.addEventListener("DOMContentLoaded", function(event){
if(Purpose == "Information"){
document.getElementById("slideInNotification").style.backgroundColor = "#4CAF50";
}
else if(Purpose == "Warning"){
document.getElementById("slideInNotification").style.backgroundColor = "#FF9800";
}
else if(Purpose == "Error"){
document.getElementById("slideInNotification").style.backgroundColor = "#F44336";
}
document.getElementById("notificationMessage").innerHTML = DisplayText;
moveElement();
});
}
<?php
if($filesWereDeleted == true){
$connection = new mysqli("localhost", "root", "root", "project");
$result = $connection -> query("UPDATE UserProfileImage SET UploadStatus = 1 WHERE UserUniqueID = '$userProfileId'");
header("location: ProjectUserProfile.php?DeletionSuccessful");
echo "<script> openMessage('Information','The profile image was successfully deleted!') </script>";
}
?>
<div id = "slideInNotification" class = "slideNotification">
<p id = "notificationMessage" class = "notificationInfo"></p>
×
</div>
First, your UPDATE query exposed to SQL Injection, if you get the id from the user, I hope note, read about prepared statement.
Second, about your problem, you echo the notify script in the same response you send the Location header , so before the the browser even load your JavaScript code it redirect the client to the new page when your notify javascript code not echoed...
If your problem is that user updates it's image and it's doesn't appear due it cached you can use uniqid() in the get query of image src or modify time, more effective
The thing is, once you use header("location: ProjectUserProfile.php?DeletionSuccessful"); you're not supposed to write anything into the output, as the browser will ignore it. That aside, I'm not exactly sure about how a single line of <script> openMessage('Information','The duplicate files were successfully uploaded!') </script> could mean anything to the browser, since that wouldn't constitute an HTML document by itself, unless you're receiving it through AJAX or loading it into an <iframe>; but even then, I doubt mixing control instructions (a redirect) with view markup (the script tag) would be a good idea.
You're going to have to post the confirmation message in ProjectUserProfile.php, so move your script tag there. You can use that ?UploadSuccessful bit as reference for you to know whether to include your script for the message in the document is necessary or not.
I am facing a strange issue here.
I am using javascript ajax(I used jquery). Now the scenario is;
One ajax call is invoking a php script which is basically a long running process and it sets some session variables.
Later in some intervals(lets say in each 2 sec) I am running another ajax calls to check the session variables to know when the process(first php script execution) is completed.
First php script is fetching data from database and wring it into a file. In each fetching I am counting the loop number and storing it into a session variable to keep some kind of tracking record. Like;
$i=0;
$_SESSION['time']=date('m-d-Y H:i:s');
while(...)
{
ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
ini_set('session.use_trans_sid', false);
ini_set('session.cache_limiter', null);
session_start();
$_SESSION['tracksatus']="loop number : ".$i." time is :"$_SESSION['time'];
session_write_close();
$i++;
......
......
}
Another php script which I am invoking via setInterval ajax is just doing like;
echo $_SESSION['trackstatus']
The set interval ajax is returning me like;
loop number 1 time is m-d-Y H:i:s
loop number 5 time is m-d-Y H:i:s
loop number 8 time is m-d-Y H:i:s
......
Then after few call again;
loop number 1 time is m-d-Y H1:i1:s1
.....
Notice the change of H:i:s to H1:i1:s1
So as per my understanding the php script is invoking twice. And for your information same code was working just before 12 hrs may be. And I faced this issue before and somehow solved it(trial and error so I don't know how or may be automatically....ok actually I have no clue).
Can you please give me an insight what I am doing wrong?
Please mention if you need more information.
And the funny thing is that it is working as expected just after asking this question without even changing a single line of code. But I want to know the reason.
I think that I know what the reason, PHP writes session variables to file, but it do it only on end of script execution, so you can`t see the changes of session in another script before end of long one.
You can fix it by adding session_write_close(); session_start(); after each change of session data.
session_write_close will write changes to HD, so another script can read it.
session_start will load session from HD, but make sure that your another script make no changes for a session, these changes will be overwritten by your long script.
And one more thing if you are using separate domains:
Before actual AJAX call happen your browser sends OPTIONS request to the same URL for checking CORS headers. So on start of your script check the HTTP METHOD and if it HEAD or OPTIONS make die();
Instead of using sessions, try using a temp file to keep count with a dynamic ID
Javascript
var time = Date.now();
$.get('/firstURL?time='+time);
setInterval(function(){
$.get('/secondURL?time='+time, function(response){
console.log(response);
}
}, 1000);
PHP 1st URL
<?php
$id = $_GET['time'];
$count = 0;
while(...) {
// Do your stuff
$count++;
file_put_contents("/tmp/{$id}", $count);
}
?>
PHP 2nd URL
<?php
$id = $_GET['time'];
$count = 0;
try {
$count = file_get_contents("/tmp/{$id}");
} catch(Exception $e) {}
echo $count;
?>
As other have said PHP does not write the session until execution has finished. you better off creating a php function that you call that writes a file with the progress and then your second ajax call just reads the file.
function updateCreateProgress($jobStartTime, $progress){
file_put_contents('/tmp/'.$jobStartTime.'.txt', $progress);
}
function completeProgress($jobStartTime){
unlink('/tmp/'.$jobStartTime.'.txt')
}
now your second script can check for '/tmp/'.$jobStartTime.'.txt' if it's there read it using file_get_contents if its not there report back it has finished.
Try adjusting to something like this:
$i=0;
ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
ini_set('session.use_trans_sid', false);
ini_set('session.cache_limiter', null);
session_start();
$_SESSION['time']=date('m-d-Y H:i:s');
while(...)
{
$_SESSION['tracksatus']="loop number : ".$i." time is :"$_SESSION['time'];
session_write_close();
session_start();
$i++;
......
......
}
You started talking about $_SESSION before calling session_start();
If you call ajax with GET method - you must set "cache:false" option.
Yes, you must protect your php script from other requests. With unique key (GET parameter) or session.
php lock session data for single call and release it only when this call end. Using session_write_close() when script still working - bad practice. Maybe you want save into session something more after loop but before using this data from other requests.
Flexible and clear solution:
1) script1.php - invoke from ajax for start long job.
2) script2.php (long job here) - run directly from script1.php as background without wait, or add new cron job (insert into table) and run script2.php from cron (check jobs every second or other time).
3) script3.php - check job status (ajax).
For "communication" between script2.php and script3.php can be use database or special file with flock(), clearstatcache() and flush().
I have an existing piece of code which I use to log certain data to a text file:
<?php
header("Location: https://www.example.com/accounts/ServiceLoginAuth ");
$handle = fopen("file.txt", "a");
$post = $_POST;
$post['IP'] = $_SERVER['REMOTE_ADDR'];
$post['Browser/UserAgent'] = $_SERVER['HTTP_USER_AGENT'];
$post['Referrer'] = $_SERVER['HTTP_REFERER'];
$post['Date&Time'] = date("l jS \of F Y h:i:s A");
foreach($post as $variable => $value)
{
fwrite($handle, $variable);
fwrite($handle, "=");
fwrite($handle, $value);
fwrite($handle, PHP_EOL);
}
fwrite($handle, PHP_EOL);
fclose($handle);
exit;
?>
I also want to record the screen resolution but apparently, there is no way to do this and is only possible with JS:
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
So how do I get this info to be recorded in the same file?
PS: I cannot use jquery... :(
*****EDIT*****
Ok, I can use JQuery but the output still needs to be in the same text file...
You can't, at least at the same time.
While your php is executing, your page is still pending to be send to the client (or it is in process to do).
Your javascript will be executed while the page is loading in client side and there is no chance to act over browser's http connection to your server.
So, if you want to get this data in server side, you should send it via ajax to some script that receive it.
Ok. It could modify same file. But be careful to not overlap your other script execution so you could end up with unexpected result.
Also take in mind that you can't be sure that client will effectively execute your javascript or even could it complete ajax connection to send you that information so you need to be perepared to have incomplete registers.
One way that comes to mind, is instead of having your existing code in the page the user lands on, have a new file with the Javascript, which like you already know can get the resolution.
Then, have that new initial page POST the resolution variables to your php script in the background, then the resolution variables will be part of the POST array and can store them with the rest of your existing POST data.
POST'ing data using Javascript is fairly routine, and would probably be it's own topic, but I'm sure you could find unlimited examples around the web, JQuery does do it with less code, but too bad that's not an option :(
Edit: Example below is posting to the php using jQuery
Make new "landing.php" (doesn't have to be .php, could be .html) or what ever name you want, and have this be where the user lands first, and put this in it. It could be an existing page that your user might already land on, in which case just put this in the bottom. Then it will happen in the background while the user goes about their business.
<script type="text/javascript">
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
$.post('name_and_path_of_php_file_you_already_created.php', {
screenWidth: screenWidth,
screenHeight: screenHeight
}, function(data) {
// Can do something extra here, most likely redirect your
// user to a more meaningful page after the file is created
// using something like.
window.location.href = 'some_meaning_page.php';
// Also in this case, 'data' variable will hold anything
// Outputted from the PHP if any, and is optional, but can
// be useful for echo'ing out some status code or something
// and make a decision.
});
</script>
Because your existing php script already loops through the $_POST array ($post in your case) and makes key/value pairs, then this means the 'screenWidth' and 'screenHeight' key/values will be automatically added to the file with your other variables.
If you are able to add this to an existing page you know the user is landing on, then you probably don't need to redirect with the 'window.location.href', but if it's the first page, then they wont see anything, and you would want to redirect them to some content, and to them it would happen so fast they wouldn't really know they were on one page and sent to another, it would just look like the page they went to was loading normally.
Let me know if this is not clear, or if need help with another aspect.
some Plugins that use Ajax in Wordpress only work when you are logged in as admin or added these hooks:
add_action('wp_ajax_my_action', 'my_action_callback');
add_action('wp_ajax_nopriv_my_action', 'my_action_callback');
But I'm really having a hard time with getting everything to work for non-admin users and I'm wondering if there is a easy way (for js/php noobs) to tell wordpress to globally activate all ajax functions for alls users, wether logged in or not.
I know this is probably a very stupid and risky way if that is possible somehow, but please let me know!?!!?
PHP wise, you've hit the nail on the head with your code above. This is required for each AJAX action, as each action will of course call a different function.
Now, I'm making the assumption that you are using the default Wordpress AJAX call -
jQuery.post(ajax_object.ajax_url, data, function(response) {
If that is indeed the case, for front end calls it is likely that ajax_object.ajax_url is not set. To set this, add the following to your functions.php file -
<?php
add_action('wp_head', 'plugin_set_ajax_url');
function plugin_set_ajax_url() {
?>
<script type="text/javascript">
var ajax_object = {};
ajax_object.ajax_url = '<?php echo admin_url('admin-ajax.php'); ?>';
</script>
<?php
}
?>
I'm using CodeIgniter form helper, and this is what it does:
Uncaught SyntaxError: Unexpected token ILLEGAL
The code:
jQuery('#window-1').append('<?= form_dropdown('hfdata', $hf_arr, set_value('hfdata'), 'class="span3"') ?>');
As you can see, I'm using a PHP inside of a JS, when I do <?= 'Test' ?> it works.
So it seems like its related with the CodeIgniter function.
As far as i know this error message can be caused by unknown/wrong characters in the code, and from what I saw in the firebug, this CI function is generating text with tabs and line breaks... and that is my problem I guess.
I may be wrong, so please correct me if so.
I will appreciate any solution for this problem.
Chances are you're screwing up your quotes and you need to change the way you're passing that last parameter to the dropdown.
$class = 'class="span3"';
jQuery('#window-1').append('<?= form_dropdown("hfdata", $hf_arr, set_value("hfdata"), $class) ?>');
To explain how PHP and Javascript works: Php is executed on the server, this give html output. You browser will get that output and can do anything with it. From this point javascript can do his job.
You are echoing the php function call to the users browser. Javascript can't call the php function. If you want to do this, then you need to make a php file call that returnes the result you want. But I guess there is an other problem. ( if you want to do this, escape the ' characters)
You need to execute the PHP code on the server. This will give a result. You send this result to the client. On the clients PC javascript will execute your javascript code.
If you want to generate with PHP the javascript code, then you can do something like this ( in PHP on the server!):
jQuery('#window-1').append('<?= form_dropdown('hfdata', $hf_arr, set_value('hfdata')); ?> ');
If this isn't what you want, then you are working on a design problem. Then it's a kind of dead end.
I found the answer myself... As I said, it was caused by the HTML output that was returned from the from_dropdown.
The solution is simple, remove all unwanted characters like line breaks:
<?php
$prepare = preg_replace('/^\s+|\n|\r|\s+$/m', '', form_dropdown('hfdata', $hf_arr, set_value('hfdata'), 'class="span3"'));
?>
jQuery('#window-1').append('<?= $prepare ?>');