<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Weird rocketry &#187; php</title>
	<atom:link href="http://webapp.org.ua/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>https://webapp.org.ua</link>
	<description>Flights to outer code</description>
	<lastBuildDate>Sat, 16 Jul 2016 11:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Running php 5.2 fpm on ARM processor</title>
		<link>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/</link>
		<comments>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/#comments</comments>
		<pubDate>Sun, 20 Mar 2016 20:06:57 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[armhf]]></category>
		<category><![CDATA[fpm]]></category>
		<category><![CDATA[legacy]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scaleway]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=439</guid>
		<description><![CDATA[Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p>Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot of linux distros support ARM architecture. There is even <a href="https://www.scaleway.com/">dedicated ARM cloud hosting</a>.</p>
<p>In this post we&#8217;re going to fix the inability to run PHP in the FPM(Fast Process Manager) mode which is an absolute requirement if you want to run production websites.</p>
</div>
<p><span id="more-439"></span></p>
<div class="markdown-content">
<h2>Compiling from sources</h2>
<p>Since there is no old php releases in modern linux distros we&#8217;re obviously going to compile everything from scratch. For our purposes we&#8217;ll use <code>ubuntu 15.04</code>, let&#8217;s download php sources from PHP museum:</p>
<pre><code class="bash" title="">$ mkdir -p /mnt/build/ &amp;&amp; cd /mnt/build/
$ wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
$ apt-get install -y build-essential nano wget curl libbz2-dev libncurses5-dev autoconf libxml2-dev

</code></pre>
<h2>PHP-FPM patch</h2>
<p>For historical reasons, Fast Process Manager(FPM) for 5.2.X branch exists only in the <a href="http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz">form of patch</a>. Let&#8217;s download this patch and apply it the most recent 5.2 version:</p>
<pre><code class="bash" title="">$ cd php-5.2.17/
$ wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz &amp;&amp; gzip -d php-5.2.17-fpm-0.5.14.diff.gz
$ patch -p1 &lt; php-5.2.17-fpm-0.5.14.diff
 patching file configure
Hunk #7 succeeded at 110645 (offset 1324 lines).
Hunk #8 succeeded at 118930 (offset 1324 lines).
Hunk #9 succeeded at 119634 (offset 1324 lines).
Hunk #10 succeeded at 119689 (offset 1324 lines).
patching file configure.in
patching file libevent/ChangeLog
patching file libevent/Makefile.am
patching file libevent/Makefile.in
patching file libevent/README
patching file libevent/aclocal.m4

</code></pre>
<p>After this operation <code>--enable-fpm</code> option becomes available in <code>./configure</code> script:</p>
<pre><code class="bash" title="">$ ./configure --help | grep "fpm"
  --enable-fpm              FastCGI: If this is enabled, the fastcgi support
  --with-fpm-conf=PATH        Set the path for php-fpm configuration file [PREFIX/etc/php-fpm.conf]
  --with-fpm-log=PATH         Set the path for php-fpm log file [PREFIX/logs/php-fpm.log]
  --with-fpm-pid=PATH         Set the path for php-fpm pid file [PREFIX/logs/php-fpm.pid]

</code></pre>
<p>Let&#8217;s try to compile php with FPM support:</p>
<pre><code class="bash" title="">$ ./configure --prefix=/opt/php52 --enable-fastcgi --enable-fpm

loading cache ./config.cache
checking for Cygwin environment... no
checking for mingw32 environment... no
checking for egrep... grep -E
checking for a sed that does not truncate output... /bin/sed
checking host system type... armv7l-unknown-linux-gnueabi
checking target system type... armv7l-unknown-linux-gnueabi
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... yes
....

Thank you for using PHP.

</code></pre>
<p>So far, everything is looking fine. Let&#8217;s try to build it by running <code>make</code> using 4 ARM cores to speedup process:</p>
<pre><code class="bash" title="">$ make -j4

/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/php_date.c -o ext/date/php_date.lo
/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/lib/astro.c -o ext/date/lib/astro.lo

..........

/mnt/build/php-5.2.17/ext/dom/node.c: In function ‘dom_canonicalization’:
/mnt/build/php-5.2.17/ext/dom/node.c:1953:21: error: dereferencing pointer to incomplete type ‘xmlBuf {aka struct _xmlBuf}’
    ret = buf-&gt;buffer-&gt;use;
                     ^
Makefile:553: recipe for target 'ext/dom/node.lo' failed
make: *** [ext/dom/node.lo] Error 1

</code></pre>
<h2>libxml2 patching</h2>
<p>And boom! We&#8217;re stuck with the first error: <code>dereferencing pointer to incomplete type xmlBuf {aka struct _xmlBuf}</code>. After googling around, the problem seems to be related to <code>libxml2</code> incompatibility and is <a href="https://code.google.com/archive/p/php52-backports/issues/16">well documented</a>. Let&#8217;s fix that error by applying yet another patch:</p>
<pre><code class="bash" title="">$ wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/libxml29_compat.patch
$ patch -p1 &lt; libxml29_compat.patch
patching file ext/dom/node.c
Hunk #1 succeeded at 1950 (offset 55 lines).
patching file ext/dom/documenttype.c
Hunk #1 succeeded at 215 (offset 10 lines).
patching file ext/simplexml/simplexml.c
Hunk #1 succeeded at 1343 (offset -74 lines).

</code></pre>
<p>And run <code>make</code> once again:</p>
<pre><code class="bash" title="">$ make -j4

......

In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
Makefile:433: recipe for target 'sapi/cgi/fpm/fpm_worker_pool.lo' failed
make: *** [sapi/cgi/fpm/fpm_worker_pool.lo] Error 1
make: *** Waiting for unfinished jobs....
Makefile:431: recipe for target 'sapi/cgi/fpm/fpm_children.lo' failed
make: *** [sapi/cgi/fpm/fpm_children.lo] Error 1

</code></pre>
<p>Well, this is embarrassing. As we can see from compiler logs, the FPM author suggests us to write a patch and send it to him because current CPU type is not supported. Obviously, the first thing I did was to try google yet another patch to solve this problem, but unfortunately, there is no one &#8212; people moved on to newer PHP versions and no one cared enough to write a fix.</p>
<p>Therefore, we&#8217;re going to write our own patch. Let&#8217;s take a look at <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2</code></p>
<pre><code class="cpp" title="">

  /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
  /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#include &lt;stdint.h&gt;
#include &lt;sched .h&gt;

#if ( __i386__ || __i386 )

typedef int32_t                     atomic_int_t;
typedef uint32_t                    atomic_uint_t;
typedef volatile atomic_uint_t      atomic_t;

static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
{
        __asm__ volatile ( "lock;" "xaddl %0, %1;" :
                "+r" (add) : "m" (*value) : "memory");

        return add;
}

static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
{
        unsigned char res;

        __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
                "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");

    return res;
}

#elif ( __amd64__ || __amd64 )

// definitions of the same functions for AMD64

#else

#error unsupported processor. please write a patch and send it to me

#endif

</code></pre>
<h2>Atomic types</h2>
<p>Looks like we need to define those 2 functions for ARM platform. But how do we do it without proper knowledge of <code>C</code> and specifics of <code>armhf</code> architecture? Luckily, we may steal some code from newer PHP versions, which do work in FPM mode on ARM platform. Go to <code>https://github.com/php/php-src/blob/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h</code> and take a look at source code:</p>
<pre><code class="cpp" title="">

    /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
    /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#if HAVE_INTTYPES_H
# include &lt;inttypes .h&gt;
#else
# include &lt;stdint .h&gt;
#endif
#include &lt;sched .h&gt;

#ifdef HAVE_BUILTIN_ATOMIC

/**
 * all the cases below (as provided by upstream) define:
 * word as atomic_int_t, and
 * unsigned word as atomic_uint_t
 * and only use volatile atomic_uint_t as atomic_t
 */

typedef volatile unsigned long atomic_t;
#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)

#elif ( __i386__ || __i386 )

///  a lot of platform-speicific definitions of above mentioned functions

#if (__GNUC__) &amp;&amp; (__GNUC__ &lt; 4 || (__GNUC__ == 4 &amp;&amp; __GNUC_MINOR__ &lt; 2))

#elif ( __arm__ || __arm ) /* W-Mark Kubacki */

///  other code we're not interested in

</code></pre>
<p>Although, it does contain the mention of ARM, the code defined for this case won&#8217;t be executed, since this is not our case:</p>
<pre><code class=" bash" title="">$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.2.1-22ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-multilib --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)

