December 17th, 2008 at 12:32 pm
Here's a little trick how to print definitions of large arrays in a more beatiful way. Instead of passing a set of strings to the array() function, pass only one string to the explode() function!
For example, consider a section in the WordPress code (/wp-includes/post.php):
PHP:
-
// currently
-
$data =
compact( array( 'post_author',
'post_date',
'post_date_gmt',
-
'post_content', 'post_content_filtered', 'post_title', 'post_excerpt',
-
'post_status', 'post_type', 'comment_status', 'ping_status',
-
'post_password', 'post_name', 'to_ping', 'pinged', 'post_modified',
-
'post_modified_gmt', 'post_parent', 'menu_order', 'guid' ) );
-
-
// equals
-
$data =
compact( explode('|',
'post_author|post_date|post_date_gmt|post_content|'.
-
'post_content_filtered|post_title|post_excerpt|post_status|post_type|'.
-
'comment_status|ping_status|post_password|post_name|to_ping|pinged|'.
-
'post_modified|post_modified_gmt|post_parent|menu_order|guid' ) );
Not only is the second part shorter, but it is also easier to edit and to overview. Of course this always depends on how many elements your array has; it's rather ridiculous with small arrays.
0
Codebits
array, explode, PHP
December 11th, 2008 at 10:28 am
JSON is a great data transfer format, especially for AJAX style applications (much better than XML for that purpose). Fetching JSON from your server is usually not a big deal these days, since all common browsers provide the XMLHttpRequest.
But: It can be a big problem to fetch data from a third party server, due to the Same Origin Policy. Imagine you want to provide a service where people simply need to include a JS file from your server to make great things happen on their own sites. Fetching JSON with your script via XMLHttpRequest (even from your own server) will not work.
However, there's a great workaround, which I first saw at Jeffrey Sambells' site. His solution is more generic, as it's able to load any JavaScript (not only JSON data) dynamically. Also, it's compatible with the XMLHttpRequest functions. I just needed something to fetch my JSON, and I don't need all of the XMLHttpRequest. Yet I do want to use AJAX indicators and error handling. So I used his code and taylored a lightweight JSON fetcher. If compressed with a JavaScript packer, it is as tiny as 1.4 kB.
The client side
Here's the code for the fetcher. Save it as request.js or something and have it loaded with your other JS. You can also insert into other JS files.
JAVASCRIPT:
-
/*
-
XssJsonFetch
-
(C) 2008 Alex Günsche
-
Available under the MIT license
-
based on XssHttpRequest (c) 2005 Jeffrey Sambells <info@jeffreysambells.com>
-
see info and terms of use: http://jeffreysambells.com/posts/2006/03/06/centralized_ajax_services/
-
*/
-
-
var XhrCount = 0;
-
var XhrWatchList = [];
-
reqjson = [];
-
-
var Xhr = function() {
-
this.ins = ++XhrCount;
-
this.u;
-
this.so;
-
this.w;
-
this.wc = 0;
-
this.to = 5;
-
this.responseText = null;
-
this.status = null;
-
this.readyState = 0;
-
};
-
-
Xhr.prototype.onerror = function() {};
-
Xhr.prototype.onload = function() {};
-
-
Xhr.prototype.srs = function(a) {
-
if (this.readyState <a || a == 0) {
-
this.readyState = a;
-
-
if (this.readyState == 2)
-
{
-
this.srs(3);
-
if(typeof reqjson[this.ins] != 'undefined')
-
{
-
var re = reqjson[this.ins];
-
-
// this is more secure, but sometimes fails on complex objects
-
//re = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( re.replace(/"(\\.|[^"\\])*"/g, ''))) && re || false;
-
-
re = re || false;
-
-
this.responseText = re;
-
this.status = (re) ? 'ok' : 'string error';
-
}
-
else
-
{
-
this.status = 'noresult';
-
this.onerror();
-
}
-
-
this.so.parentNode.removeChild(this.so);
-
reqjson = [];
-
this.srs(4);
-
this.onload();
-
}
-
}
-
};
-
-
Xhr.prototype.load = function(u)
-
{
-
this.u = u;
-
this.so = document.createElement('script');
-
this.so.id = 'reqjson'+this.ins;
-
this.so.charset = 'utf-8';
-
-
this.srs(1);
-
this.so.type = 'text/javascript';
-
this.so.src = this.u + (this.u.indexOf('?') != -1 ? '&': '?') + 'jsonvar=reqjson' + this.ins;
-
this.so = document.getElementsByTagName('head')[0].appendChild(this.so);
-
XhrWatchList[this.ins] = this;
-
this.w = setInterval('XhrWatchList[' + this.ins + '].wl()', 50);
-
};
-
-
Xhr.prototype.wl = function()
-
{
-
this.wc++;
-
if (typeof reqjson[this.ins] != 'undefined')
-
{
-
clearInterval(this.w);
-
this.srs(2);
-
}
-
else if ( this.wc>= (this.to*20) )
-
{
-
clearInterval(this.w);
-
this.status = 'timeout';
-
this.onerror();
-
}
-
};
The server side
Of course, you need a part on the server to generate the dynamic parts. In this example, we simply output the date, but it can be any data that is expressible with a JSON string (and that's a lot). Save it as ajax.php in the same directory on the server.
PHP:
-
<?php
-
header("Expires: Mon, 01 Jan 2000 05:00:00 GMT");
-
-
header("Cache-Control: no-cache, must-revalidate");
-
-
header("Content-Type: text/javascript");
-
-
// $results could as well be an array or any type of a scalar
-
// if you use an array, be sure that the keys and structure match what your JS expects
-
$results =
date('d.m.Y H:i:s');
-
-
$json = json_encode($results);
-
-
$reqvar =
preg_match('|^reqjson[0-9]+$|',
$_GET['jsonvar'])
-
?
'reqjson['.
str_replace('reqjson',
'',
$_GET['jsonvar']).
']'
-
: 'reqjson[0]';
-
-
-
?>
... and a demo
A little demo to show you the integration into your own project. Save it as demo.html in the same directory as the other two, then load it in your browser.
HTML:
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-
-
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
-
<script type="text/javascript" src="request.js"></script>
-
-
#main { border: 1px solid #888; padding: 10px; margin: 50px auto; width: 30em; }
-
#dynfield { color: #090; }
-
#button { border: 1px outset #888; padding: 3px; background: #eee; cursor: pointer; }
-
</style>
-
<script type='text/javascript'>/*
<![CDATA[ */
-
window.onload = function()
-
{
-
var $ = function(el) { return document.getElementById(el); };
-
-
// the event to trigger the request
-
$('button').onclick = function()
-
{
-
// if you use an indicator, make it appear here
-
-
// any URL, relative or absolute, with parameters or without, even from a third-party server
-
var url = "ajax.php";
-
-
var http = new Xhr;
-
http.load(url);
-
-
http.onload = function()
-
{
-
// hide your indicator
-
-
// here happens everything you need to perform with your fetched JSON
-
var serverdate = http.responseText;
-
if (serverdate) { $('dynfield').firstChild.data = serverdate; }
-
};
-
-
http.onerror = function() {
-
// some error handling (and hide indicator)
-
alert('Error: ' + http.status);
-
};
-
};
-
};
-
/* ]]> */</script>
-
-
</head>
-
-
-
<p>The server date is:
<strong id="dynfield"> </strong></p>
-
<p><span id="button">retrieve
</span></p>
-
</div>
-
</body>
-
</html>
0
Codebits
AJAX, Cross Site Scripting, JSON, XMLHttpRequest