I have a MVC 3 project that publish in a server.
Scenario
For example I have a function for saving a data from (PC1) to (PC2).
It is possible that the viewing of data(data in jqgrid) in (PC2) is open(open in page) by a user and it will auto refresh or update the page or the jqgrid after the (PC1) save a data?
My jqgrid version is 4.3.3.
Hope you guys understand what I mean in my post. Post feedback if down votes. Thanks.
Any help will be accepted.
You might wonna use ajax to accomplish such a job, please read below
if I understand what you mean, is that you wonna poll a server to realtime updates on either intervals or something else...
option 1
Issue a normal stateless ajax call to the server, then force the server to hold the request for a limited time [to overcome server overhead]
This can also be reffered to as reverse ajax or comet.
Unless you are planning to use websocket technology, I hardly stress that you try this.
if(isset($_GET['finite'])){
#declare time for a session
$_SESSION['typing']=$reduce_browser_overhead=time();
#remember to close the session before entering the loop;
#if u dont close, then the browser will not reload the same website untill the connection is close or satisfied
session_write_close();
function loop(){
#do this to access external variables ===> $reduce_browser_overhead;
global $con,$reduce_browser_overhead;
#explicitly check 2exit
#please do this to release mysql connection since they are in a loop
if($reduce_browser_overhead+4<time()){
echo ' ';ob_flush();flush();
if(connection_aborted()){
#do some work here before you finally exit the connection
exit;
}$reduce_browser_overhead=time();
}
#php prepare statement...
$looper=$con->prepare("SELECT ROW FROM TABLE WHERE ID=SOMETHING AND $_SESSION[typing]=SOME_ROW");
#The statement above willcause the loop to work
#If a table had been update and table has not yet updated, this sql will detemin by the current time
#meaning that if the time[integer] of SOME_ROW is not equal to the time in the session variable,
#then it will let go to the client and then again it will continue looping untill the time in the
#SOME TABLE ROW changes....
$looper->execute();
$looper->store_result();
if($looper->num_rows>0){
sleep(2);
#do some work before looping again
loop();
#you have to explicitly return to this loop to work as expected.
return;
}else{
#send back data to the user or the client listening on the connection
session_start();$_SESSION['typing']=time();session_write_close();
#update the session before finishing the request so that the next time the request comes, the time will be equal to the DBserver time in the row and hence causing the loop again and again => more like a cycle
echo 'After some time the server has received new data which is =>> '.$newdata;
}
}loop();
exit;
//In another file on in the same document as the php / your server file ==> do javascript below
//first issue a normal / stateless ajax request to the target server
$.ajax({
//All optional but url required!
url:'abc.php?var_one=blabla',
cache:true,//whether to cache the requests
timeout:(1000*60)*20,//timeoutthe request
success:function(data){
//if the server successfully completed the request
//do some work here with data returned
},
error:function(){
//if the server return an error
//do more work around
//or call the function again
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
Is it possible to set PHP session variables using Javascript?
In JavaScript:
jQuery('#div_session_write').load('session_write.php?session_name=new_value');
In session_write.php file:
<?
session_start();
if (isset($_GET['session_name'])) {$_SESSION['session_name'] = $_GET['session_name'];}
?>
In HTML:
<div id='div_session_write'> </div>
The session is stored server-side so you cannot add values to it from JavaScript. All that you get client-side is the session cookie which contains an id. One possibility would be to send an AJAX request to a server-side script which would set the session variable. Example with jQuery's .post() method:
$.post('/setsessionvariable.php', { name: 'value' });
You should, of course, be cautious about exposing such script.
If you want to allow client-side manipulation of persistent data, then it's best to just use cookies. That's what cookies were designed for.
or by pure js, see also on StackOverflow :
JavaScript post request like a form submit
BUT WHY try to set $_session with js? any JS variable can be modified by a player with
some 3rd party tools (firebug), thus any player can mod the $_session[]! And PHP cant give js any secret codes (or even [rolling] encrypted) to return, it is all visible. Jquery or AJAX can't help, it's all js in the end.
This happens in online game design a lot. (Maybe a bit of Game Theory? forgive me, I have a masters and love to put theory to use :) ) Like in crimegameonline.com, I
initialize a minigame puzzle with PHP, saving the initial board in $_SESSION['foo'].
Then, I use php to [make html that] shows the initial puzzle start. Then, js takes over, watching buttons and modding element xy's as players make moves. I DONT want to play client-server (like WOW) and ask the server 'hey, my player want's to move to xy, what should I do?'. It's a lot of bandwidth, I don't want the server that involved.
And I can just send POSTs each time the player makes an error (or dies). The player can block outgoing POSTs (and alter local JS vars to make it forget the out count) or simply modify outgoing POST data. YES, people will do this, especially if real money is involved.
If the game is small, you could send post updates EACH move (button click), 1-way, with post vars of the last TWO moves. Then, the server sanity checks last and cats new in a $_SESSION['allMoves']. If the game is massive, you could just send a 'halfway' update of all preceeding moves, and see if it matches in the final update's list.
Then, after a js thinks we have a win, add or mod a button to change pages:
document.getElementById('but1').onclick=Function("leave()");
...
function leave() {
var line='crimegameonline-p9b.php';
top.location.href=line;
}
Then the new page's PHP looks at $_SESSION['init'] and plays thru each of the
$_SESSION['allMoves'] to see if it is really a winner. The server (PHP) must decide if it is really a winner, not the client (js).
You can't directly manipulate a session value from Javascript - they only exist on the server.
You could let your Javascript get and set values in the session by using AJAX calls though.
See also
Javascript and session variables
jQuery click event to change php session variable
One simple way to set session variable is by sending request to another PHP file. Here no need to use Jquery or any other library.
Consider I have index.php file where I am creating SESSION variable (say $_SESSION['v']=0) if SESSION is not created otherwise I will load other file.
Code is like this:
session_start();
if(!isset($_SESSION['v']))
{
$_SESSION['v']=0;
}
else
{
header("Location:connect.php");
}
Now in count.html I want to set this session variable to 1.
Content in count.html
function doneHandler(result) {
window.location="setSession.php";
}
In count.html javascript part, send a request to another PHP file (say setSession.php) where i can have access to session variable.
So in setSession.php will write
session_start();
$_SESSION['v']=1;
header('Location:index.php');
Not possible. Because JavaScript is client-side and session is server-side. To do anything related to a PHP session, you have to go to the server.
be careful when doing this, as it is a security risk. attackers could just repeatedly inject data into session variables, which is data stored on the server. this opens you to someone overloading your server with junk session data.
here's an example of code that you wouldn't want to do..
<input type="hidden" value="..." name="putIntoSession">
..
<?php
$_SESSION["somekey"] = $_POST["putIntoSession"]
?>
Now an attacker can just change the value of putIntoSession and submit the form a billion times. Boom!
If you take the approach of creating an AJAX service to do this, you'll want to make sure you enforce security to make sure repeated requests can't be made, that you're truncating the received value, and doing some basic data validation.
I solved this question using Ajax. What I do is make an ajax call to a PHP page where the value that passes will be saved in session.
The example that I am going to show you, what I do is that when you change the value of the number of items to show in a datatable, that value is saved in session.
$('#table-campus').on( 'length.dt', function ( e, settings, len ) {
$.ajax ({
data: {"numElems": len},
url: '../../Utiles/GuardarNumElems.php',
type: 'post'
});
});
And the GuardarNumElems.php is as following:
<?php
session_start();
if(isset ($_POST['numElems'] )){
$numElems = $_POST['numElems'];
$_SESSION['elems_table'] = $numElems;
}else{
$_SESSION['elems_table'] = 25;
}
?>
I was wondering if it was possible to send HTTP response immediately and continue the script.
Background: Among all the petition I make to the server there's one that creates an Excel file (using PHPSpreadSheet), since creating this files can take a little longer I was thinking of responding a HTTP 202 status code to the Client, something like:
header("HTTP/1.1 202 Excel file in process");
and program in JavaScript a listener on the main js file for every time that status code arrives to activate an interval (setInterval()) and ask every certain amount of seconds whether the Excel file is ready or not
$(document).ajaxSuccess(function ( event, xhr, settings) {
if(xhr.status === 202) {
//Activate the setInterval function to ask the server every 10 seconds whether the file is ready or not
}
});
(I know I have to be activating/deactivating the interval)
So whenever I receive a petition on my createExcel.php file I would like to respond the user immediately that the petition has being received and start the making of such Excel file(s)
Something like:
<?php
//Tell user that the petition has being received
header("HTTP/1.1 202 Excel file in process");
//Kill this process or close this connection but continue executing
//Call createExcel.php
the createExcel.php file would update some table in the database the confirm the file has been created, same table that the interval petition will be consulting every 10 seconds
That's what I'm attempting to do, I would just like you guys to tell me how to call another another file without waiting for such called file to finish to respond the user.
I was thinking of using exec() but I have never used it (I'm testing it right after I post this), and most importantly any experience or tips would be greatly appreciated (like optimization tips and the like)
I saw this question here on Stack Overflow, but the answer suggests to create a cron service which is not a solution for me.
Thank you!
Edit---
Hey in case someone sees this I found two solutions to my question:
The first one I tried but gave a lot of trouble with permissions is this: https://code-boxx.com/php-background-process/
But this one would work beautifully if you run it from cmd, but when you run it thought the browser, Apache forbids you from using executing commands; so exec(), popen(), and similar commandss won't work unless you change your permissions in your folders, which I consider a security issue, so I found out this very beautiful function fastcgi_finish_request()
Edit 2 - solution
https://qastack.mx/programming/15273570/continue-processing-php-after-sending-http-response
this works we flush all content in buffer and close the connection and then we just continue the execution of the script.
In JS:
$(document).ajaxSuccess(function ( event, xhr, settings) {
if(xhr.status === 202) {
//console.log("Your file is in process");
//console.log(xhr.responseJSON);
//Activate interval to check if file is ready
}
});
//Make petition
$.post("petitionsHandler.php", {"texto":"Hello world, greeting from México!"}, function (resp){
//Handle responses
}, "json").fail(function () {
//Handle errors
});
In PHP
<?php
$text = $_POST["text"];
//If you are using sessions don't forget to close the session file
//Or such will be blocked until long script finishes
session_write_close();
header("HTTP/1.1 202 Solicitud recibida"); #This is the code I wanted to send
header("Content-Type: application/json"); #Depends the kind of data you're sending to the client
// Buffer all upcoming output...
ob_start();
// Send your response.
echo '{"success":true, "message":"Your request has been received."}';
// Get the size of the output.
$size = ob_get_length();
// Disable compression (in case content length is compressed).
//header("Content-Encoding: none"); #I didn't need this but check your situation
// Set the content length of the response.
header("Content-Length: {$size}");
// Close the connection.
header("Connection: close");
// Flush all output.
ob_end_flush();
ob_flush();
flush();
//All outputs have now been sent to the client
//You can continue executing your long tasks
include_once('createExcel.php');
createExcel.php
<?php
sleep(10); #You can use to checkthat the code works
//The above code will respond the client immediately and after ten seconds the Excel file will be created
require "PHPSpreadSheet/vendor/autoload.php";
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', $text);
$writer = new Xlsx($spreadsheet);
$writer->save('MyFile.xlsx');
Of course you have to make validations, so you don't have lots of running process in background but I hope the general idea has been shown in this example.
This is not exactly the code I use, but this is all it takes to continue executing code after responding the client.
In my own opinion, I thinks this is better than using exec() or similar functions which invoke the command terminal as that could be a potential vulnerability , so you don't have to change permissions or anything.
Note: If you're using sessions, Please remember to use session_write_close() because on heavy tasks will block the file until such task is finished.
I hope it helps :)
My answer was based on this blog: https://qastack.mx/programming/15273570/continue-processing-php-after-sending-http-response
I am calling an AJAX after each 5 seconds to update the some info of current logged-in user into database table in PHP.
But it creates a heavy load on my website, and website down after some time when there are multiple users logged-in on my website.
Is there any way to use some other techniques like Comet or Push to improve my script?
Here is a code i am using:
Javascript code:
jQuery(document).ready(function ($) {
update_data();
function update_data() {
$.ajax({
type: "POST",
url: "$URL",
data: {update_current_time:1},
success: function(response){
setTimeout(update_data, 5000);
},
error: function(){
setTimeout(update_data, 5000);
}
});
}
});
PHP code:
if(isset($_POST['update_current_time']))
{
$query = "UPDATE users SET user_timer=now() WHERE user_id=".$_SESSION['id'];
$db->execute();
echo 'success';
die;
}
To use push or comet you will need to setup up a "webserver" that will listen to some port. So this cannot be solved using pure php but needs a listener setup (unless you create your on listening server using php).
To stay at php you can check out ratchet.
Another common way to go would be a node.js server parrallel to your webserver.
If I ever encounter this use case, My Implementation would be using the session variable. Instead of writing to database every 5 seconds, I'd store the request timestamps in $_SESSION for like 1-2 Minutes, and then write the whole data at once. For this example lets consider that you wish to make it a minute(60 sec).
So the algorithm would be
Make the request from client side.
On the server check if the session variable $_SESSION['requestcount'] is set.
If its not set, then I shall set that variable to 1, also I'll store the timestamp in some sub-array and return status 200 OK.
If its set I'll check if the value for $_SESSION['requestcount'] is 12 (1 request every 5 seconds x 12).
If the value of $_SESSION['requestcount'] is less than 12 then I'll increment its value by 1 and return status 200 OK.
If the value of $_SESSION['requestcount'] is equal to or grater than 12 then I'll Get all data from the sub-array and prepare it to insert inside the database, Also reset the $_SESSION['requestcount'] to 0, if all is well return status 200 OK.
I have to use one asynchronous service. Everything I can do is send data to this service (I'm doing it with PHP and CURL) and send data to some url from this service. How can I react/wait for a response from this service?
Now I have two pages: first is sending data to service and the second takes a response from this service and inserts it to database. On a first page I'm checking some table while there isn't the response. But selecting from database few times per second is bad idea. But what I need to have: Send data from one page and get the response at the same page. I guess I can use some Ajax and make the async service sending data to the same page and wait for the response on this page.
I guess I wrote very hard because I can't fully explain what I need, so feel free to correct me.
As #Steve noted, PHP has no concept of asynchronousity. However there is a hack which allows to implement something similar to long-polling in PHP. The main point is to use a file ready to read in Javascript, i.e. JSON.
Here is a general flow:
Your single web page does AJAX request to your php script which send
appropriate request to the external service and immediately return
some response (e.g. empty) to the web page.
The web page starts to repeatedly request server for the same static
JSON file (by doing AJAX requests) until it appears (created by
callback script).
The external service passes response to your callback script which
save the response into the JSON file.
The web page get the response from the JSON file and outputs it.
Your easiest option is going to be ajax polling - send the request to the webservice, then poll every x seconds. The response handler (the script called by the webservice when it completes) need to save the data somewhere, eg database or session, and the poll script will check for this data.
Although this will add a little to server load, if you set the polling interval high enough it should be fine
session_start();
if(isset($_GET['sendrequest'])){
WebService:sendRequest(['callback_url'=>'thispage?receiveresponse=1'])
$_SESSION['response']=false;
die();
}elseif(isset($_GET['receiveresponse'])){
$response = WebService:receive();
$_SESSION['response'] = $response;
die();
}elseif(isset($_GET['checkresponse'])){
$data=[];
if($_SESSION['response']){
$data['success']=true;
$data['response']=$_SESSION['response'];
}else{
$data['success']=false;
}
header('Content-Type: application/json');
die(json_encode($data);
}
<html>
<head>....</head>
<body>
<a id="send" href="#">Send Request</a>
<div id="response"></div>
<script>
var poll;
$('#send').click(function(ev){
ev.preventDefault();
$post('?sendrequest=1', {...}, function(){
poll = setInterval(function(){
$get('?checkresponse=1', function(response){
if(response.success){
clearInterval(poll);
$('#response').html(response.response);
}
});
}), 3000);
});
});
</script>
</body>
</html>
I currently have a JS ajax script to load data from the Database, where the query is in load.php
How would I make auto load new content separately based on the server time and date?
Such as rather than having the whole DB table refresh every "5 Seconds"
But loading the current data once, then new data based on server time/date.
Here is my script>
<script language="JavaScript">
window.onload = function()
{
$('#feed').empty();
$('#feed').load("load.php");
}
</script>
You cannot initiate sending AJAX data from the server without a request from the client (browser). So you should use the first request (the browser requesting the page itself) to calculate the time offset on the server (in PHP), and put your .load() function inside a setTimeout which will execute that many seconds later. So your PHP file would look something like this:
$time = 4300 // or whatever, based on your server clock.
echo '<script language="JavaScript">
window.onload = function(){
$("#feed").empty();
/* if you want to execute it once at page load too:*/
$("#feed").load("load.php");
/* then load after $time milliseconds:*/
setTimeout(function(){
$("#feed").load("load.php");
},'.$time.');
}
</script>';
Remember that setTimeout's offset is supposed to be in milliseconds.
Websockets are another solution to your problem if you have full server access (like to sockets and stuff). They involve basically creating a websocket connection when the script is first executed, and then server and client can send messages to each other as they please. These messages can include the data you wish.