I have a piece of php code:
....
for ($i=0; $i < count($files); $i++) { $rows = array_chunk($files, 5); }
....
Where I want to have the chunk length “5” as dynamic (to display items different way in different view port width), accordingly to the visitor’s browser’s view port width.
Exmpl:
if view port >= 800px – the chunk length = 5
if view port >= 680px – the chunk length = 4
etc…
I know that I need to get the view port size (width) via Javascript and I know how to dial with that part, but all the problem is to pass that value to a php variable to implement it in that piece of code.
So I need to use GET or POST method, I tried several ways, but I can’t make it work really.
Maybe I need to create a page loading at first, to do this calculation and redirecting then user to the main page with that value in a PHP variable or something like this?.
These kind of things should be done always with CSS and Javascript. PHP has no connection to these components. PHP is "static" while your viewport (width and height) are dynamically.
If you insist on doing it anyway then the following solution:
read data via JavaScript (keyword "SelfHTML Document height" or "SelfHTML Window height")
when you have the data, you pass the data
via $_POST and hidden input fields
via $_GET parameter or
via Ajax
The parameters you send to your PHP script can then be used.
But now again why you should not do it:
Problem A: I call your website, your PHP has received all possible data, has built me a layout, now I change the size, your PHP script has not noticed anything, and I have problems with the operation of your page.
Problem B: The values can open an unwanted security vulnerability, so I could pass e.g. as width or height or other information in the worst case a script via these parameters to infiltrate your server, ie you must ALWAYS validate these values.
Related
Background:
I am making a simple game in PHP, JavaScript and HTML for the web. A player control movements of a box on the screen, and see others fly around with their boxes.
I have the following files, that I upload to my domain via a hosting company:
index.html: a file with some buttons (eg. to start the game) and frames (for putting boxes in).
server.php: PHP script that receives messages from client, performs reads/writes to a database, echoes (using echo) boxes from database to the client. Does not echo the box of the player the message came from.
database.txt: a JSON text file containing data of players and the next free ID number. When empty it looks like this: {"players":[], "id": 1}. players contain objects with values such as ID, position and rotation.
script.js: JavaScript file with script to send/receive messages, display data from messages etc. Linked to index.html. Moves your box.
A screenshot, two players in movement:
Problem: The game crashes, always. Sooner or later. This is what happens:
Client recevies player data from server.php, everything is fine. This could be for 10 seconds or up to some minutes.
The data starts to falter, the message sometimes is null instead of actual data.
The data recevied is always null. The database file is now {"players":null,"id":5}. (The "id" could be any number, does not have to be 5).
Picture of data flow, printing of players from database. Two players. Before this screenshot lots of rows with valid data. Then as seen two null messages. Then after a while null forever.
I am not completely sure where the problem is, but I am guessing it has to do with my read/write in server.php. I feels like a lot of player movement makes the program more likely to crash. Also how often the program sends data affetcs.
Code Piece 1: This is code from server.php, that writes to the database. I have some sort of semaphore (the flock( ... ) ) to prevent clients from reading/writing at the same time (causing errors). I have an other function, read, which is very similar to this. Possible problems here:
The semaphore is incorrect.
The mode for fopen() is incorrect. See PHP docs. The mode w is for write. The tag b is for "If you do not specify the 'b' flag when working with binary files, you may experience strange problems with your data ...".
Something weird happening because I use read() in my writing function?
Code:
// Write $val to $obj in database JSON
function write($obj,$val){
$content = read();
$json = json_decode($content);
$json->{$obj} = $val; // eg. $json->{'id'} = 5;
$myfile = fopen("database.txt", "wb") or die("Unable to open file!");
if(flock($myfile, LOCK_EX|LOCK_NB)) {
fwrite($myfile,json_encode($json));
flock($myfile, LOCK_UN);
}
fclose($myfile);
}
Code Piece 2: This is my code to send data. It is called via a setInterval(). In script.js:
// Send message to server.php, call callback with answer
function communicate(messageFunc,callback){
var message = messageFunc();
if (window.XMLHttpRequest) {
var xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange= function() {
if (this.readyState==4 && this.status==200) {
callback(this.responseText);
}
}
xmlhttp.open("GET","server.php?msg="+message,true);
xmlhttp.send();
}
This is my code to receive data, in server.php: $receive = $_GET["msg"].
My current work of solving
This is what I have done so far, but nothing has changed:
Added mode b to fopen().
Added flock() to read/write functions in server.php.
Much reworking on script.js, I would say it looks/works very clean.
Check memory_get_peak_usage(), and check with the hosting company for memory limits. Should be no problem at all.
Looked at PHP garbage collecting and gc_enable() (I don't know why that would change anything).
Lots of testing, looking at the data flow.
Crying.
Conclusion: Is this type of application what PHP is for? What do you think is wrong? If you want more code/info I provide. Thank you very much.
Here is the root of your problem:
$myfile = fopen("database.txt", "wb") or die("Unable to open file!");
Note the behavior of the w open mode (emphasis mine):
Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
This happens before you lock the file. What's happening is that between this fopen() call and the following flock() call, the file's content is zero length, and a reader is coming along during that time and reading the empty file.
Why doesn't this cause an error in PHP when you parse the empty string as JSON? Because json_decode() is defective, and returns null when the input is not valid JSON rather than throwing an exception. Nevermind that the string "null" is valid JSON -- json_decode() gives you no way to differentiate between the cases of valid input representing the null value and invalid input. If json_decode() actually threw an exception or triggered a PHP error (don't ask me why two error-signalling mechanisms are necessary in PHP), you would have a fantastic point to start debugging to figure out why the file is empty, and you might have solved this problem by now!
... sigh ...
PHP's "design" gives me headaches. But I digress.
To fix this whole problem, change the open mode to "cb" and ftruncate($myfile, 0) after you successfully acquire the lock.
Note the behavior of the c mode, which actually specifically mentions the approach you are using (emphasis mine):
Open the file for writing only. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). The file pointer is positioned on the beginning of the file. This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, as using 'w' could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested).
I have to implement buttons that allow for simple image editing (Grayscale, turning it +/- 90° etc.). I have a selection of images (with a radio button to each) and upon clicking on one of the buttons, I call a function that makes an Ajax GET request with the relative image url and the action called (turn x degrees, grayscale...). PHP successfully receives the call and also sends a response.
Unfortunately, the response data is only gibberish
�����JFIF���������>CREATOR: gd-jpeg v1.0 (using IJG JPEG v90), default quality ���C�...
The content-type is set though (and also sent as such, confirmed using Firebug)
Content-Type: image/jpeg
However, when I check the data that Ajax receives, it just shows the folder structure of my local server (localhost/...) and [object%20Object].
This is the function where I make the request
Javascript in HTML file
var selection = document.getElementById('selection').src;
var y = $.get("image.php", { "image": selection, "type" : "jpeg" } );
PHP
$img = imagecreatefromjpeg($_GET['image']);
imagefilter($img, IMG_FILTER_GRAYSCALE);
header("Content-type: image/jpeg");
imagejpeg($img);
imagedestroy($img);
Is there any way to make this work? If not, are there any other options I could take? I thought about saving the edited image in a separate folder and only returning the path to it but I way I am trying to do it now seems a little bit easier in terms of getting it to work (at least I thought so...)
I am trying to use javascript in my CI view to update (without refresh) a data model every 2 seconds, for my use case where the database contents can be changed by other users.
<script type="text/javascript">
var refreshFunc = setInterval(function() {
<?php
$this -> load -> model('m_cube', '', TRUE);
$stamp = $this -> $m_cube -> stamp();
?>
var stamp = "<?php echo $stamp; ?>";
console.log(stamp);
}, 2000);
refreshFunc;
</script>
I am using JS setInterval to create the 2 second loop, and calling the CI model to retrieve data from the Postgresql database. In the simplified code sample, it's just asking the DB for a timestamp. The problem is that the timestamp written to console doesn't update - something is stuck.
2013-10-21 14:35:54.168-04
2013-10-21 14:35:54.168-04
2013-10-21 14:35:54.168-04
...
Same behavior when querying a table of real data - it doesn't return up-to-date values.
Why does the model access a "frozen" version of the DB?
It's not stuck or "frozen", it's that you had a bit of confusion on what comes before and what after.
I don't see you using AJAX, so by the time your php has been processed (i.e, the data fetched from the db and assigned to $stamp) the page - html, css and javascript too - are yet to be generated and served by the server, nor outputted by the browser.
This means that inside your setInterval you always have the same value, which has been already generated, and thus you keep reprinting the same string.
If you want a continue update, you need to keep requesting the data to the server, and that's where AJAX (Asynchronous JavaScript and XML) can be handy since it runs as a separate request from the main one, so you can work on two different "levels" and fetch content while the rest of the page remains static (already served and outputted).
If you're using jQUery you can look into $.ajax(), which makes this kind of things pretty easy.
When this script runs at the server it fetches the model data and replace the <?php ?> tags with the results. So when it comes to client browser, it doesn't contact server every 2 seconds, but logs the stamp value every 2 seconds. If you want it to be updated you should consider using Ajax technology.
I've got 2 HTML files and 1 javascript file, index.html, results.html and file.js
Inside index.html I retrieve user input which is used to do some calculations inside the javascript file. The calculating starts when a button is pressed. Now I want to display the data retrieved from index.html to display on results.html so when pressing the button it should run the function and go to another page.
It all works fine to calculate and show the results on 1 page, but I don't know how to display the results on results.html.
This is how a piece of the code looks:
function berekenKoolBehoefte(){
koolBehoefte = (energieBehoefte - (eiwitBehoefte * 4) - vetBehoefte) / 4;
toonKool();
}
function toonKool(){
var uitkomstKool = document.getElementById("uitkomstKool");
uitkomstKool.innerHTML = (koolBehoefte * 4).toFixed(1) + " kcal" + " " + koolBehoefte.toFixed(1) + " gram"
}
bereken.addEventListener('click', berekenKoolBehoefte, false);
This displays all on 1 page, know function toonKool() should be display inside results.html
Your best bet in this case is to use:
server side to store the values and get the results from there
cookies - if it's small data, simply put it inside a cookie. For more info how to use cookies with plain javascript look here
attach your results to url and then parse them with JS. You can see how it's done here
iFrame - you can attach your results in an iframe and access the
data. This method is quite good, but for my taste - it's awful
I think you'd better:
1) Create form on your page aroud the button.
2) On form submit do calculations and put result to hidden field in the form (Or post all fields for calculation to server side). Then all arguments that you want to pass would be accessible on server on second page.
3) Display second page using GET or POST argument from previous.
Cookies is something that you may forgot to clear and it's much harder to manage them.
Calculation in iframe is much worse then using ajax. You may use ajax for partial load the second page, then all javascript variables would remain.
I am working on creating a RESTful API that supports cross-domain requests, JSON/JSONP support, and the main HTTP method (PUT/GET/POST/DELETE). Now while will be easy to accessing this API through server side code , it would nice to exposed it to javascript. From what I can tell, when doing a JSONP requests with jQuery, it only supports the GET method. Is there a way to do a JSONP request using POST/PUT/DELETE?
Ideally I would like a way to do this from within jQuery (through a plugin if the core does not support this), but I will take a plain javascript solution too. Any links to working code or how to code it would be helpful, thanks.
Actually - there is a way to support POST requests.
And there is no need in a PROXI server - just a small utility HTML page that is described bellow.
Here's how you get Effectively a POST cross-domain call, including attached files and multi-part and all :)
Here first are the steps in understanding the idea, after that - find an implementation sample.
How JSONP of jQuery is implemented, and why doesn't it support POST requests?
While the traditional JSONP is implemented by creating a script element and appending it into the DOM - what results inforcing the browser to fire an HTTP request to retrieve the source for the tag, and then execute it as JavaScript, the HTTP request that the browser fires is simple GET.
What is not limited to GET requests?
A FORM. Submit the FORM while specifing action the cross-domain server.
A FORM tag can be created completely using a script, populated with all fields using script, set all necessary attributes, injected into the DOM, and then submitted - all using script.
But how can we submit a FORM without refreshing the page?
We specify the target the form to an IFRAME in the same page.
An IFRAME can also be created, set, named and injected to the DOM using script.
But How can we hide this work from the user?
We'll contain both FORM and IFRAME in a hidden DIV using style="display:none"
(and here's the most complicated part of the technique, be patient)
But IFRAME from another domain cannot call a callback on it's top-level document. How to overcome that?
Indeed , if a response from FORM submit is a page from another domain, any script communication between the top-level page and the page in the IFRAME results in "access denied". So the server cannot callback using a script. What can the server can do? redirect. The server may redirect to any page - including pages in the same domain as the top-level document - pages that can invoke the callback for us.
How can a server redirect?
two ways:
Using client side script like <Script>location.href = 'some-url'</script>
Using HTTP-Header. See: http://www.webconfs.com/how-to-redirect-a-webpage.php
So I end up with another page? How does it help me?
This is a simple utility page that will be used from all cross-domain calls. Actually, this page is in-fact a kind of a proxi, but it is not a server, but a simple and static HTML page, that anybody with notepad and a browser can use.
All this page has to do is invoke the callback on the top-level document, with the response-data from the server. Client-Side scripting has access to all URL parts, and the server can put it's response there encoded as part of it, as well as the name of the callback that has to be invoked. Means - this page can be a static and HTML page, and does not have to be a dynamic server-side page :)
This utility page will take the information from the URL it runs in - specifically in my implementation bellow - the Query-String parameters (or you can write your own implementation using anchor-ID - i.e the part of a url right to the "#" sign). And since this page is static - it can be even allowed to be cached :)
Won't adding for every POST request a DIV, a SCRIPT and an IFRAME eventually leak memory?
If you leave it in the page - it will. If you clean after you - it will not. All we have to do is give an ID to the DIV that we can use to celan-up the DIV and the FORM and IFRAME inside it whenever the response arrives from the server, or times out.
What do we get?
Effectively a POST cross-domain call, including attached files and multi-part and all :)
What are the limits?
The server response is limited to whatever fits into a redirection.
The server must ALWAYS return a REDIRECT to a POST requests. That include 404 and 500 errors.
Alternatively - create a timeout on the client just before firing the request, so you'll have a chance to detect requests that have not returned.
not everybody can understand all this and all the stages involved. it's a kind of an infrastructure level work, but once you get it running - it rocks :)
Can I use it for PUT and DELETE calls?
FORM tag does not PUT and DELETE.
But that's better then nothing :)
Ok, got the concept. How is it done technically?
What I do is:
I create the DIV, style it as invisible, and append it to the DOM. I also give it an ID that I can clean it up from the DOM after the server response has arrived (the same way JQuery cleans it's JSONP SCRIPT tasgs - but the DIV).
Then I compose a string that contains both IFRAME and FORM - with all attributes, properties and input fields, and inject it into the invisible DIV. it is important to inject this string into the DIV only AFTER the div is in the DOM. If not - it will not work on all browsers.
After that - I obtain a reference to the FORM and submit it.
Just remember one line before that - to set a Timeout callback in case the server does not respond, or responds in a wrong way.
The callback function contains the clean-up code. It is also called by timer in case of a response-timeout (and cleans it's timeout-timer when a server response arrives).
Show me the code!
The code snippet bellow is totally "neutral" on "pure" javascript, and declares whatever utility it needs. Just for simplification of explaining the idea - it all runs on the global scope, however it should be a little more sophisticated...
Organize it in functions as you may and parameterize what you need - but make sure that all parts that need to see each other run on the same scope :)
For this example - assume the client runs on http://samedomain.com and the server runs on http://crossdomain.com.
The script code on the top-level document
//declare the Async-call callback function on the global scope
function myAsyncJSONPCallback(data){
//clean up
var e = document.getElementById(id);
if (e) e.parentNode.removeChild(e);
clearTimeout(timeout);
if (data && data.error){
//handle errors & TIMEOUTS
//...
return;
}
//use data
//...
}
var serverUrl = "http://crossdomain.com/server/page"
, params = { param1 : "value of param 1" //I assume this value to be passed
, param2 : "value of param 2" //here I just declare it...
, callback: "myAsyncJSONPCallback"
}
, clientUtilityUrl = "http://samedomain.com/utils/postResponse.html"
, id = "some-unique-id"// unique Request ID. You can generate it your own way
, div = document.createElement("DIV") //this is where the actual work start!
, HTML = [ "<IFRAME name='ifr_",id,"'></IFRAME>"
, "<form target='ifr_",id,"' method='POST' action='",serverUrl
, "' id='frm_",id,"' enctype='multipart/form-data'>"
]
, each, pval, timeout;
//augment utility func to make the array a "StringBuffer" - see usage bellow
HTML.add = function(){
for (var i =0; i < arguments.length; i++)
this[this.length] = arguments[i];
}
//add rurl to the params object - part of infrastructure work
params.rurl = clientUtilityUrl //ABSOLUTE URL to the utility page must be on
//the SAME DOMAIN as page that makes the request
//add all params to composed string of FORM and IFRAME inside the FORM tag
for(each in params){
pval = params[each].toString().replace(/\"/g,""");//assure: that " mark will not break
HTML.add("<input name='",each,"' value='",pval,"'/>"); // the composed string
}
//close FORM tag in composed string and put all parts together
HTML.add("</form>");
HTML = HTML.join(""); //Now the composed HTML string ready :)
//prepare the DIV
div.id = id; // this ID is used to clean-up once the response has come, or timeout is detected
div.style.display = "none"; //assure the DIV will not influence UI
//TRICKY: append the DIV to the DOM and *ONLY THEN* inject the HTML in it
// for some reason it works in all browsers only this way. Injecting the DIV as part
// of a composed string did not always work for me
document.body.appendChild(div);
div.innerHTML = HTML;
//TRICKY: note that myAsyncJSONPCallback must see the 'timeout' variable
timeout = setTimeout("myAsyncJSONPCallback({error:'TIMEOUT'})",4000);
document.getElementById("frm_"+id+).submit();
The server on the cross-domain
The response from the server is expected to be a REDIRECTION, either by HTTP-Header or by writing a SCRIPT tag. (redirection is better, SCRIPT tag is easier to debug with JS breakpoints).
Here's the example of the header, assuming the rurl value from above
Location: http://samedomain.com/HTML/page?callback=myAsyncJSONPCallback&data=whatever_the_server_has_to_return
Note that
the value of the data argument can be a JavaScript Object-Literal or JSON expression, however it better be url-encoded.
the length of the server response is limited to the length of a URL a browser can process.
Also - in my system the server has a default value for the rurl so that this parameter is optional. But you can do that only if your client-application and server-application are coupled.
APIs to emit redirection header:
http://www.webconfs.com/how-to-redirect-a-webpage.php
Alternatively, you can have the server write as a response the following:
<script>
location.href="http://samedomain.com/HTML/page?callback=myAsyncJSONPCallback&data=whatever_the_server_has_to_return"
</script>
But HTTP-Headers would be considered more clean ;)
The utility page on the same domain as the top-level document
I use the same utility page as rurl for all my post requests: all it does is take the name of the callback and the parameters from the Query-String using client side code, and call it on the parent document. It can do it ONLY when this page runs in the EXACT same domain as the page that fired the request! Important: Unlike cookies - subdomains do not count!! It has to he the exact same domain.
It's also make it more efficient if this utility page contains no references to other resources -including JS libraries. So this page is plain JavaScript. But you can implement it however you like.
Here's the responder page that I use, who's URL is found in the rurl of the POST request (in the example: http://samedomain.com/utils/postResponse.html )
<html><head>
<script type="text/javascript">
//parse and organize all QS parameters in a more comfortable way
var params = {};
if (location.search.length > 1) {
var i, arr = location.search.substr(1).split("&");
for (i = 0; i < arr.length; i++) {
arr[i] = arr[i].split("=");
params[arr[i][0]] = unescape(arr[i][1]);
}
}
//support server answer as JavaScript Object-Literals or JSON:
// evaluate the data expression
try {
eval("params.data = " + params.data);
} catch (e) {
params.data = {error: "server response failed with evaluation error: " + e.message
,data : params.data
}
}
//invoke the callback on the parent
try{
window.parent[ params.callback ](params.data || "no-data-returned");
}catch(e){
//if something went wrong - at least let's learn about it in the
// console (in addition to the timeout)
throw "Problem in passing POST response to host page: \n\n" + e.message;
}
</script>
</head><body></body></html>
It's not much automation and 'ready-made' library like jQuery and involes some 'manual' work - but it has the charm :)
If you're a keen fan of ready-made libraries - you can also check on Dojo Toolkit that when last I checked (about a year ago) - had their own implementation for the same mechanism.
http://dojotoolkit.org/
Good luck buddy, I hope it helps...
Is there a way to do a JSONP request using POST/PUT/DELETE?
No there isn't.
No. Consider what JSONP is: an injection of a new <script> tag in the document. The browser performs a GET request to pull the script pointed to by the src attribute. There's no way to specify any other HTTP verb when doing this.
Rather than banging our heads with JSONP method, that actually won't
support POST method by default, we can go for CORS .That will provide no big changes in the conventional way of programming. By simple Jquery Ajax call we can go with cross domains.
In CORS method, you have to add headers in server side scripting file, or in the server itself(in remote domain), for enabling this access. This is much reliable, since we can prevent/restrict the domains making unwanted calls.
It can be found in detail in wikipedia page.