</code></pre>
<p>What we&#8217;re going to do is leveraging built-in atomic types, which are controlled by <code>HAVE_BUILTIN_ATOMIC</code> flag. But first, let&#8217;s do a drop-in replacement of <code>fpm_atomic.h</code> from 5.3 branch:</p>
<pre><code class="" title="">$ cd /mnt/build/php-5.2.17/sapi/cgi/fpm
$ rm fpm_atomic.h &amp;&amp; wget "https://github.com/php/php-src/raw/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h"

</code></pre>
<p>Another <code>magic</code> step is in fact, fix configure system to be able to enable above mentioned flag. Open <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/acinclude.m4</code>  and add at the top:</p>
<pre><code class="" title="">AC_DEFUN([AC_FPM_BUILTIN_ATOMIC],
[
  AC_MSG_CHECKING([if gcc supports __sync_bool_compare_and_swap])
  AC_TRY_LINK(,
  [
    int variable = 1;
    return (__sync_bool_compare_and_swap(&amp;variable, 1, 2)
           &amp;&amp; __sync_add_and_fetch(&amp;variable, 1)) ? 1 : 0;
  ],
  [
    AC_MSG_RESULT([yes])
    AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.])
  ],
  [
    AC_MSG_RESULT([no])
  ])
])

</code></pre>
<p>After this is done, everything should compile just fine.</p>
<h2>TL;DR</h2>
<p>For those lazy folks who don&#8217;t want all the investigation details here&#8217;s an updated patch which I prepared:<br />
<code>https://github.com/bananos/dockerized/blob/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff</code></p>
<p>In order to use it, just download vanilla php-5.2.17 sources and apply the patch:</p>
<pre><code class="bash" title="">mkdir -p /tmp/build
cd /tmp/build &amp;&amp; wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
cd /tmp/build &amp;&amp; wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff
cd /tmp/build &amp;&amp; patch -p1 -d php-5.2.17/ &lt; /tmp/build/php-5.2.17-fpm-arm-0.5.14.diff

