Session Start is very slow with AJAX - javascript

i have using Ajax to load the content of another page in my div with Twitter Bootstrap tabs.
I realized that Ajax was taking too long to load the request, so I decided to clean up the code and leave just the 'session_start ()'.
And the problem is exactly the 'session_start ()'.
Microtime used to measure the time of the requests.
Below is the result of tests:
PHP WITH session_start() loaded with AJAX - 29.041733980179 ms
PHP with session_start() loaded without AJAX - 0.00010895729064941 ms
PHP WITHOUT session_start() loaded with AJAX - 1.6927719116211 ms
This is my Javascript code:
$(function() {
$("#MainTabs").tab();
$("#MainTabs").bind("show", function(e) {
var contentID = $(e.target).attr("data-target");
var contentURL = $(e.target).attr("href");
if (typeof(contentURL) != 'undefined')
$(contentID).html('<img src="<?php echo IMG_DIR; ?>loading/loading-large.gif" width="64" />').load(contentURL, function(){
$("#MainTabs").tab();
});
else
$(contentID).tab('show');
});
$('#MainTabs a:first').tab("show");
});
This is my PHP Code:
<?php
$start = microtime(TRUE); // Start counting
set_time_limit(0);
// session_start();
$temp = microtime(TRUE) - $start;
echo $temp;
exit;
Does anyone know what is happening?

I had almost the same problem, it is called a session lock. When you do more than one ajax calls, the server prevents session writing for the the latter calls so they have to wait for the previous calls to end. Using session_write_close() when you are done with your session, unlocks the other calls.
Here's more info: session_write_close() on php.net

Related

How to refresh the web page when index changes without lagging the server

I would like to refresh my static web page running on apache when the index changes. I've already tried to use server-side events, where I had a PHP file checking if the index changed and if yes, it sent the event to the webpage. This works exactly how I want, but there is a problem. Because the page is used by a lot of people sometimes (tens or up to a hundred opened tabs), it quickly starts to spam many apache processes. Then, it reaches the limit, and the apache freezes.
The question is how to handle this. If a user closes the tab, the process is killed, however, if not, the apache freezes.
The PHP script looks like this (it is checking two things, first, if the file chenged, or second if the status is something. As I said, this works fine, the problem is its lagging the server):
<?php
session_start();
session_write_close();
ignore_user_abort(false);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$filename = "index.html";
while(True){
if ( connection_aborted() ){
exit();
}else{
try{
$string = file_get_contents("current_status.json");
$json = json_decode($string, true);
$pom1 = $json["state"];
$t1 = shell_exec("date -r index.html");
sleep(3);
$pom2 = $json["state"];
if($t1 != shell_exec("date -r index.html")) {
sleep(2);
echo "data: file changed \n\n";
} else if($pom2=="ready") {
sleep(2);
echo "data: new shot available \n\n";
} else {
echo "heartbeat";
}
ob_flush();
flush();
}
catch (\Error $e){
echo "data: error, json not available \n\n";
}
}
}
ob_end_flush()
?>
Then, there is a classical javascript function in the index file with event source on the PHP file.
My question is, how can I do this to not make apache crashing? Can I somehow set up SSE to handle it? I know I can allow more processes on apache, but my resources are limited.
Is there any other way how to do this? For example, live.js works as well, but the problem is the sam, a lot of processes when opened multiple times.
Yes, I can see how this would put far more strain on your server than necessary.
What you should do is poll for changes from javascript. You send an asynchronous request for the last time the index file changed from your javascript. You do it once when the page loads and store the time. Then you check again on an interval and compare the result with the first one. If it changed you refresh the page.
The PHP script should get the last change date, output it and exit - no continuously running PHP scripts.
Here is what the PHP file should look like:
<?php
header('Content-type: text/plain');
echo filemtime('index.html');
?>
Keep this minimal. The built in filemtime function is more efficient than running shell_exec commands.
Here is an example javascript:
chk_index_change_time(false);
function chk_index_change_time(last){
fetch('http://yourdomain.com/yourpath/get_index_change_time.php')
.then(res => res.text())
.then((index_change_time) => {
if ((false !== last) && (last != index_change_time)){
location.reload();
} else {
setTimeout(chk_index_change_time, 3000, index_change_time);
}
});
}
Feel free to error handling or whatever, but this will work. I used a timeout here instead of interval so that if the server is slow the server response time doesn't come out of the 3 second delay.

How can i open, read, close, update, reopen and read a file without refreshing in php

