Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added hackday toolbox

  • Loading branch information...
commit c6177167a03171e2912130ec14724e984f655b60 0 parents
@codepo8 authored
Showing with 6,106 additions and 0 deletions.
  1. +88 −0 index.html
  2. +608 −0 phpforhacks/index.html
  3. +321 −0 phpforhacks/index.php
  4. BIN  phpforhacks/links.png
  5. BIN  phpforhacks/parameters.png
  6. BIN  phpforhacks/php-rendered.png
  7. BIN  phpforhacks/phperrorlog.png
  8. BIN  phpforhacks/print_r-demo.png
  9. BIN  phpforhacks/smashingmagwithcurl.png
  10. BIN  phpforhacks/variables-rendered.png
  11. +35 −0 styles.css
  12. +114 −0 yahoo-maps/index.html
  13. +52 −0 yql-flickr-photos-js/index.html
  14. +61 −0 yql-flickr-photos-yui/index.html
  15. +87 −0 yql-form/index.html
  16. +88 −0 yql-form/index.php
  17. +138 −0 yql-geo-library/index.html
  18. +136 −0 yql-geo-library/yqlgeo.js
  19. +28 −0 yql-open-table-with-js/count-tags.xml
  20. +102 −0 yql-open-table-with-js/index.php
  21. +19 −0 yql-open-table-with-js/results.xml
  22. +69 −0 yql-with-javascript/index.html
  23. +74 −0 yql-with-php-authenticated/index.php
  24. +8 −0 yql-with-php-authenticated/keys.php
  25. +803 −0 yql-with-php-authenticated/lib/JSON.php
  26. +1,003 −0 yql-with-php-authenticated/lib/OAuth.php
  27. +2,007 −0 yql-with-php-authenticated/lib/Yahoo.inc
  28. +120 −0 yql-with-php-authenticated/lib/YahooSessionStore.inc
  29. +69 −0 yql-with-php-simple/index.php
  30. +63 −0 yql-with-yui3/index.html
  31. +13 −0 yui.css