</code></pre>
<p>If you&#8217;re familiar with <a href="https://www.docker.com/">Docker</a> you may might also check precompiled and flattened <a href="https://github.com/bananos/dockerized/tree/master/armbuild-php52">PHP-5.2.17 ARMHF image</a><br />
with some most popular <code>PECL</code> packages pre-built.</p>
<p>Happy running your old legacy PHP code!</p>
<h2>Sources</h2>
<p>http://php-fpm.org/</p>
<p>https://github.com/bananos/dockerized/tree/master/armbuild-php52/</p>
<p>https://github.com/php/php-src/</p>
<p>https://code.google.com/archive/p/php52-backports/issues/16</p>
<p>http://saravananlinux.blogspot.com/2014/01/libxml-error-while-compiling-dual-php.html</p>
</div>
<p></sched></sched></stdint></inttypes></sched></p>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python vs. PHP duck typing</title>
		<link>https://webapp.org.ua/dev/python-vs-php-duck-typing/</link>
		<comments>https://webapp.org.ua/dev/python-vs-php-duck-typing/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 12:44:38 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[duck typing]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[typecast]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=128</guid>
		<description><![CDATA[Having previous experience in writing PHP code could potentially lead you to hours of debugging in Python. Consider the following simple example in PHP: PHP $s = "0"; $my = (bool) $s; var_dump($s); var_dump($my) And the output would be: string(1) "0" bool(false) Which is pretty expectable behavior in PHP, since it first casts string to [...]]]></description>
			<content:encoded><![CDATA[<p>Having previous experience in writing PHP code could potentially lead you to hours of debugging in Python.<br />
Consider the following simple example in PHP:</p>
<h2>PHP</h2>
<pre><code class="php">
$s = "0";
$my = (bool) $s;

var_dump($s);
var_dump($my)
</code>
</pre>
<p><span id="more-128"></span></p>
<p>And the output would be:</p>
<pre><code class="bash">
string(1) "0"
bool(<strong>false</strong>)
</code></pre>
<p>Which is pretty expectable behavior in PHP, since it first casts string to int, and than to boolean.</p>
<p>Consider the same example in Python:</p>
<h2>Python</h2>
<pre><code class="python">
s = "0"
my = bool(s)
print type(s), s
print type(my), my
</code>
</pre>
<p>And the output would be:</p>
<pre><code class="bash">

&lt;type 'str'&gt; 0
&lt;type 'bool'&gt; <strong>True</strong>

</code></pre>
<p>We&#8217;re not going to debate here wether this is good or bad, but you should be aware such things before they&#8217;ll steal hours of your time</p>
<p>To achieve the same behavior as in PHP, you&#8217;ll need to add explicit integer typecast:</p>
<pre><code class="python">
s = "0"
my = bool(int(s))
print type(s), s
print type(my), my
</code>
</pre>
<p>And the output would be:</p>
<pre><code class="bash">

&lt;type 'str'&gt; 0
&lt;type 'bool'&gt; <strong>False</strong>

</code></pre>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/python-vs-php-duck-typing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make use of Google Spreadsheets in your php scripts</title>
		<link>https://webapp.org.ua/dev/make-use-of-google-spreadsheets-in-your-php-scripts/</link>
		<comments>https://webapp.org.ua/dev/make-use-of-google-spreadsheets-in-your-php-scripts/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 16:59:29 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[Google spreadsheets]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=33</guid>
		<description><![CDATA[Ever wanted to integrate Google Spreadsheets with your application? This post describes a simple way of how you can do it using simple php script. Step 1. Create sample google spreadsheet with random data Here is how it might look like: Step 2. Publish it on the web &#38; obtain a secret key for your [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to integrate <a href="http://www.google.com/google-d-s/spreadsheets/">Google Spreadsheets</a> with your application?  This  post describes a simple way of how you can do it using simple php script.</p>
<h3>Step 1. Create sample google spreadsheet with random data</h3>
<p>Here is how it might look like:<br />
<a href="http://webapp.org.ua/wp-content/uploads/2011/04/gspreadsheet_sample.png"><img class="aligncenter size-full wp-image-49" title="Sampe Google spreadsheet" src="http://webapp.org.ua/wp-content/uploads/2011/04/gspreadsheet_sample.png" alt="" width="514" height="294" /></a></p>
<p><span id="more-33"></span></p>
<h3>Step 2. Publish it on the web &amp; obtain a secret key for your spreadsheet</h3>
<p>Click on &#8220;Share&#8221; button at top right section, and make sure that your spreadsheet will be available to anyone, i.e. &#8220;Public on the web &#8211; Anyone on the Internet can find and edit&#8221;</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2011/04/sharing_settings.png"><img class="aligncenter size-full wp-image-51" title="Google spreadsheets Sharing settings" src="http://webapp.org.ua/wp-content/uploads/2011/04/sharing_settings.png" alt="" width="545" height="226" /></a></p>
<p>See that URL?  Copy-paste it &amp; extract &#8220;key&#8221; from there, this will be required for programmatic access to your spreadsheet.</p>
<pre><code class="bash">

https://spreadsheets.google.com/ccc?key=0Am9NwGgzBIuBdDhSQ3FKMjRDZjAyYlZscUhmNUdKQnc&#038;hl=en

</code></pre>
<p>Mine access key is  <strong>0Am9NwGgzBIuBdDhSQ3FKMjRDZjAyYlZscUhmNUdKQnc </strong></p>
<h3>Step 3. Retrieve JSONP data from Google API</h3>
<p>By using special key from above you can download your data from following URL:</p>
<pre><code class="bash">

https://spreadsheets.google.com/feeds/cells/{$your_key}/1/public/basic?alt=json-in-script&#038;callback=_

</code></pre>
<p>Google API does not support pure JSON, so in order to parse it using standard tools you need to strip extra JSONP overhead from the response.<br />
Here a simple php code which downloads data &amp; parses it using <code>json_decode</code></p>
<pre><code class="php">
   /**
     * Download &amp; parse Google spreadsheet content
     *
     * @param unknown_type $link
     */
    function download_sheet($sp_key) {

        // construct Google spreadsheet URL:
        $url = "https://spreadsheets.google.com/feeds/cells/{$sp_key}/1/public/basic?alt=json-in-script&amp;callback=_";

        // UA
        $userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9";
        $curl = curl_init();
        // set URL
        curl_setopt($curl, CURLOPT_URL, $url);

        // setting curl options
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// return page to the variable
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // return into a variable
        curl_setopt($curl, CURLOPT_TIMEOUT, 30000); // times out after 4s
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curl, CURLOPT_USERAGENT, $userAgent);

        // grab URL and pass it to the variable
        $str = curl_exec($curl);
        curl_close($curl);

        // extract pure JSON from response
        $str  = substr($str, 2, strlen($str) - 4);
        $data = json_decode($str, true);

        // https://spreadsheets.google.com/feeds/cells/0Am9NwGgzBIuBdDhSQ3FKMjRDZjAyYlZscUhmNUdKQnc/1/public/basic/R1C2
        $id_marker = "https://spreadsheets.google.com/feeds/cells/{$sp_key}/1/public/basic/";
        $entries   = $data["feed"]["entry"];

        $res = array();
        foreach($entries as $entry) {
           $content = $entry["content"];
           $ind = str_replace($id_marker."R", "", $entry["id"]['$t']);
           $ii  = explode("C", $ind);
           $res[$ii[0]-1][$ii[1]-1] = $entry["content"]['$t'];
        }

        return $res;
    }

$SP_KEY = "0Am9NwGgzBIuBdDhSQ3FKMjRDZjAyYlZscUhmNUdKQnc";
$data = download_sheet($SP_KEY);

print_r($data);
</code></pre>
<p>Here is how output should look like:</p>
<pre><code class="bash">
Array
(
    [0] =&gt; Array
        (
            [0] =&gt; header1
            [1] =&gt; header2
            [2] =&gt; header3
        )

    [1] =&gt; Array
        (
            [0] =&gt; value1
            [1] =&gt; test1
            [2] =&gt; result1
            [3] =&gt; yetty1
        )

    [2] =&gt; Array
        (
            [0] =&gt; value2
            [1] =&gt; test2
            [2] =&gt; result2
        )

    [3] =&gt; Array
        (
            [0] =&gt; value3
            [1] =&gt; test3
            [2] =&gt; result3
        )

)
</code>
</pre>
<p>Of course, this is not an ideal solution:</p>
<ul>
<li> There is <a href="http://en.wikipedia.org/wiki/Security_through_obscurity">security through obscurity</a>, by giving someone a key you can&#8217;t deny access to document in future</li>
<li> Huge amount of data can&#8217;t be downloaded using this approach</li>
</ul>
<p>One of possible applications could be publishing changelogs for your product:</p>
<ul>
<li> Product manager maintains changelog in Google spreadsheet</li>
<li> An automation script pulls data from there &amp; publishes it to your application build</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/make-use-of-google-spreadsheets-in-your-php-scripts/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