I am trying to make a chat application using html and php.
I am writing a .txt file with the whole chat in it and want to read it every five seconds without refreshing my page. I tried to use a loop in javascript, but it dont refreshes the file after open it again.
function readChat(){
clearArea();
<?php
if ($file = fopen("chat.txt", "r")) {
while(!feof($file)) {
$line = trim(fgets($file));
if($line !== " "){
$arr = explode(":", $line, 2);
$name = $arr[0];
$string = $arr[1];
$string = str_replace(array("\r", "\n"), '', $string);
if($name === $_COOKIE["username"] && $string !== "" && $string !== " " && $string !== "\n"){
echo "selfMessage(\"".$string."\");";
}else if($line !== "" && $line !== " " && $line !== "\n" && $string !== "" && $string !== " " && $string !== "\n"){
echo "otherMessage(\"".$string."\", \"".$name."\");";
}
}
}
fclose($file);
}
?>
}
window.setInterval(function() {
readChat();
}, 5000);
This is what i tried so far.
The problem you are having is due to mixing PHP and Javascript code.
First you should know that the PHP code executes on the server which generates the page content that will be sent to the client (web browser). Then that web browser executes the Javascript code contained in the page content it receives.
Can you see already why the chat isn't updating?
Your PHP function executes just once, when the page is requested, and inserts the chat messages into the body of the readChat() function. When the browser receives the web page data that contains readChat() it just sees the chat messages as if they were hard-coded into the function!
For Example, the following PHP script:
function someJSFunc() {
<?php
$now = date('m/d/Y H:i:s', time());
echo "var now = '$now';";
?>
console.log(now);
}
Results in the following function being sent to the client:
function someJSFunc() {
var now = '6/4/2019 16:39:18';
console.log(now);
}
No matter how many times the client calls someJSFunc() it will always output the same date and time because that was the time that the PHP function executed.
Sometimes mixing PHP and Javascript this way can be very useful, but to accomplish what you are looking for you are going to need to use AJAX requests.
An AJAX request can be accomplished easily using JQuery. All you need to do is add another <script> tag to your page header to include the JQuery script. Further instructions on setting up JQuery can be found on their website.
Next you have to fix your readChat() function. Instead of using PHP in that function, just use javascript and use JQuery to perform a GET request.
function readChat() {
clearArea();
$.get("getchat.php", function(data) {
// inside this function data will contain whatever your PHP script echos
$('#chat').html(data); // for example, replacing a div with id="chat" with the data received from getchat.php
});
window.setInterval(function() { readChat(); }, 5000); // I would personally move this outside of readChat() so that it is only called once...
}
This function will load getchat.php every time the browser calls readChat(), and set up an interval to call readChat() every 5 seconds. The function inside $.get() is where you can use the data received from getchat.php. It is usually just a string that you can insert into your chat area or div, but it depends on how you make the getchat.php script work.
Lastly you just make a new PHP script called getchat.php that will read the chat file and echo it in the format that you would like to see added to the page.

Javascript on webpage not changing text

I have the following script at the bottom of my php page, it runs on pageload, but I need it running every 10 seconds. It only runs on page load.
PHP is running.
I've tested this with a countdown from ten, and the script is actually looping, but for some reason not when i integrate this PHP.
Please help.
<script>
var CurrentBranch = "<?php echo file_get_contents('gitstatus.txt'); ?>";
var x = setInterval(function () {
CurrentBranch = "<?php echo file_get_contents('gitstatus.txt'); ?>";
document.getElementById("CurrentTestBranch").innerHTML = CurrentBranch;
CurrentBranch = "";
}, 10000);
</script>
Edit:
The code does display the file contents the first time around. But does not refresh when I make a change and save it.
Your PHP code is run only when the page loads. It generates string literals when it runs. These do not get updated when the interval function gets called repeatedly (because the PHP does not run again).
If you want to get new data from PHP you need to make new HTTP requests.
You could either reload the entire page, or use XMLHttpRequest (or fetch) to call a web service that gives you the data you want (Ajax is a useful search term).
PHP happens before HTML hits the server.
Look up setTimeout() javascript command. What you need to do is get javascript to call another php script, which checks and echoes your value.
Something like this (could be pseudocode, from memory):
setTimeout(function(){
var CurrentBranch = $.get('/url/that/sends/value');
// do something with your value, call a function, whatever
}, 10000);

How can i access javascript variable in kirby cms for “limit” functionality