88 index.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>The Hackday Toolbox</title>
+ <link rel="stylesheet" type="text/css" href="yui.css">
+ <link rel="stylesheet" href="styles.css" type="text/css">
+</head>
+<body class="yui-skin-sam">
+<div id="doc2" class="yui-t5">
+ <div id="hd" role="banner">
+ <h1>The Hackday Toolbox</h1>
+ <p class="update">Version: 1.0 (28/07/2010) - <a href="">check for updates on GitHub</a></p>
+ </div>
+ <div id="bd" role="main">
+ <div id="yui-main">
+ <div class="yui-b">
+ <div id="intro">
+ <p>The Hackday Toolbox is a collection of demo code that should get you going when you are competing in a hackathon or hackday. It was compiled to avoid having to explain the same problems over and over again and instead to give you a simple example to start from.</p>
+ <p>This is not meant to be a document to surf but instead to try out and look at the source code. All the client-side examples have all the code in-line and you can start altering it to your needs. The PHP examples you need to look at the source in the editor of your choice.</p>
+ <p>You can <a href="">download the Hackday Toolbox at GitHub</a>. All the code here is <a href="http://wait-till-i.com/license.txt">licensed with BSD</a> - so go nuts.</p>
+ </div>
+ <h2>Hack demo code</h2>
+ <ul class="nav">
+ <li>Setup and general language information:
+ <ul>
+ <li><a href="phpforhacks/index.html">Using PHP for hacks</a></li>
+ </ul>
+ </li>
+ <li>Geo and location based services
+ <ul>
+ <li><a href="yql-geo-library/index.html">Getting all kind of geographical and visitor information with YQLGeo</a></li>
+ <li><a href="yahoo-maps/index.html">Using Yahoo Maps with GeoPlanet data</a></li>
+ </ul>
+ </li>
+ <li>YQL client side
+ <ul>
+ <li><a href="yql-with-javascript/index.html">Using YQL with JavaScript</a></li>
+ <li><a href="yql-with-php-simple/index.php">Using YQL with PHP (open data)</a></li>
+ <li><a href="yql-with-yui3/index.html">Using YQL with YUI3 (open data)</a></li>
+ <li><a href="yql-form/index.html">Showing a form to query YQL data with JavaScript</a></li>
+ <li><a href="yql-flickr-photos-js/index.html">Demo of showing Flickr photos using YQL and <code>flickr.photolist</code> in JavaScript</a></li>
+ <li><a href="yql-flickr-photos-yui/index.html">Demo of showing Flickr photos using YQL and YUI3</a></li>
+ <li><a href="yql-open-table-with-js/index.php">Using JavaScript in an open table</a></li>
+ </ul>
+ </li>
+ <li>YQL server side
+ <ul>
+ <li><a href="yql-with-php-simple/index.php">Using YQL with PHP (open data)</a></li>
+ <li><a href="yql-with-php-authenticated/index.php">Using YQL with PHP (oAuth authenticated data)</a></li>
+ <li><a href="yql-form/index.php">Showing a form to query YQL data with PHP</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div class="yui-b" id="sb">
+ <h2>Resources</h2>
+ <ul class="nav resource">
+ <li>PHP:
+ <ul>
+ <li><a href="http://php.net">PHP documentation</a></li>
+ </ul>
+ </li>
+ <li>YQL:
+ <ul>
+ <li><a href="http://developer.yahoo.com/yql">Official documentation</a></li>
+ <li><a href="http://developer.yahoo.com/yql/console">Interactive console</a></li>
+ <li><a href="http://github.com/yql/yql-tables">Open Tables repository on GitHub</a></li>
+ <li><a href="http://developer.yahoo.net/forum/?showforum=41&cookiecheckonly=1">Forum</a></li>
+ </ul>
+ </li>
+ <li>YUI:
+ <ul>
+ <li><a href="http://developer.yahoo.com/yui">Official documentation</a></li>
+ <li><a href="http://yuilibrary.com/forum/viewforum.php?f=15">Forums</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Hackday toolbox by <a href="http://wait-till-i.com">Chris Heilmann</a>.</p>
+ </div>
+
+</div>
+</body>
+</html>
608 phpforhacks/index.html
@@ -0,0 +1,608 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Using PHP for hacks</title>
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.8.0/build/reset-fonts-grids/reset-fonts-grids.css&2.8.0/build/base/base-min.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <style type="text/css" media="screen">
+ body{font-family:verdana,sans-serif;width:700px;margin:10px auto;}
+ p img{display:block;margin:10px 0;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+
+ <div id="hd" role="banner">
+ <h1>Using PHP for hacks</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+
+
+
+<p>In this article I want to introduce you to the basics of PHP. We'll concentrate specifically on PHP to access web services and turn static HTML pages into dynamic ones by retrieving data from the web and by showing different content dependent on what users entered in forms or requested in the URL. You won't come out at the end of this article as a professional PHP developer but it'll get you well on the way of building a small page that uses web services. You can find a lot of great PHP info out on the web and most of the time you will end up on the <a href="http://php.net">PHP.net</a> site itself. I was however asked repeatedly on several hack days and competitions to write this quick introduction article - so here it is. </p>
+
+<h2>What is PHP?</h2>
+
+PHP is a server-side language that has become a massive success because of three reasons:
+<ul>
+<li>It is a very easy, forgiving language - variables can be anything and you can create them any time you want to.</li>
+<li>it is part of the free LAMP stack (Linux, Apache, MySQL, PHP) and thus available on almost any server you can rent on the web.</li>
+<li>it does not need any special editor, environment or build process. All you do is create a file with the <code>.php</code> file type, mix PHP and HTML and put it on your server for displaying.</li>
+</ul>
+
+<h2>Installing PHP locally and your first code</h2>
+
+<p>To run PHP locally on your computer you need a local server with PHP enabled. The easiest way is to download and install <a href="">MAMP for OSX</a> or <a href="">XAMPP for Windows</a>. Once you have any of these packages installed you can start using PHP. Simply create a file called <code>index.php</code> in the <code>htdocs</code> folder of your MAMP or XAMPP install. </p>
+
+<p>In this file, type (or actually copy + paste) the following:</p>
+
+<pre><code>&lt;?php
+ $myname = &#x27;Chris&#x27;;
+ echo &#x27;&lt;p&gt;This is PHP&lt;/p&gt;&#x27;;
+ echo &quot;&lt;p&gt;My name is $myname&lt;/p&gt;&quot;
+ echo &#x27;&lt;p&gt;My name in another notation is still &#x27;.$myname.&#x27;&lt;/p&gt;&#x27;;
+?&gt;</code></pre>
+
+<p>If you open this file in a browser by accessing your XAMPP or MAMP install (via http://localhost/index.php or http://localhost:8888/index.php) you should get the following:</p>
+
+<pre><code>This is PHP
+My name is Chris
+My name in another notation is still Chris</code></pre>
+
+<p>However, you won't. The problem is that the third line does not end in a semicolon ";". This is an error. Depending on what PHP installation you have you either get an error message or simply nothing. If you got nothing, find the file called <code>php_error.log</code> on your hard drive and open it - it will tell you what went wrong <img src="phperrorlog.png" alt="The PHP error log as shown on a Mac">. So, the first thing to remember is that every line of PHP needs to end in a semicolon. If we fix this problem <a href="http://icant.co.uk/articles/phpforhacks/index.php">we get the result</a>:<img src="php-rendered.png" alt="PHP rendered in a browser"></p>
+
+<pre><code>&lt;?php
+ $myname = &#x27;Chris&#x27;;
+ echo &#x27;&lt;p&gt;This is PHP&lt;/p&gt;&#x27;;
+ echo &quot;&lt;p&gt;My name is $myname&lt;/p&gt;&quot;;
+ echo &#x27;&lt;p&gt;My name in another notation is still &#x27;.$myname.&#x27;&lt;/p&gt;&#x27;;
+?&gt;</code></pre>
+
+
+
+<p>You can see the first few features of PHP that are important:</p>
+
+<ul>
+<li>PHP blocks start with <code>&lt?php</code> and end with <code>?&gt;</code> - anything within these two commands will be interpreted as PHP and returned to the document as HTML.</li>
+<li>Every line of PHP has to end with a semicolon ";" - otherwise it is an error.</li>
+<li>Variables in PHP start with a $ - not with the var keyword like you'd do it in JavaScript (this is where it gets confusing with jQuery and Prototype)</li>
+<li>You print out content to the document in PHP with the <code>echo</code> command. There is also a <code>print</code> command which does almost the same so you can use that, too.</li>
+<li>In this example we define a string called <code>myname</code> as "Chris". To print it out with the echo command surrounded by other text you need to either embed the variable name in a text with quotation marks or to concatenate the string with a full stop when you use single quotation marks. This is line 3 and 4 - they do the same but show the different syntax. Concatenation is always achieved with the full stop - never with a + as you do in JavaScript.</li>
+</ul>
+
+<p>You can jump in and out of PHP anywhere in the document. So if you intersperse PHP with HTML blocks, that is totally fine. For example:</p>
+
+<pre><code>&lt;?php
+ $origin = &#x27;Outer Space&#x27;;
+ $planet = &#x27;Earth&#x27;;
+ $plan = 9;
+ $sceneryType = &quot;awful&quot;;
+?&gt;
+&lt;h1&gt;Synopsis&lt;/h1&gt;
+
+&lt;p&gt;It was a peaceful time on planet &lt;?php echo $planet;?&gt;
+and people in the &lt;?php echo $sceneryType;?&gt; scenery were unaware
+of the diabolic plan &lt;?php echo $plan;?&gt; from &lt;?php echo $origin;?&gt;
+that will take their senses to the edge of what can be endured.&lt;/p&gt;</code></pre>
+
+<p>This <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=1">has the following output</a>: <img src="variables-rendered.png" alt="Rendered variables in PHP"></p>
+
+<p>Are you with me so far? If you want to show something on the screen, you use echo - if it is numbers or a string. If you need to show more complex structures, you need loops or specialized debugging methods.</p>
+
+<h2>Displaying more complex data types</h2>
+
+<p>You can define arrays in PHP using the <code>array()</code> method:</p>
+
+<pre><code>$lampstack = array('Linux','Apache','MySQL','PHP');</code></pre>
+
+<p>If you simply want to display a complex datatype like this in PHP for debugging you can use the <code>print_r()</code> command:</p>
+
+<pre><code>$lampstack = array('Linux','Apache','MySQL','PHP');
+print_r($lampstack);</code></pre>
+
+<p><a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=2">This gives you all the information</a> but it doesn't help you structuring it as HTML: <img src="print_r-demo.png" alt="Displaying arrays with print_r"> For this, you need to access the elements with the array counter. In PHP this is done with the <code>[]</code> brackets:</p>
+
+<pre><code>&lt;ul&gt;
+&lt;?php
+$lampstack = array(&#x27;Linux&#x27;,&#x27;Apache&#x27;,&#x27;MySQL&#x27;,&#x27;PHP&#x27;);
+echo &#x27;&lt;li&gt;Operating System:&#x27;.$lampstack[0] . &#x27;&lt;/li&gt;&#x27;;
+echo &#x27;&lt;li&gt;Server:&#x27; . $lampstack[1] . &#x27;&lt;/li&gt;&#x27;;
+echo &#x27;&lt;li&gt;Database:&#x27; . $lampstack[2] . &#x27;&lt;/li&gt;&#x27;;
+echo &#x27;&lt;li&gt;Language:&#x27; . $lampstack[3] . &#x27;&lt;/li&gt;&#x27;;
+?&gt;
+&lt;/ul&gt;</code></pre>
+<p>See this <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=3">demo in action</a>.</p>
+
+<p>This of course is stupid programming as it is not flexible. If you get the chance to make a computer do your dirty work for you, make it do it. In this case, <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=4">we could define two arrays and use a loop</a>:</p>
+
+<pre><code>&lt;ul&gt;
+&lt;?php
+$lampstack = array(&#x27;Linux&#x27;,&#x27;Apache&#x27;,&#x27;MySQL&#x27;,&#x27;PHP&#x27;);
+$labels = array(&#x27;Operating System&#x27;,&#x27;Server&#x27;,&#x27;Database&#x27;,&#x27;Language&#x27;);
+$length = sizeof($lampstack);
+for( $i = 0;$i &lt; $length;$i++ ){
+ echo &#x27;&lt;li&gt;&#x27; . $labels[$i] . &#x27;:&#x27; . $lampstack[$i] . &#x27;&lt;/li&gt;&#x27;;
+}
+?&gt;
+&lt;/ul&gt;</code></pre>
+
+<p>The for loop works the same way as it does in JavaScript - the only difference is that you read the size of an array not with <code>array.length</code> but with <code>sizeof($array)</code> instead.</p>
+
+<p>Again, this example is not really clever, as it assumes that both the <code>$lampstack</code> and the <code>$labels</code> array are the same length and in the same order. Instead of using this, <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=5">I'd use an associated array</a>:</p>
+
+<pre><code>&lt;ul&gt;
+&lt;?php
+$lampstack = array(
+ &#x27;Operating System&#x27; =&gt; &#x27;Linux&#x27;,
+ &#x27;Server&#x27; =&gt; &#x27;Apache&#x27;,
+ &#x27;Database&#x27; =&gt; &#x27;MySQL&#x27;,
+ &#x27;Language&#x27; =&gt; &#x27;PHP&#x27;
+);
+$length = sizeof($lampstack);
+$keys = array_keys($lampstack);
+for( $i = 0;$i &lt; $length;$i++ ){
+ echo &#x27;&lt;li&gt;&#x27; . $keys[$i] . &#x27;:&#x27; . $lampstack[$keys[$i]] . &#x27;&lt;/li&gt;&#x27;;
+}
+?&gt;
+&lt;/ul&gt;
+</code></pre>
+
+<p>The function <code>array_keys()</code> gives you back all the keys of an array as an array itself. This way we can display the keys and the values at the same time.</p>
+
+<p>A shorter way of achieving the same principle which works both with arrays and with objects is <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=6">using the <code>foreach()</code> loop construct</a>:</p>
+
+<pre><code>&lt;ul&gt;
+&lt;?php
+$lampstack = array(
+ &#x27;Operating System&#x27; =&gt; &#x27;Linux&#x27;,
+ &#x27;Server&#x27; =&gt; &#x27;Apache&#x27;,
+ &#x27;Database&#x27; =&gt; &#x27;MySQL&#x27;,
+ &#x27;Language&#x27; =&gt; &#x27;PHP&#x27;
+);
+foreach( $lampstack as $key =&gt; $stackelm ){
+ echo &#x27;&lt;li&gt;&#x27; . $key . &#x27;:&#x27; . $stackelm . &#x27;&lt;/li&gt;&#x27;;
+}
+?&gt;
+&lt;/ul&gt;</code></pre>
+
+<p>This is the shortest way of displaying a complex construct - it will however also fail when <code>$lampstack</code> is not an array. So checking for <code>sizeof()</code> is still a good plan. You do this with a conditional.</p>
+
+<h2>Using conditionals</h2>
+
+<p>Conditionals are if statements - both in the English language and in almost any programming language I know. So for example to test if an array is safe to loop over <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=7">you use the <code>sizeof()</code> test</a>:</p>
+
+<pre><code>&lt;ul&gt;
+&lt;?php
+$lampstack = array(
+ &#x27;Operating System&#x27; =&gt; &#x27;Linux&#x27;,
+ &#x27;Server&#x27; =&gt; &#x27;Apache&#x27;,
+ &#x27;Database&#x27; =&gt; &#x27;MySQL&#x27;,
+ &#x27;Language&#x27; =&gt; &#x27;PHP&#x27;
+);
+if( sizeof($lampstack) &gt; 0 ){
+ foreach( $lampstack as $key =&gt; $stackelm ){
+ echo &#x27;&lt;li&gt;&#x27; . $key . &#x27;:&#x27; . $stackelm . &#x27;&lt;/li&gt;&#x27;;
+ }
+}
+?&gt;
+&lt;/ul&gt;</code></pre>
+
+<p>Common conditionals are: </p>
+
+<ul>
+<li><code>if($x > 10 and $x < 20)</code> - is <code>$x</code> larger than 10 and less than 20?</li>
+<li><code>if(isset($name))</code> - has the variable <code>$name</code> been defined?</li>
+<li><code>if($name == 'Chris')</code> - does the variable <code>$name</code> have the value Chris?</li>
+<li><code>if($name == 'Chris' or $name == 'Vitaly')</code> - does the variable <code>$name</code> have the value Chris or the value Vitaly?</li>
+</ul>
+
+<p>Cool, but what if you want to make that reusable?</p>
+
+<h2>Functions in PHP</h2>
+
+<p>In order to make a task even more generic, you can write a function. In this case we put <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=8">the loop and the testing in a function and simply call it with different arrays</a>:</p>
+
+<pre><code>&lt;?php
+function renderList($array){
+ if( sizeof($array) &gt; 0 ){
+ echo &#x27;&lt;ul&gt;&#x27;;
+ foreach( $array as $key =&gt; $item ){
+ echo &#x27;&lt;li&gt;&#x27; . $key . &#x27;:&#x27; . $item . &#x27;&lt;/li&gt;&#x27;;
+ }
+ echo &#x27;&lt;/ul&gt;&#x27;;
+ }
+}
+$lampstack = array(
+ &#x27;Operating System&#x27; =&gt; &#x27;Linux&#x27;,
+ &#x27;Server&#x27; =&gt; &#x27;Apache&#x27;,
+ &#x27;Database&#x27; =&gt; &#x27;MySQL&#x27;,
+ &#x27;Language&#x27; =&gt; &#x27;PHP&#x27;
+);
+renderList($lampstack);
+
+$awfulacting = array(
+ &#x27;Natalie Portman&#x27; =&gt; &#x27;Star Wars&#x27;,
+ &#x27;Arnold Schwarzenegger&#x27; =&gt; &#x27;Batman and Robin&#x27;,
+ &#x27;Keanu Reaves&#x27; =&gt; &#x27;*&#x27;
+);
+renderList($awfulacting);
+?&gt;</code></pre>
+
+<p>Notice that functions do not start with a dollar sign.</p>
+
+<p>That is already most of the magic of PHP. The rest is all about functions that are build for you to do all kind of things: convert strings, sort arrays, find things in other things, access the file system, set cookies and many more functions - all of which doing one thing and one thing right. I keep catching myself writing complex functions in PHP just to realize looking at the docs that there is a native function for that.</p>
+
+<h2>Interacting with the web - URL parameters</h2>
+
+<p>Let's start playing with the web in PHP - or, better said - information that comes from the browser address bar or forms for you to re-use. In order to get parameters from the current URL you use the global <code>$_GET</code> array. So, if you call the index.php script with <code>http://localhost/index.php?language=fr&font=large</code> you can change the display and locale by checking for these settings. The <code>language</code> parameter will be available as <code>$_GET['language']</code> and the <code>font</code> parameter as <code> $_GET['font']</code>:
+
+<pre><code>&lt;?php
+$name = &#x27;Chris&#x27;;
+
+// if there is no language defined, switch to English
+if( !isset($_GET[&#x27;language&#x27;]) ){
+ $welcome = &#x27;Oh, hello there, &#x27;;
+}
+if( $_GET[&#x27;language&#x27;] == &#x27;fr&#x27; ){
+ $welcome = &#x27;Salut, &#x27;;
+}
+switch($_GET[&#x27;font&#x27;]){
+ case &#x27;small&#x27;:
+ $size = 80;
+ break;
+ case &#x27;medium&#x27;:
+ $size = 100;
+ break;
+ case &#x27;large&#x27;:
+ $size = 120;
+ break;
+ default:
+ $size = 100;
+ break;
+}
+echo &#x27;&lt;style&gt;body{font-size:&#x27; . $size . &#x27;%;}&lt;/style&gt;&#x27;;
+echo &#x27;&lt;h1&gt;&#x27;.$welcome.$name.&#x27;&lt;/h1&gt;&#x27;;
+?&gt;</code></pre>
+
+<p>This means now that you can send URL parameters to change the behaviour of this document:<img src="parameters.png" alt="changing the content and look of a document with parameters"></p>
+
+<ul>
+ <li><a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=9">http://localhost:8888/index.php</a></li>
+ <li><a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=9&language=fr">http://localhost:8888/index.php?language=fr</a></li>
+ <li><a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=9&language=fr&font=large">http://localhost:8888/index.php?language=fr&font=large</a></li>
+</ul>
+
+<p>Notice that it is always the best to predefine a set of values that are acceptable for a certain parameter. The earlier example might as well have the font size in pixels as a parameter and we write that to the document but that means that we need to write a good validation script to prevent end users from sending bad values or even malicious code through the parameter.</p>
+<p>Sending malicious code via a parameter without filtering is called <a href="http://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29">Cross Site Scripting or XSS</a> and is one of the big security problems of the web. You can prevent against it by not printing out the values of parameters but instead using them in comparisons and by using the <a href="http://uk.php.net/manual/en/intro.filter.php">filters provided by PHP</a>.</p>
+
+<p>Say for example you want to allow users to enter some data with a form that you will display later on. Make sure that you filter out the results:</p>
+
+<pre><code>&lt;?php
+ $search_html = filter_input(INPUT_GET, &#x27;s&#x27;,
+ FILTER_SANITIZE_SPECIAL_CHARS);
+ $search_url = filter_input(INPUT_GET, &#x27;s&#x27;,
+ FILTER_SANITIZE_ENCODED);
+?&gt;
+&lt;form action=&quot;index.php&quot; method=&quot;get&quot;&gt;
+ &lt;div&gt;
+ &lt;label for=&quot;search&quot;&gt;Search:&lt;/label&gt;
+ &lt;input type=&quot;text&quot; name=&quot;s&quot; id=&quot;search&quot;
+ value=&quot;&lt;?php echo $search_html;?&gt;&quot;&gt;
+ &lt;/div&gt;
+ &lt;div class=&quot;bar&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Make it so&quot;&gt;&lt;/div&gt;
+&lt;/form&gt;
+&lt;?php
+if(isset($_GET['s'])){
+ echo &#x27;&lt;h2&gt;You searched for &#x27;.$search_html.&#x27;&lt;/h2&gt;&#x27;;
+ echo &#x27;&lt;p&gt;&lt;a href=&quot;index.php?search=&#x27;.$search_url.&#x27;&quot;&gt;Search again.&lt;/a&gt;&lt;/p&gt;&#x27;;
+}
+?&gt;</code></pre>
+
+<p>See the <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=10">filtering example in action</a>. Without the filters, attackers could send parameters like <code>index.php?s=&quot;&lt;script&gt;</code> which would execute third party code in your site. With filtering this malicious code gets converted to HTML entities.</p>
+
+<p>If you want to use POST as the method to send the data in your form the PHP variables change accordingly to <code>$_POST</code> for the array and <code>INPUT_POST</code> for the filter.</p>
+
+<h2>Loading content from the web</h2>
+
+<p>PHP comes with a lot of <a href="http://uk2.php.net/manual/en/ref.filesystem.php">file functions</a> that allow you to read and write files from the hard drive or load content from the web. I found however that for security reasons a lot of hosting companies disable them - especially when you try to read content from a third party resource. The workaround is to use cURL to load information from the web. cURL is a tool that allows you to make HTTP requests and get the information back from them - so to say a browser in command form. I've <a href="http://www.wait-till-i.com/2009/12/18/curl-your-view-source-of-the-web/">written a detailed post about cURL and how to use it</a>, so here's just the most simple use case for you:</p>
+
+<pre><code>&lt;?php
+ // define the URL to load
+ $url = &#x27;http://www.smashingmagazine.com&#x27;;
+ // start cURL
+ $ch = curl_init();
+ // tell cURL what the URL is
+ curl_setopt($ch, CURLOPT_URL, $url);
+ // tell cURL that you want the data back from that URL
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // run cURL
+ $output = curl_exec($ch);
+ // end the cURL call (this also cleans up memory so it is
+ // important)
+ curl_close($ch);
+ // display the output
+ echo $output;
+?&gt;</code></pre>
+
+
+<p><a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=11">If you run this in a browser</a>, you see the Smashing Magazine homepage. <img src="smashingmagwithcurl.png" alt="Smashing Magazine homepage loaded with cURL"> You can however also take that data and strip out content:</p>
+
+<pre><code>&lt;?php
+ // define the URL to load
+ $url = &#x27;http://www.smashingmagazine.com&#x27;;
+ // start cURL
+ $ch = curl_init();
+ // tell cURL what the URL is
+ curl_setopt($ch, CURLOPT_URL, $url);
+ // tell cURL that you want the data back from that URL
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // run cURL
+ $output = curl_exec($ch);
+ // end the cURL call (this also cleans up memory so it is
+ // important)
+ curl_close($ch);
+ // if a filter parameter with the value links was sent
+ if($_GET[&#x27;filter&#x27;] == &#x27;links&#x27;){
+ // get all the links from the document and show them
+ echo &#x27;&lt;ul&gt;&#x27;;
+ preg_match_all(&#x27;/&lt;a[^&gt;]+&gt;[^&lt;\/a&gt;]+&lt;\/a&gt;/msi&#x27;,$output,$links);
+ foreach($links[0] as $l){
+ echo &#x27;&lt;li&gt;&#x27; . $l . &#x27;&lt;/li&gt;&#x27;;
+ }
+ echo&#x27;&lt;/ul&gt;&#x27;;
+ // otherwise just show the page
+ } else {
+ echo $output;
+ }
+?&gt;</code></pre>
+
+<p>If you open this in your browser you <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=12&filter=true">get all the links on smashing magazine</a> and none of the other content. <img src="links.png" alt="Smashing magazine links"> In nowaday's web development you are more likely to use APIs than loading web sites though, which is why you need a way to convert XML and JSON returned from a web service into PHP friendly data.</p>
+
+<h2>Displaying XML content</h2>
+
+<p>The easiest way to deal with XML content in PHP is to use the <a href="http://php.net/manual/en/book.simplexml.php">SimpleXML functions of PHP</a>. Using this we can turn a bunch of XML into a PHP object and loop over this. Say for example you want to <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=13">show the Smashing Magazine RSS feed</a> you can do the following:</p>
+
+<pre><code>&lt;?php
+ $url = &#x27;http://rss1.smashingmagazine.com/feed/&#x27;;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = simplexml_load_string($output);
+ echo &#x27;&lt;ul&gt;&#x27;;
+ foreach($data-&gt;entry as $e){
+ echo &#x27;&lt;li&gt;&lt;a href=&quot;&#x27; . $e-&gt;link[0][&#x27;href&#x27;] .
+ &#x27;&quot;&gt;&#x27;.$e-&gt;title.&#x27;&lt;/a&gt;&lt;/li&gt;&#x27;;
+ }
+ echo &#x27;&lt;/ul&gt;&#x27;;
+?&gt;</code></pre>
+
+<p>The <code>simplexml_load_string()</code> function takes the XML document and turns it into a PHP object with arrays. How did I find out to loop over <code>data->entry</code> and get the <code>href</code> via <code>link[0]['href']</code>? Simple. I did a <code>print_r($output)</code> and checked the source of the document with CMD+U in Firefox on my mac. That showed me that <code>entry</code> is an array. I then did a <code>print_r($e)</code> in the loop to see all the properties of every entry. If it is part of the <code>@attributes</code> array, you need to use the <code>[]</code> notation.</p>
+
+<p>That's all. The only stumbling block you will encounter are CDATA blocks and namespaces in SimpleXML. Stuart Herbert <a href="http://blog.stuartherbert.com/php/2007/01/07/using-simplexml-to-parse-rss-feeds/">has a good introduction to these two issues in this article</a>.</p>
+
+<h2>Displaying JSON content</h2>
+
+<p>The data format <a href="http://json.org">JSON</a> is the low-fat alternative to XML. It is far less complex (no namespaces) and if you work in a JavaScript environment, it is native to the browser. This makes it very fast and easy to use and thus started to become a very much used data format for APIs. In essence, JSON is a JavaScript object. So for example I could write the LAMP stack example as:</p>
+<pre><code>{"lampstack":
+ {
+ "operatingsystem" : "Linux",
+ "server" : "Apache",
+ "database" : "MySQL",
+ "language" : "PHP"
+ }
+}</code></pre>
+
+<p>You can <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=14">convert this to PHP using the <code>json_decode()</code> method</a> and get it back as a PHP object:</p>
+
+<pre><code>&lt;?php
+ $json = &#x27;{
+ &quot;lampstack&quot;:
+ {
+ &quot;operatingsystem&quot;:&quot;Linux&quot;,
+ &quot;server&quot;:&quot;Apache&quot;,
+ &quot;database&quot;:&quot;MySQL&quot;,
+ &quot;language&quot;:&quot;PHP&quot;
+ }
+ }&#x27;;
+ print_r(json_decode($json));
+?&gt;</code></pre>
+
+<p>One API that returns JSON is the <a href="http://apiwiki.twitter.com/Twitter-Search-API-Method%3A-trends">Twitter trends API</a>. For example if you load this API's URL with cURL and do a <code>print_r()</code> after <code>json_decode()</code> you <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=15">get the following back</a>:</p>
+
+<pre><code>&lt;?php
+ $url = &#x27;http://search.twitter.com/trends.json&#x27;;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ print_r($data);
+?&gt;</code></pre>
+
+<pre><code>stdClass Object
+(
+[trends] => Array
+ (
+ [0] => stdClass Object
+ (
+ [name] => #nowplaying
+ [url] => http://search.twitter.com/search?q=%23nowplaying
+ )
+
+ [1] => stdClass Object
+ (
+ [name] => #Didntwannatellyou
+ [url] => http://search.twitter.com/search?q=%23Didntwannatellyou
+ )
+
+ [2] => stdClass Object
+ (
+ [name] => #HappyBirthdayGagaBR
+ [url] => http://search.twitter.com/search?q=%23HappyBirthdayGagaBR
+ )
+
+ [3] => stdClass Object
+ (
+ [name] => Justin Bieber
+ [url] => http://search.twitter.com/search?q=%22Justin+Bieber%22
+ )
+
+ [4] => stdClass Object
+ (
+ [name] => #FreakyFactSays
+ [url] => http://search.twitter.com/search?q=%23FreakyFactSays
+ )
+
+ [5] => stdClass Object
+ (
+ [name] => #YouSoGangsta
+ [url] => http://search.twitter.com/search?q=%23YouSoGangsta
+ )
+
+ [6] => stdClass Object
+ (
+ [name] => I ♥
+ [url] => http://search.twitter.com/search?q=%22I+%E2%99%A5%22
+ )
+
+ [7] => stdClass Object
+ (
+ [name] => #MeMyselfandTime
+ [url] => http://search.twitter.com/search?q=%23MeMyselfandTime
+ )
+
+ [8] => stdClass Object
+ (
+ [name] => #2010yearofJonas
+ [url] => http://search.twitter.com/search?q=%232010yearofJonas
+ )
+
+ [9] => stdClass Object
+ (
+ [name] => Easter
+ [url] => http://search.twitter.com/search?q=Easter
+ )
+ )
+ [as_of] => Sun, 28 Mar 2010 19:31:30 +0000
+)
+</code></pre>
+
+<p>You can then use a simple loop to <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=16">render the current trends as an unordered list</a>:</p>
+
+<pre><code>&lt;?php
+ $url = &#x27;http://search.twitter.com/trends.json&#x27;;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ echo &#x27;&lt;h2&gt;Twitter trending topics (&#x27;.$data-&gt;as_of.&#x27;)&lt;/h2&gt;&#x27;;
+ echo &#x27;&lt;ul&gt;&#x27;;
+ foreach ($data-&gt;trends as $t){
+ echo &#x27;&lt;li&gt;&lt;a href=&quot;&#x27;.$t-&gt;url.&#x27;&quot;&gt;&#x27;.$t-&gt;name.&#x27;&lt;/a&gt;&lt;/li&gt;&#x27;;
+ }
+ echo &#x27;&lt;/ul&gt;&#x27;;
+?&gt;</code></pre>
+
+<h2>Putting it all together</h2>
+
+<p>Let's do a quick example using all the things we learnt so far - a simple search interface for the web.</p>
+
+<p>Using <a href="http://developer.yahoo.com/yql/">Yahoo's YQL</a> it is pretty easy to do a web search for "cat" with the command <code>select * from search.web where query="cat"</code> sent to the YQL endpoint. You can define JSON as the return format and the rest means you simply <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=17">enhance the earlier form example</a>:</p>
+
+<pre><code>&lt;?php
+ $search_html = filter_input(INPUT_GET, &#x27;s&#x27;, FILTER_SANITIZE_SPECIAL_CHARS);
+ $search_url = filter_input(INPUT_GET, &#x27;s&#x27;, FILTER_SANITIZE_ENCODED);
+?&gt;
+&lt;form action=&quot;index.php&quot; method=&quot;get&quot;&gt;
+ &lt;div&gt;
+ &lt;label for=&quot;search&quot;&gt;Search:&lt;/label&gt;
+ &lt;input type=&quot;text&quot; name=&quot;s&quot; id=&quot;search&quot;
+ value=&quot;&lt;?php echo $search_html;?&gt;&quot;&gt;
+ &lt;input type=&quot;hidden&quot; name=&quot;demo&quot; value=&quot;17&quot;&gt;
+ &lt;input type=&quot;submit&quot; value=&quot;Make it so&quot;&gt;
+ &lt;/div&gt;
+&lt;/form&gt;
+&lt;?php
+if(isset($_GET[&#x27;s&#x27;])){
+ echo &#x27;&lt;h2&gt;You searched for &#x27;.$search_html.&#x27;&lt;/h2&gt;&#x27;;
+ $yql = &#x27;select * from search.web where query=&quot;&#x27;.$search_url.&#x27;&quot;&#x27;;
+ $url = &#x27;http://query.yahooapis.com/v1/public/yql?q=&#x27;.
+ urlencode($yql).&#x27;&amp;format=json&amp;diagnostics=false&#x27;;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ echo &#x27;&lt;ul&gt;&#x27;;
+ foreach ($data-&gt;query-&gt;results-&gt;result as $r){
+ echo &#x27;&lt;li&gt;&lt;h3&gt;&lt;a href=&quot;&#x27;.$r-&gt;clickurl.&#x27;&quot;&gt;&#x27;.$r-&gt;title.&#x27;&lt;/a&gt;&lt;/h3&gt;&#x27;.
+ &#x27;&lt;p&gt;&#x27;.$r-&gt;abstract.&#x27; &lt;span&gt;(&#x27;.$r-&gt;dispurl.&#x27;)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&#x27;;
+ }
+ echo &#x27;&lt;/ul&gt;&#x27;;
+
+ echo &#x27;&lt;p&gt;&lt;a href=&quot;index.php?search=&#x27;.$search_url.&#x27;&amp;demo=17&quot;&gt;Search again.&lt;/a&gt;&lt;/p&gt;&#x27;;
+}
+?&gt;</code></pre>
+
+<h2>Interaction with JavaScript</h2>
+
+<p>One thing that people keep asking about is to send information from PHP and JavaScript and back. This is done in a few ways.</p>
+<ul>
+ <li>If you want to send information from JavaScript to PHP you need to either alter the <code>href</code> of a link or populate a hidden form field. The other solution of course is to use Ajax.</li>
+ <li>If you want to send information from PHP to JavaScript simply render a script element and write out the PHP information with an <code>echo</code> statement.</li>
+ <li>Using PHP's <code>header()</code> function and <code>json_encode()</code> you can send data back to the browser as JavaScript and thus make it possible to use it as a <code>src</code> attribute of a <code>script</code> node.</li>
+</ul>
+
+<p>So for example when you want to have the smashing magazine RSS feed as a JavaScript object, <a href="http://icant.co.uk/articles/phpforhacks/index.php?demo=18">you can do the following</a>:</p>
+
+<pre><code>&lt;?php
+ header(&#x27;Content-type: text/javascript&#x27;);
+ $url = &#x27;http://rss1.smashingmagazine.com/feed/&#x27;;
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = simplexml_load_string($output);
+ $data = json_encode($data);
+ echo &#x27;var smashingrss=&#x27;.$data;
+?&gt;</code></pre>
+
+<p>You could then use this in a JavaScript block:</p>
+
+<pre><code>&lt;script src=&quot;http://icant.co.uk/articles/phpforhacks/index.php?demo=18&quot;&gt;&lt;/script&gt;
+&lt;script&gt;alert(smashingrss.title);&lt;/script&gt;</code></pre>
+
+<p>Using <code>header()</code> and <code>json_encode()</code> you could do any complex conversion and filtering in PHP and re-use it in JavaScript.</p>
+
+<h2>Summary</h2>
+
+<p>I hope this gave you an idea of what PHP is and how you can use it to use web services and build your own APIs to re-use in JavaScript. Using PHP for the web boils down to a few tricks:</p>
+
+<ul>
+ <li>Use cURL to load data from web resources</li>
+ <li>Convert information with <code>simplexml_load_string()</code> and <code>json_decode()</code></li>
+ <li>Check the structure of returned information with <code>print_r()</code></li>
+ <li>Loop over information with <code>foreach()</code></li>
+ <li>Use the <code>$_GET[]</code> and <code>$_POST[]</code> arrays to re-use form data and URL parameters</li>
+ <li>Filter information from the user and URLs using the inbuilt PHP filter methods</li>
+</ul>
+
+<p>There is a lot of documentation out there, and your best bet is to go directly to the <a href="http://php.net">PHP homepage</a> and read/download the docs. You should especially check the user-added comments as this is where the real gems ands implementation examples are listed.</p>
+
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+
+</div>
+</body>
+</html>
321 phpforhacks/index.php
@@ -0,0 +1,321 @@
+<?php if(!isset($_GET['demo'])){/*
+ Simple PHP demo
+*/?><?php
+ $myname = 'Chris';
+ echo '<p>This is PHP!</p>';
+ echo "<p>My name is $myname</p>";
+ echo '<p>My name in another notation is still '.$myname.'</p>';
+?><?php }?><?php if($_GET['demo']=='1'){/*
+ Showing the interaction between PHP and HTML
+*/?><?php
+ $origin = 'Outer Space';
+ $planet = 'Earth';
+ $plan = 9;
+ $sceneryType = "awful";
+?>
+<h1>Synopsis</h1>
+
+<p>It was a peaceful time on planet <?php echo $planet;?>
+and people in the <?php echo $sceneryType;?> scenery were unaware
+of the diabolic plan <?php echo $plan;?> from <?php echo $origin;?>
+that will take their senses to the edge of what can be endured.</p>
+<?php }?><?php if($_GET['demo']=='2'){/*
+ Using print_r() for debugging
+*/?><?php
+$lampstack = array('Linux','Apache','MySQL','PHP');
+print_r($lampstack);
+?><?php }?><?php if($_GET['demo']=='3'){/*
+ Accessing array members
+*/?><ul><?php
+$lampstack = array('Linux','Apache','MySQL','PHP');
+echo '<li>Operating System:'.$lampstack[0] . '</li>';
+echo '<li>Server:' . $lampstack[1] . '</li>';
+echo '<li>Database:' . $lampstack[2] . '</li>';
+echo '<li>Language:' . $lampstack[3] . '</li>';
+?></ul><?php }?><?php if($_GET['demo']=='4'){/*
+ Looping over arrays
+*/?><ul><?php
+$lampstack = array('Linux','Apache','MySQL','PHP');
+$labels = array('Operating System','Server','Database','Language');
+$length = sizeof($lampstack);
+for( $i = 0;$i < $length;$i++ ){
+ echo '<li>' . $labels[$i] . ':' . $lampstack[$i] . '</li>';
+}
+?></ul><?php }?><?php if($_GET['demo']=='5'){/*
+ Using array keys and several arrays
+*/?><ul><?php
+$lampstack = array(
+ 'Operating System' => 'Linux',
+ 'Server' => 'Apache',
+ 'Database' => 'MySQL',
+ 'Language' => 'PHP'
+);
+$length = sizeof($lampstack);
+$keys = array_keys($lampstack);
+for( $i = 0;$i < $length;$i++ ){
+ echo '<li>' . $keys[$i] . ':' . $lampstack[$keys[$i]] . '</li>';
+}
+?></ul><?php }?><?php if($_GET['demo']=='6'){/*
+ Looping over an associative array
+*/?><ul><?php
+$lampstack = array(
+ 'Operating System' => 'Linux',
+ 'Server' => 'Apache',
+ 'Database' => 'MySQL',
+ 'Language' => 'PHP'
+);
+foreach( $lampstack as $key => $stackelm ){
+ echo '<li>' . $key . ':' . $stackelm . '</li>';
+}
+?>
+</ul><?php }?><?php if($_GET['demo']=='7'){/*
+ Using foreach
+*/?><ul><?php
+$lampstack = array(
+ 'Operating System' => 'Linux',
+ 'Server' => 'Apache',
+ 'Database' => 'MySQL',
+ 'Language' => 'PHP'
+);
+if( sizeof($lampstack) > 0 ){
+ foreach( $lampstack as $key => $stackelm ){
+ echo '<li>' . $key . ':' . $stackelm . '</li>';
+ }
+}
+?>
+</ul>
+<?php }?><?php if($_GET['demo']=='8'){/*
+ Writing a reusable function
+*/?><?php
+function renderList($array){
+ if( sizeof($array) > 0 ){
+ echo '<ul>';
+ foreach( $array as $key => $item ){
+ echo '<li>' . $key . ':' . $item . '</li>';
+ }
+ echo '</ul>';
+ }
+}
+$lampstack = array(
+ 'Operating System' => 'Linux',
+ 'Server' => 'Apache',
+ 'Database' => 'MySQL',
+ 'Language' => 'PHP'
+);
+renderList($lampstack);
+
+$awfulacting = array(
+ 'Natalie Portman' => 'Star Wars',
+ 'Arnold Schwarzenegger' => 'Batman and Robin',
+ 'Keanu Reaves' => '*'
+);
+renderList($awfulacting);
+?><?php }?><?php if($_GET['demo']=='9'){/*
+ Using $_GET parameters
+*/?><?php
+$name = 'Chris';
+// if there is no language defined, switch to English
+if( !isset($_GET['language']) ){
+ $welcome = 'Oh, hello there, ';
+}
+if( $_GET['language'] == 'fr' )
+ $welcome = 'Salut, ';
+
+switch($_GET['font']){
+ case 'small':
+ $size = 80;
+ break;
+ case 'medium':
+ $size = 100;
+ break;
+ case 'large':
+ $size = 120;
+ break;
+ default:
+ $size = 100;
+ break;
+}
+echo '<style>body{font-size:' . $size . '%;}</style>';
+echo '<h1>'.$welcome.$name.'</h1>';
+?><?php }?><?php if($_GET['demo']=='10'){/*
+ Parameter filtering
+*/?><?php
+ $search_html = filter_input(INPUT_GET, 's', FILTER_SANITIZE_SPECIAL_CHARS);
+ $search_url = filter_input(INPUT_GET, 's', FILTER_SANITIZE_ENCODED);
+?>
+<form action="index.php" method="get">
+ <div>
+ <label for="search">Search:</label>
+ <input type="text" name="s" id="search"
+ value="<?php echo $search_html;?>">
+ <input type="hidden" name="demo" value="10">
+ <input type="submit" value="Make it so">
+ </div>
+</form>
+<?php
+if(isset($_GET['s'])){
+ echo '<h2>You searched for '.$search_html.'</h2>';
+ echo '<p><a href="index.php?search='.$search_url.'">Search again.</a></p>';
+}?><?php }?><?php if($_GET['demo']=='11'){/*
+ Loading HTML
+*/?><?php
+ // define the URL to load
+ $url = 'http://www.smashingmagazine.com';
+ // start cURL
+ $ch = curl_init();
+ // tell cURL what the URL is
+ curl_setopt($ch, CURLOPT_URL, $url);
+ // tell cURL that you want the data back from that URL
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // run cURL
+ $output = curl_exec($ch);
+ // end the cURL call (this also cleans up memory so it is
+ // important)
+ curl_close($ch);
+ // display the output
+ echo $output;
+?><?php }?><?php if($_GET['demo']=='12'){/*
+ Loading and filtering HTML
+*/?><?php
+ // define the URL to load
+ $url = 'http://www.smashingmagazine.com';
+ // start cURL
+ $ch = curl_init();
+ // tell cURL what the URL is
+ curl_setopt($ch, CURLOPT_URL, $url);
+ // tell cURL that you want the data back from that URL
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // run cURL
+ $output = curl_exec($ch);
+ // end the cURL call (this also cleans up memory so it is
+ // important)
+ curl_close($ch);
+ // if a filter parameter with the value links was sent
+ if($_GET['filter'] == 'links'){
+ // get all the links from the document and show them
+ echo '<ul>';
+ preg_match_all('/<a[^>]+>[^<\/a>]+<\/a>/msi',$output,$links);
+ foreach($links[0] as $l){
+ echo '<li>' . $l . '</li>';
+ }
+ echo'</ul>';
+ // otherwise just show the page
+ } else {
+ echo $output;
+ }
+?><?php }?><?php if($_GET['demo']=='13'){/*
+ Loading and displaying XML
+*/?><?php
+ $url = 'http://rss1.smashingmagazine.com/feed/';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = simplexml_load_string($output);
+ echo '<ul>';
+ foreach($data->entry as $e){
+ echo '<li><a href="'.$e->link[0]['href'].'">'.$e->title.'</a></li>';
+ }
+ echo '</ul>';
+?><?php }?><?php if($_GET['demo']=='14'){/*
+ JSON example
+*/?><?php
+ $json = '{
+ "lampstack":
+ {
+ "operatingsystem":"Linux",
+ "server":"Apache",
+ "database":"MySQL",
+ "language":"PHP"
+ }
+ }';
+ print_r(json_decode($json));
+?>
+<?php }?><?php if($_GET['demo']=='15'){/*
+ JSON API example
+*/?><pre><?php
+ $url = 'http://search.twitter.com/trends.json';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ print_r($data);
+?></pre>
+<?php }?><?php if($_GET['demo']=='16'){/*
+ Format JSON API results example
+*/?><?php
+ $url = 'http://search.twitter.com/trends.json';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ echo '<h2>Twitter trending topics ('.$data->as_of.')</h2>';
+ echo '<ul>';
+ foreach ($data->trends as $t){
+ echo '<li><a href="'.$t->url.'">'.$t->name.'</a></li>';
+ }
+ echo '</ul>';
+?>
+<?php }?><?php if($_GET['demo']=='17'){/*
+ Web search example
+*/?><?php
+ $search_html = filter_input(INPUT_GET, 's', FILTER_SANITIZE_SPECIAL_CHARS);
+ $search_url = filter_input(INPUT_GET, 's', FILTER_SANITIZE_ENCODED);
+?>
+<form action="index.php" method="get">
+ <div>
+ <label for="search">Search:</label>
+ <input type="text" name="s" id="search"
+ value="<?php echo $search_html;?>">
+ <input type="hidden" name="demo" value="17">
+ <input type="submit" value="Make it so">
+ </div>
+</form>
+<?php
+if(isset($_GET['s'])){
+ echo '<h2>You searched for '.$search_html.'</h2>';
+ $yql = 'select * from search.web where query="'.$search_url.'"';
+ $url = 'http://query.yahooapis.com/v1/public/yql?q='.
+ urlencode($yql).'&format=json&diagnostics=false';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = json_decode($output);
+ echo '<ul>';
+ foreach ($data->query->results->result as $r){
+ echo '<li><h3><a href="'.$r->clickurl.'">'.$r->title.'</a></h3>'.
+ '<p>'.$r->abstract.' <span>('.$r->dispurl.')</span></p></li>';
+ }
+ echo '</ul>';
+
+ echo '<p><a href="index.php?search='.$search_url.'&demo=17">Search again.</a></p>';
+}
+?>
+<?php }?><?php if($_GET['demo']=='18'){/*
+ Loading XML and converting it to JavaScript
+*/?><?php
+ header('Content-type: text/javascript');
+ $url = 'http://rss1.smashingmagazine.com/feed/';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ $data = simplexml_load_string($output);
+ $data = json_encode($data);
+ echo 'var smashingrss='.$data;
+?>
+<?php }?><?php if($_GET['demo']=='19'){/*
+ Including XML as JavaScript
+*/?><?php
+ echo '<script src="http://icant.co.uk/articles/phpforhacks/index.php?demo=18"></script>';
+ echo '<script>alert(smashingrss.title);</script>';
+?>
+<?php }?>
BIN  phpforhacks/links.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/parameters.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/php-rendered.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/phperrorlog.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/print_r-demo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/smashingmagwithcurl.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  phpforhacks/variables-rendered.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 styles.css
@@ -0,0 +1,35 @@
+html,body{background:#999;color:#000;}
+#doc2,#doc{
+ font-family:calibri,sans-serif;background:#f8f8f8;
+ border:1em solid #f8f8f8;-moz-border-radius:5px;
+ -webkit-border-radius:5px;border-radius:5px;
+}
+#sb,.update{
+ background:#ccc;-moz-border-radius:5px;
+ -webkit-border-radius:5px;border-radius:5px;
+ font-size:90%;
+}
+.update{padding:5px;text-align:right;background:#369;color:#fff;}
+#hd .update a{color:#fff;font-weight:bold;}
+h1{color:#036;font-size:200%;margin:10px 0;}
+h2{color:#060;font-size:150%;margin:10px 0;}
+#hd a{color:#369;display:block;text-align:right;}
+#bd p,#bd li{font-size:110%;}
+.nav{margin:0;}
+.nav ul{margin:.5em 1em;}
+#bd .nav li{font-weight:bold;font-size:130%;list-style:none;margin:0;padding:0;}
+#hd .update a{display:inline;}
+.nav a:link{color:#369;}
+.nav a:visited{color:#036;}
+.nav a:hover{color:#000;background:#ff9;}
+.nav a:focus{color:#000;background:#ff9;}
+.nav a:active{color:#000;background:#ff9;}
+#bd .nav li li{font-weight:normal;padding:0 0 .5em 0;list-style:square;font-size:90%;}
+#ft{font-size:80%;color:#999;text-align:right;margin:4em 1em 1em 1em;}
+#ft a{color:#666;}
+#sb ul{margin:0 1em;}
+#sb a{color:#333;}
+#sb li ul{margin:.5em 1em;}
+#sb h2{color:#000;padding:0 10px;}
+#intro a{color:#369;}
+#intro {font-size:120%;}
114 yahoo-maps/index.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing Geoplanet information on a Yahoo map</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <script type="text/javascript" src="http://yui.yahooapis.com/combo?3.2.0pr1/build/yui/yui-min.js"></script>
+ <style type="text/css" media="screen">
+ #map{width:100%;height:400px;}
+ form{margin:0;padding:.5em;background:#666;color:#fff;}
+ /* fix to use maps with YUI CSS, I know it is terrible */
+ #map table,#map td,#map th{margin:0;padding:0;border:none;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing Geoplanet information on a Yahoo map</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <form id="f"><div>
+ <label for="location">Show map for</label>
+ <input type="text" id="location" name="location">
+ <input type="submit" value="go there">
+ </div></form>
+ <div id="map"></div>
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<!--
+ replace the appid with your own if you use this demo, please
+ you can get yours at http://developer.yahoo.com/maps/
+-->
+<script src="http://api.maps.yahoo.com/ajaxymap?v=3.8&appid=SckyCn7V34EmWovT9sK7Z2ivzd2NtNKOMzTWVFwViDtkNLvxNKbiLqqWN9nqtdg-'"></script>
+<script>
+YUI().use('yql','node',function(Y){
+ var container = Y.one('#map');
+ Y.one('#f').on('submit',function(e){
+ e.preventDefault();
+ findlocation(Y.one('#location').get('value'));
+ });
+ /*
+ Find a location with YQL and geo.places.
+ */
+ function findlocation(location){
+ new Y.YQL('select * from geo.places where text="'+location+'"',
+ function(r){
+ if(r.error){
+ container.set('innerHTML','<p class="error">'+
+ r.error.description+'</p>');
+ } else {
+ // send the information of the center and the bounding box to
+ // rendermap - without the bounding box the zoom level would
+ // be way off
+ var cur = r.query.results.place[0] ?
+ r.query.results.place[0] :
+ r.query.results.place;
+ if(cur){
+ rendermap(
+ location,'map',[
+ cur.centroid.latitude,
+ cur.centroid.longitude,
+ cur.boundingBox.northEast.latitude,
+ cur.boundingBox.northEast.longitude,
+ cur.boundingBox.southWest.latitude,
+ cur.boundingBox.southWest.longitude
+ ]
+ );
+ }
+ }
+ });
+ };
+ findlocation('San Francisco');
+ /*
+ Reusable function to use the Yahoo maps Ajax API.
+ checks if there is only a center point or also boundaries
+ */
+ function rendermap(title,elementid,points){
+ var x = points;
+ if(x[0]){
+ var map = new YMap(document.getElementById(elementid));
+ map.addTypeControl();
+ map.addZoomLong();
+ map.addPanControl();
+ map.disableKeyControls();
+ map.setMapType(YAHOO_MAP_HYB);
+ var points = [];
+ var point = new YGeoPoint(x[0],x[1]);
+ points.push(point);
+ var newMarker = new YMarker(point);
+ newMarker.addAutoExpand(title);
+ map.addOverlay(newMarker);
+ }
+ if(x[2] && x[3]){
+ point = new YGeoPoint(x[2],x[3]);
+ points.push(point);
+ }
+ if(x[4] && x[5]){
+ point = new YGeoPoint(x[4],x[5]);
+ points.push(point);
+ }
+ var zac = map.getBestZoomAndCenter(points);
+ var level = points.length > 1 ? zac.zoomLevel : zac.zoomLevel + 1;
+ map.drawZoomAndCenter(zac.YGeoPoint,level);
+ map.drawZoomAndCenter(points[0],level);
+ };
+});
+</script>
+</body>
+</html>
52 yql-flickr-photos-js/index.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing Flickr photos using YQL and flickr.photolist</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <style type="text/css">
+ #flickr ul,#flickrlocation ul{
+ margin:1em 0;padding:0;overflow:hidden;list-style:none;
+ }
+ #flickr ul li,#flickrlocation ul li{
+ float:left;padding:5px;background:#eee;
+ border:1px solid #999;margin-right:5px;
+ list-style:none;
+ }
+ ul li img{display:block;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing Flickr photos using YQL and <code>flickr.photolist</code></h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <h2>Photos of cats:</h2>
+ <div id="flickr"></div>
+ <h2>Photos of puppies:</h2>
+ <div id="flickrlocation"></div>
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<script>
+ function flickr(o){
+ document.getElementById('flickr').innerHTML = o.results;
+ }
+ function flickrpup(o){
+ document.getElementById('flickrlocation').innerHTML = o.results;
+ }
+</script>
+<!--
+ The following script source where copied from YQL
+ notice format=xml and callback=functionname to
+ trigger JSON-P-X output.
+-->
+<script src="http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photolist%20where%20text%3D%22cat%22%20and%20amount%3D5&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&output=xml&callback=flickr"></script>
+<script src="http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photolist%20where%20text%3D%22puppies%22%20and%20amount%3D5&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&output=xml&callback=flickrpup"></script>
+</body>
+</html>
61 yql-flickr-photos-yui/index.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing Flickr photos using YQL and YUI3</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <script type="text/javascript" src="http://yui.yahooapis.com/combo?3.2.0pr1/build/yui/yui-min.js"></script>
+ <style type="text/css">
+ #flickr{
+ margin:1em 0;padding:0;overflow:hidden;list-style:none;
+ }
+ #flickr li{
+ float:left;padding:5px;background:#eee;
+ border:1px solid #999;margin-right:5px;
+ list-style:none;
+ }
+ ul li img{display:block;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing Flickr photos using YQL and YUI3</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <h2>Photos of elephants:</h2>
+ <ul id="flickr"></ul>
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<script>
+ YUI().use('node','substitute','yql', function(Y){
+ var url='<li><a href="http://flickr.com/photos/{OWNER}/{ID}">'+
+ '<img src="http://static.flickr.com/{SERVER}/{ID}'+
+ '_{SECRET}_s.jpg"></a></li>';
+ var container = Y.one('#flickr');
+ new Y.YQL('select * from flickr.photos.search where text="elephant"',
+ function(r){
+ if(r.error){
+ container.set('innerHTML','<p class="error">'+
+ r.error.description+'</p>');
+ } else {
+ Y.each(r.query.results.photo,function(v){
+ var img = Y.substitute(url,{
+ ID: v.id,
+ OWNER: v.owner,
+ SERVER: v.server,
+ SECRET: v.secret
+ });
+ container.append(img);
+ });
+ }
+ });
+ });
+</script>
+</body>
+</html>
87 yql-form/index.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing a form to query YQL data with JavaScript</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing a form to query YQL data with JavaScript</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <form action="http://search.yahoo.com/search">
+ <div>
+ <label for="p">Search:</label>
+ <input type="text" id="p" name="p"></input>
+ <input type="submit" value="make it so"></input>
+ </div>
+ </form>
+ <!--
+ notice the progressive enhancement - when there is no JS, we just
+ send the user to the Yahoo search result page - that's why I chose
+ p as the name of the search box.
+ -->
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<script>
+ function query(term){
+ var query = 'select * from search.web where query="'+
+ encodeURIComponent(term)+'"';
+
+ // start the URL by defining the API endpoint and encoding the query
+ var apiendpoint = 'http://query.yahooapis.com/v1/public/yql?q=';
+ var url = apiendpoint + encodeURIComponent(query);
+
+ // diagnostics - remove if you don't need them
+ url += '&diagnostics=true';
+
+ // format (json or xml)
+ url += '&format=json';
+
+ // callback function (when format is json this triggers JSON-P-X output)
+ url += '&callback=incoming';
+
+ // environment. this gives you access to the community tables
+ url += '&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
+
+ var s = document.createElement('script');
+ s.setAttribute('src',url);
+ document.getElementsByTagName('head')[0].appendChild(s);
+ }
+ function incoming(o){
+ if(o.query && o.query.results && o.query.results.result){
+ var res = o.query.results.result,
+ out = '<ol>',
+ i = 0,
+ cur = '';
+ for(i=0,j=res.length;i<j;i++){
+ cur = res[i];
+ out += '<li><h3><a href="'+cur.clickurl+'">'+cur.title+'</a></h3>'+
+ '<p>'+cur.abstract+' ('+cur.dispurl+')</p></li>';
+ }
+ out += '</ol>';
+ output.innerHTML = out;
+ } else {
+ output.innerHTML = '<p class="error">Could not retrieve data...</p>';
+ }
+ };
+ var output = document.createElement('div');
+ output.setAttribute('id','yqldata');
+ document.getElementById('bd').appendChild(output);
+
+ var f = document.getElementsByTagName('form')[0];
+ f.onsubmit = function(){
+ output.innerHTML = 'Loading&hellip;';
+ query(document.getElementById('p').value);
+ return false;
+ };
+</script>
+</body>
+</html>
88 yql-form/index.php
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing a form to query YQL data with JavaScript</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <style>
+ pre{overflow:auto;padding:1em;background:#eee;border:1px solid #999;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing a form to query YQL data with JavaScript</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <?php
+ // check if the form was sent off and filter out insecure
+ // content before displaying the search term
+ if(isset($_GET['p'])){
+ $term = filter_input(INPUT_GET,'p',FILTER_SANITIZE_SPECIAL_CHARS);
+ }
+ ?>
+ <form action="index.php">
+ <div>
+ <label for="p">Search:</label>
+ <input type="text" id="p" name="p"
+ value="<?php echo $term;?>"></input>
+ <input type="submit" value="make it so"></input>
+ </div>
+ </form>
+ <?php
+ if(isset($_GET['p'])){
+ // filter the search term for insecure URL content
+ $search = filter_input(INPUT_GET,'p',FILTER_SANITIZE_ENCODED);
+
+ // Your YQL query
+ $query = 'select * from search.web where query="'.$search.'"';
+
+ // start the URL by defining the API endpoint and encoding the query
+ $apiendpoint = 'http://query.yahooapis.com/v1/public/yql?q=';
+ $url = $apiendpoint . urlencode($query);
+
+ // diagnostics - remove if you don't need them
+ $url .= '&diagnostics=true';
+
+ // format (json or xml)
+ $url .= '&format=json';
+
+ // environment. this gives you access to the community tables
+ $url .= '&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
+
+ // initiate curl request
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $results = curl_exec($ch);
+
+ $data = json_decode($results);
+ if($data->query->results){
+ echo '<ol>';
+ foreach($data->query->results->result as $r){
+ echo '<li><h3><a href="'.$r->clickurl.'">'.$r->title.'</a></h3>'.
+ '<p>'.$r->abstract.' ('.$r->dispurl.')</p></li>';
+ }
+ echo '</ol>';
+ } else {
+ echo '<h2>Debugging information</h2>';
+ echo '<h3>URL</h3>';
+ echo '<p><a href="'.$url.'">'.$url.'</a></p>';
+ echo '<h3>Raw data</h3><pre>';
+ echo $results;
+ echo '</pre>';
+ echo '<h3>Decoded data</h3><pre>';
+ print_r(json_decode($results));
+ echo '</pre>';
+ }
+ }
+ ?>
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+</body>
+</html>
138 yql-geo-library/index.html
@@ -0,0 +1,138 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4+01//EN" "http://www+w3+org/TR/html4/strict+dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Using Geo information with YQLGeo</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" type="text/css" href="../styles.css">
+<style type="text/css" media="screen">
+ pre{border:1px solid #999;background:#eee;padding:.5em;clear:both;margin:1em 0;}
+ button{float:right;margin:.5em;}
+</style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+
+ <div id="hd" role="banner">
+ <h1>Using Geo information with YQLGeo</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <p>As an aid for the Georgia Tech Hack 2010 and as a follow-up <a href="http://www.slideshare.net/cheilmann/introduction-to-geo-hacking-with-amongst-others-yahoo-technology-3388374">to my talk about geolocation</a> here is a simple JavaScript library that answers most of your geo questions. It wraps the following services in a simple interface:</p>
+ <ul>
+ <li><a href="http://developer.yahoo.com/geo/placemaker">Yahoo Placemaker</a></li>
+ <li><a href="http://developer.yahoo.com/geo/geoplanet/">Yahoo GeoPlanet</a></li>
+ <li><a href="http://jsonip.appspot.com">jsonip.appspot.com</a></li>
+ <li><a href="http://iplocationtools.com/ip_location_api.php">IP location tools</a></li>
+ <li><a href="http://dev.w3.org/geo/api/spec-source.html">W3C Geo location</a></li>
+ <li><a href="http://www.flickr.com/services/api/flickr.places.findByLatLon.html">Flickr.places.findByLatLon</a></li>
+ </ul>
+ <h2>Usage</h2>
+ <p>To use the geo library, simply include it in your document. There is one simple method to use which is:</p>
+<pre><code>yqlgeo.get(<em>what</em>,<em>callback</em>)</code></pre>
+ <dl>
+ <dt><em>what</em></dt>
+ <dd>is the thing you want to analyse - this could be the URL to a web document, a text, an IP, a pair of latitude and longitude information or "visitor" to detect the geographic location of the current visitor.</dd>
+ <dt><em>callback</em></dt>
+ <dd>is the callback method that will be called when there was a succesful retrieval of information. The data comes back as an object - if there was an error retrieving the information the data will be wrapped in an <code>error</code> property.</dd>
+ </dl>
+
+ <p>Check out the different use cases of the library below:</p>
+
+ <h2>Getting the geographical location from a text</h2>
+ <p>You can send an arbitrary text to the <code>get()</code> method to find the geographical information in it:</p>
+
+<pre><code>yqlgeo.get('paris,fr',function(o){
+ alert(o.place.name+' ('+
+ o.place.centroid.latitude+','+
+ o.place.centroid.longitude+
+ ')');
+})</code></pre>
+<button onclick="yqlgeo.get('paris,fr',function(o){alert(o.place.name+' ('+o.place.centroid.latitude+','+o.place.centroid.longitude+')');})">Try this out</button>
+
+ <h2>Getting the location information from lat/lon</h2>
+
+ <p>You can get all kind of data from a latitude and longitude pair. You can either send them in as two parameters or as an array:</p>
+
+<pre><code>yqlgeo.get(33.748,-84.393,function(o){
+ alert(o.place.name + ',' + o.place.country.content);
+})</code></pre>
+<button onclick="yqlgeo.get(33.748,-84.393,function(o){alert(o.place.name + ',' + o.place.country.content);})">Try this out</button>
+
+<pre><code>yqlgeo.get([33.748,-84.393],function(o){
+ alert(o.place.name + ',' + o.place.country.content);
+})</code></pre>
+<button onclick="yqlgeo.get([33.748,-84.393],function(o){alert(o.place.name + ',' + o.place.country.content);})">Try this out</button>
+
+<h2>Get all the geo locations from a certain URL</h2>
+
+<p>You can scrape a certain document at a URL for geographical locations:</p>
+
+<pre><code>yqlgeo.get('http://www.wait-till-i.com/talks-and-conference-participation/',function(o){
+ if(o.place){
+ var out = '';
+ var all = o.place.length;
+ for(var i=0;i&lt;all;i++){
+ out+=o.place[i].name+'\n';
+ };
+ alert(out);
+ }
+});</code></pre>
+<button onclick="yqlgeo.get('http://www.wait-till-i.com/talks-and-conference-participation/',function(o){if(o.place){var out='';var all=o.place.length;for(var i=0;i<all;i++){out+=o.place[i].name+'\n'};alert(out)}}); ">Try this out</button>
+
+<h2>Get the place from an IP number</h2>
+
+<pre><code>yqlgeo.get('217.12.14.240',function(o){
+ alert(o.place.name + ',' + o.place.country.content +
+ ' (' + o.place.centroid.latitude + ',' +
+ o.place.centroid.longitude + ')'
+ );
+});
+</code></pre>
+<button onclick="yqlgeo.get('217.12.14.240',function(o){alert(o.place.name + ',' +o.place.country.content + ' ('+o.place.centroid.latitude+','+o.place.centroid.longitude+')')});">Try this out</button>
+
+<h2>Find the user (using the W3C geolocation API and IP as a fallback)</h2>
+
+<pre><code>yqlgeo.get('visitor',function(o){
+ alert(o.place.name + ',' + o.place.country.content +
+ ' (' + o.place.centroid.latitude + ',' +
+ o.place.centroid.longitude + ')'
+ );
+});
+</code></pre>
+<button onclick="yqlgeo.get('visitor',function(o){alert(o.place.name + ',' +o.place.country.content + ' ('+o.place.centroid.latitude+','+o.place.centroid.longitude+')')});">Try this out</button>
+
+<h2>Download the library</h2>
+
+<p>You can get the library directly <a href="yqlgeo.js">from here by saving this link</a> or by <a href="http://github.com/codepo8/YQL-Geo-Library">getting the source code from GitHub</a>.</p>
+
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+
+</div>
+
+<script src="yqlgeo.js"></script>
+
+</body>
+</html>
+
+place.centroid.longitude+')')});">Try this out</button>
+
+<h2>Download the library</h2>
+
+<p>You can get the library directly <a href="yqlgeo.js">from here by saving this link</a> or by <a href="http://github.com/codepo8/YQL-Geo-Library">getting the source code from GitHub</a>.</p>
+
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Written by <a href="http://wait-till-i.com">Chris Heilmann</a> using <a href="http://developer.yahoo.com/yql">YQL</a>.</p>
+ </div>
+
+</div>
+
+<script src="yqlgeo.js"></script>
+
+</body>
+</html>
+
136 yql-geo-library/yqlgeo.js
@@ -0,0 +1,136 @@
+/*
+ YQL Geo library by Christian Heilmann
+ Homepage: http://isithackday.com/geo/yql-geo-library
+ Copyright (c)2010 Christian Heilmann
+ Code licensed under the BSD License:
+ http://wait-till-i.com/license.txt
+*/
+var yqlgeo = function(){
+ var callback;
+ function get(){
+ var args = arguments;
+ for(var i=0;i<args.length;i++){
+ if(typeof args[i] === 'function'){
+ callback = args[i];
+ }
+ }
+ if(args[0] === 'visitor'){getVisitor();}
+ if(typeof args[0] === 'string' && args[0] != 'visitor'){
+ if(args[0]){
+ if(/^http:\/\/.*/.test(args[0])){
+ getFromURL(args[0]);
+ } else if(/^[\d+\.?]+$/.test(args[0])){
+ getFromIP(args[0]);
+ } else {
+ getFromText(args[0]);
+ }
+ }
+ }
+ var lat = args[0];
+ var lon = args[1];
+ if(typeof lat.join !== undefined && args[0][1]){
+ lat = args[0][0];
+ lon = args[0][1];
+ };
+ if(isFinite(lat) && isFinite(lon)){
+ if(lat > -90 && lat < 90 &&
+ lon > -180 && lon < 180){
+ getFromLatLon(lat,lon);
+ }
+ }
+ }
+ function getVisitor(){
+ if(navigator.geolocation){
+ navigator.geolocation.getCurrentPosition(
+ function(position){
+ getFromLatLon(position.coords.latitude,
+ position.coords.longitude);
+ },
+ function(error){
+ retrieveip();
+ }
+ );
+ } else{
+ retrieveip();
+ }
+ };
+
+ function getFromIP(ip){
+ var yql = 'select * from geo.places where woeid in ('+
+ 'select place.woeid from flickr.places where (lat,lon) in('+
+ 'select Latitude,Longitude from ip.location'+
+ ' where ip="'+ip+'"))';
+ load(yql,'yqlgeo.retrieved');
+ };
+
+ function retrieveip(){
+ jsonp('http://jsonip.appspot.com/?callback=yqlgeo.ipin');
+ };
+
+ function ipin(o){
+ getFromIP(o.ip);
+ };
+
+ function getFromLatLon(lat,lon){
+ var yql = 'select * from geo.places where woeid in ('+
+ 'select place.woeid from flickr.places where lat='+
+ lat + ' and lon=' + lon + ')';
+ load(yql,'yqlgeo.retrieved');
+ };
+
+ function getFromURL(url){
+ var yql = 'select * from geo.places where woeid in ('+
+ 'select match.place.woeId from geo.placemaker where '+
+ 'documentURL="' + url + '" and '+
+ 'documentType="text/html" and appid="")';
+ load(yql,'yqlgeo.retrieved');
+ }
+
+ function getFromText(text){
+ var yql = 'select * from geo.places where woeid in ('+
+ 'select match.place.woeId from geo.placemaker where'+
+ ' documentContent = "' + text + '" and '+
+ 'documentType="text/plain" and appid = "")';
+ load(yql,'yqlgeo.retrieved');
+ };
+
+ function jsonp(src){
+ if(document.getElementById('yqlgeodata')){
+ var old = document.getElementById('yqlgeodata');
+ old.parentNode.removeChild(old);
+ }
+ var head = document.getElementsByTagName('head')[0];
+ var s = document.createElement('script');
+ s.setAttribute('id','yqlgeodata');
+ s.setAttribute('src',src);
+ head.appendChild(s);
+ };
+
+ function load(yql,cb){
+ if(document.getElementById('yqlgeodata')){
+ var old = document.getElementById('yqlgeodata');
+ old.parentNode.removeChild(old);
+ }
+ var src = 'http://query.yahooapis.com/v1/public/yql?q='+
+ encodeURIComponent(yql) + '&format=json&callback=' + cb + '&'+
+ 'env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
+ var head = document.getElementsByTagName('head')[0];
+ var s = document.createElement('script');
+ s.setAttribute('id','yqlgeodata');
+ s.setAttribute('src',src);
+ head.appendChild(s);
+ };
+
+ function retrieved(o){
+ if(o.query.results){
+ callback(o.query.results);
+ } else {
+ callback({error:o.query});
+ }
+ };
+ return {
+ get:get,
+ retrieved:retrieved,
+ ipin:ipin
+ };
+}();
28 yql-open-table-with-js/count-tags.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <sampleQuery>select * from count where url="http://www.korea-dpr.com/" and tag="strong"</sampleQuery>
+ <author>Christian Heilmann</author>
+ <documentationURL>http://isithackday.com/hackday-toolbox/yql-open-table-with-js</documentationURL>
+ <description>Counts to amount of times a certain tag is in an HTML document.</description>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <inputs>
+ <key id='url' type='xs:string' paramType='variable' required="true" />
+ <key id='tag' type='xs:string' paramType='variable' required="true" />
+ </inputs>
+ <execute><![CDATA[
+ var data = y.rest(url).get().response;
+ var match = new RegExp('<'+tag+'[>|\s]');
+ var count = data.split(match);
+ var number = parseInt(count.length-1);
+ response.object = <counted>
+ <url>{url}</url>
+ <tag>{tag}</tag>
+ <count>{number}</count>
+ </counted>;
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
102 yql-open-table-with-js/index.php
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of using JavaScript in a YQL open table</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+ <script type="text/javascript" src="http://yui.yahooapis.com/combo?3.2.0pr1/build/yui/yui-min.js"></script>
+ <style type="text/css">
+ form{margin:1em 0;padding:.5em;background:#666;color:#fff;}
+ label{padding-right:1em;}
+ input{margin-right:1em;}
+ #result{margin:1em 0;background:#090;padding:1em;font-weight:bold;}
+ .hidden{position:absolute;left:-9999px;}
+ #result.loading{background:#ccc;}
+ #bd a{color:#369;}
+ pre{overflow:auto;padding:1em;margin:1em 0;background:#eee;border:1px solid #999;}
+ </style>
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of using JavaScript in a YQL open table</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ <p>Using server-side JavaScript in a YQL open table you can shift JavaScript logic to the server side. In this example I wanted to write a script that loads an HTML document and counts the amount of times a certain tag is used. With pure JavaScript this can't be done because of cross-domain loading issues. This is why I wrote the following <a href="http://isithackday.com/hackday-toolbox/yql-open-table-with-js/count-tags.xml">XML document</a> and put it on my server:</p>
+<pre><code><?php
+$xml=file_get_contents('count-tags.xml');
+echo htmlspecialchars($xml);
+?></code></pre>
+<p>The <code>y.rest()</code> command loads external data for me on the server and then allows me to manipulate it in JavaScript. In this case, I get the content and split it at the tag I want to count. Then I return an object which is all the data as plain XML (as YQL supports E4X).</p>
+<p>In YQL, you can apply this table with the use command:</p>
+<pre><code>use "http://isithackday.com/hackday-toolbox/yql-open-table-with-js/count-tags.xml" as count;
+select * from count where url="http://www.korea-dpr.com/" and tag="strong"</code></pre>
+
+<p>The results would be:</p>
+
+<pre><code><?php
+$xml=file_get_contents('results.xml');
+echo htmlspecialchars($xml);
+?></code></pre>
+
+<p>See the source of this page to check how to use this in YUI3. Find out more about <a href="http://developer.yahoo.com/yql/guide/yql-execute-chapter.html">server-side JavaScript in YQL here</a>.</p>
+
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<script>
+YUI().use('node','yql', function(Y){
+
+ // add all the HTML we need for the functionality to #bd
+ Y.one('#bd').prepend(''+
+ '<h2>Count the tags in a certain document</h2>'+
+ '<form>'+
+ '<label for="url">URL:</label>'+
+ '<input type="text" id="url" value="http://www.korea-dpr.com/">'+
+ '<label for="tag">Tag:</label>'+
+ '<input type="text" id="tag" value="strong">'+
+ '<input type="submit" value="count them!">'+
+ '</form><div id="result" class="hidden"></div>'+
+ '');
+
+ // define the output container
+ var container = Y.one('#result');
+
+ // apply the event handling to the form, overriding the submit
+ Y.one('form').on('submit',function(e){
+ e.preventDefault();
+
+ // get the values in the form and check that they were sent
+ var url = Y.one('#url').get('value');
+ var tag = Y.one('#tag').get('value');
+ if(url !== '' && tag !== ''){
+ // show the loading message
+ container.removeClass('hidden').set('innerHTML','Loading&hellip;').
+ addClass('loading');
+ // call the YQL function
+ get(url,tag);
+ }
+ })
+ function get(url,tag){
+ new Y.YQL('use "http://isithackday.com/hackday-toolbox/yql-open-table-with-js/count-tags.xml" as count;select * from count where url="'+url+'" and tag="'+tag+'"',
+ function(r){
+ container.removeClass('loading');
+ if(r.error){
+ container.set('innerHTML','<p class="error">'+
+ r.error.description+'</p>');
+ } else {
+ var res = r.query.results.counted;
+ container.set('innerHTML','The tag ' + res.tag+
+ ' is used ' + res.count + ' times '+
+ ' in the document at ' + res.url);
+ }
+ });
+ }
+});
+</script>
+</body>
+</html>
19 yql-open-table-with-js/results.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2010-07-29T11:58:03Z" yahoo:lang="en-US">
+ <diagnostics>
+ <publiclyCallable>true</publiclyCallable>
+ <url execution-time="3" proxy="DEFAULT"><![CDATA[http://isithackday.com/hackday-toolbox/yql-open-table-with-js/count-tags.xml]]></url>
+ <url execution-time="244" proxy="DEFAULT"><![CDATA[http://www.korea-dpr.com/]]></url>
+ <javascript execution-time="306" instructions-used="3095" table-name="count"></javascript>
+ <user-time>313</user-time>
+ <service-time>247</service-time>
+ <build-version>8771</build-version>
+ </diagnostics>
+ <results>
+ <counted>
+ <url>http://www.korea-dpr.com/</url>
+ <tag>strong</tag>
+ <count>904</count>
+ </counted>
+ </results>
+</query>
69 yql-with-javascript/index.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Demo of showing YQL data with JavaScript</title>
+ <link rel="stylesheet" type="text/css" href="../yui.css">
+ <link rel="stylesheet" href="../styles.css" type="text/css">
+</head>
+<body class="yui-skin-sam">
+<div id="doc" class="yui-t7">
+ <div id="hd" role="banner">
+ <h1>Demo of showing YQL data with JavaScript</h1>
+ <p><a href="../index.html">Back to index</a></p>
+ </div>
+ <div id="bd" role="main">
+ </div>
+ <div id="ft" role="contentinfo">
+ <p>Part of the Hackday Toolbox</p>
+ </div>
+</div>
+<script>
+ var query = 'select * from search.web where query="cows"';
+
+ // start the URL by defining the API endpoint and encoding the query
+ var apiendpoint = 'http://query.yahooapis.com/v1/public/yql?q=';
+ var url = apiendpoint + encodeURIComponent(query);
+
+ // diagnostics - remove if you don't need them
+ url += '&diagnostics=true';
+
+ // format (json or xml)
+ url += '&format=json';
+
+ // callback function (when format is json this triggers JSON-P-X output)
+ url += '&callback=incoming';
+
+ // environment. this gives you access to the community tables
+ url += '&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
+
+ var s = document.createElement('script');
+ s.setAttribute('src',url);
+ document.getElementsByTagName('head')[0].appendChild(s);
+
+ var output =