Just like in demo of kirby
<?php foreach(page('projects')->children()->visible()->limit(3) as $project): ?>
I want to make dynamic limit of records.
How can i do that?
I have tried JavaScript but it not worked.
Here is JavaScript code that no worked
<script>
var p1 = 3;
function load()
{
p1=p1+3;
}
</script>
<?php
$number="<script>document.write(p1)</script>";
// echo $number;
<?php foreach(page('projects')->children()->visible()->limit($number) as $project): ?>
//Code Here
<?php endforeach ?>
<div class="text-center">LOAD MORE</div>
suggest me if anyone has done it.
You can't, at least not in this way.
Think of when and where your code is getting executed. PHP is executed by the server, before the browser even receives the page. JavaScript is executed by the browser, after the page is done loading.
You can either have a separate script that generates what you need from your number, and pass that as a GET or POST value to the script via an AJAX request, or generate the number you need in PHP.
So in case of an AJAX request you'd have your PHP script doing something like:
<?php
$number = $_GET['number'];
foreach (page('projects')->children()->visible()->limit($number) as $project) {
echo .....
}
?>
and your JavaScript would call that script via an AJAX request and put the resulting HTML into your page, with something like:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
document.getElementById("container").innerHTML = xht.responseText;
}
xhr.open("GET", "script.php?number=" + p1, true);
xhr.send();

URL Redirect in a Loop

I am using a java script in php to redirect a URL. This works for me because each time the loop is run, the link opens in a new window and the desired action takes place. However I want to stop the script from opening new windows and run / load within the same page. If I open the link the same page, it redirects to the new page in the first run and the loop does not run further.
I have no control over the next pages as they are part of an API. I do not actually want to navigate to the new page(s) but I just want to run the http:// API, which may even run in the background or something.
Please advise on what would be the best method to handle this ?
This is my current script:
<?php
$x1=$_POST["textfield1"];
$msg = "New Message Alert From $x1. blah blah";
$query = "SELECT * FROM phone_list";
$result = mysql_query($query);
$num=mysql_numrows($result);
$i=0;
while ($i < $num)
{
$f1=mysql_result($result,$i,"phone");
echo'<script> window.open("http://linktonextpage&msg='.$msg.'&num='.$f1'"); </script>';
$i++;
}
?>
Thanks in Advance !
As you're discovering, once you move from one page to another at that point the previous page is gone from the browser. JavaScript won't continue to run from pages that are no longer loaded.
I do not actually want to navigate to the new page(s) but I just want to run the http:// API, which may even run in the background or something.
Then don't navigate to the page. Instead, make an AJAX request to the desired URL. Something as simple as this:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
// This function is called when the AJAX request completes.
// Here you would check for errors or respond in some way, if needed.
};
xhttp.open('GET', 'http://someurl', true);
xhttp.send();
As long as you're not making too many concurrent requests, you can run that in a loop. Just enclose it in a function:
function sendRequest(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
// This function is called when the AJAX request completes.
// Here you would check for errors or respond in some way, if needed.
};
xhttp.open('GET', url, true);
xhttp.send();
}
And call that function in a loop over your urls:
for (var i = 0; i < myUrls.length; i++) {
sendRequest(url);
}
You can get a lot fancier with this pretty easily, passing the callback function into the sendRequest() function or having sendRequest() return the AJAX promise or lots of other things. It's up to you what further features you want to add. The main point here, in response to your statement above, is simply to make AJAX requests in the background rather than navigate the browser to the URLs.
Note: Currently your loop is server-side, which is emitting a lot of repeated code to the browser. You can probably just emit the JSON-encoded values and perform the loop client-side as demonstrated above. Or, if you really want to loop server-side, then just define a function like the one above and emit calls to that function in a loop. It's still a lot of repeated client-side code, but it'll get the job done.
Another solution - less correct than solution with AJAX,
but very simple:
You can add iframes instead of opening popups.
while(...){
echo '<iframe src="http://linktonextpage&msg='.$msg.'&num='.$f1'." width="100%" height="120"></iframe>';
}
In your code it seems like you want to send messages to all the numbers fetched from database so if you want to use JavaScript you can do as previous answer.
Another way of doing the same is without using JavaScript.
You can also make Curl request to the Api Urls. Within your PHP code without loading the page.
While (condition) { $service_url = 'http://linktonextpage&msg='.$msg.'&num='.$f1'';
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$curl_response = curl_exec($curl);
curl_close($curl);}

Categories