<?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>BLARGH!! for the people &#187; php</title>
	<atom:link href="http://blargh.tommymontgomery.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blargh.tommymontgomery.com</link>
	<description>It&#039;s time to bring forth the rhythm and the rhyme</description>
	<lastBuildDate>Fri, 09 Jul 2010 04:03:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP is Dead</title>
		<link>http://blargh.tommymontgomery.com/2010/07/php-is-dead/</link>
		<comments>http://blargh.tommymontgomery.com/2010/07/php-is-dead/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 04:03:13 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[rants]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=528</guid>
		<description><![CDATA[PHP is dead. Probably.
Allow me to preface this with some context. I ]]></description>
			<content:encoded><![CDATA[<p>PHP is dead. Probably.</p>
<p>Allow me to preface this with some context. <span style="color: #FF99FF">I <3 PHP</span>. It&#8217;s probably my favorite language for a variety of reasons, but the number one reason being I&#8217;m pretty expert at it. But I&#8217;m not above recognizing that the majority of PHP programmers are generally idiot script kiddies, and don&#8217;t know how to write code that is not terrible. In that way, all PHP programmers get a bad name, because, like in all other aspects of life, the morons far outnumber us geniuses. It&#8217;s our cross to bear.</p>
<p>Anyway, PHP is dead. Probably. Here&#8217;s why.</p>
<h2>PHP is Stagnating</h2>
<p>PHP 4 was released in <a href="http://www.php.net/archive/2000.php">May 2000</a>. PHP 5 was released in <a href="http://www.php.net/archive/2004.php#5.0.0">July 2004</a>. PHP 4.4 was released in July 2005. PHP 5.3 was released in <a href="http://www.php.net/archive/2009.php#id2009-06-30-1">June 2009</a>.</p>
<p>These dates are not enumerated here to poke fun at the slow release cycle of PHP (I&#8217;ll get to the core team later). Rather, it&#8217;s to illustrate a point. Here are some numbers that I pulled from some random data dump from <a href="http://www.nexen.net/chiffres_cles/phpversion/18829-toutes_les_stats_php_en_telechargement.php">some non-English site</a> that&#8217;s probably totally legit:</p>
<pre class="brush: sql;">
SELECT
	SUBSTRING(libelle, 1, 1) `php version`,
	SUM(nombre) `count`
FROM stats
WHERE libelle REGEXP '^[3-6](\\.\\d(\\.\\d)?)?$'
AND `date` LIKE '2008-10-06%'
GROUP BY SUBSTRING(libelle, 1, 1)
</pre>
<pre class="brush: plain;">
php version  count
-----------  -------
3               8096
4            2396211
5            1977067
6                 23
</pre>
<p>If it&#8217;s not abundantly clear to you unwashed masses what a &#8220;libelle&#8221; is, I&#8217;m pretty sure that&#8217;s &#8220;label&#8221; in some kind of European language. The dataset represents a census documenting what technologies people use to power their sites. Basically, this query is saying that in October of 2008, 2.3 million people used PHP 4 on their website and 1.9 million people used PHP 5 on their web site.</p>
<p>At that time, PHP 5 had been stable for 4 years, and PHP 4 had been stable for 8 years. Their usage in production is pretty much even. PHP 5 added a lot of features, such as, you know, <strong>object-oriented programming</strong>. And yet it takes ten years (and counting) for PEAR to get off their asses and convert their code to PHP 5.</p>
<p>For those who don&#8217;t know, PEAR is the PHP Extension Application Repository. It&#8217;s a packaging mechanism similar to <kbd>yum</kbd> or <kbd>apt-get</kbd>, as well as a repository for extensions to the PHP language written in PHP (as opposed to PECL, which are extensions to the PHP language written in C). It defined a coding standard, and generally did a lot of good for the PHP community, except that it&#8217;s written in freaking PHP 4, and the coding standard is embarrassingly terrible.</p>
<p>For example, they prefix member variables with underscores to indicate that it&#8217;s not public, since PHP 4 didn&#8217;t have the notion of member variable accessibility. PHP 4 also didn&#8217;t have the notion of static. You should see the way they implement the singleton pattern in PHP 4. It&#8217;s pretty hilarious.</p>
<p>PHP 4 also didn&#8217;t pass objects by reference. That means you manually had to insert ampersands <strong>everywhere</strong> to make sure that your objects wouldn&#8217;t be treated like a value type. And when I say everywhere, I mean everywhere. This is a very common occurrence in PHP 4:</p>
<pre class="brush: php;">
$myReferenceType =&amp; new AwesomeClass();
</pre>
<p>DEAR GOD YOU COULDN&#8217;T EVEN USE THE NEW KEYWORD WITHOUT EXPLICITLY DEFINING THE REFERENCE. WHY ARE PEOPLE STILL USING THIS VERSION OF PHP?</p>
<p>This is all a long way of saying that PHP 4 is hideously outdated, both in calendar time and technologically, and yet it remains very prominent. I die a little inside when I see someone using a host that&#8217;s rocking Apache 1.3 and PHP 4.3. It&#8217;s like seeing someone using the cgi-bin directory. Aren&#8217;t we past that yet? This isn&#8217;t 1997 anymore.</p>
<p>The same argument goes for PHP 5.3 as well. It added some sorely missing features, such as namespaces and true anonmyous functions, as well as a plethora of classes in the SPL, and yet no one is upgrading. It&#8217;s been a year, and people are still creating classes called <kbd><strong>Awesome_Controller_Abstract</strong></kbd> instead of using namespaces like a normal person. It&#8217;s heartbreaking.</p>
<p>This is what will cause PHP to always be slightly behind the curve technologically: its users&#8217; snail&#8217;s pace upgrade rate. Eventually, its one strength, the extremely low barrier to entry, will be nullified as other languages figure out how to be more accessible to the masses.</p>
<h2>The PHP Core team is separated from reality</h2>
<p>So, I imagine this is a problem for a lot of languages, and I&#8217;m definitely making unfair blanket statements, but I want to bring it up for one very specific reason. Try to read the next sentence without laughing.</p>
<p><code>In PHP, the namespace separator is the backslash.</code></p>
<p>You laughed, didn&#8217;t you?</p>
<p>Allow me to give a bit of backstory without citing any sources.</p>
<p>There was fairly raging debate among the core developers on what to use for the namespace separator in the months before PHP 5.3 was released. You see, it wasn&#8217;t as simple as you might think, because PHP isn&#8217;t primarily an object-oriented language.</p>
<p>The original solution was to use the <a href="http://php.net/manual/en/keyword.paamayim-nekudotayim.php">paamayim nekudotayim</a> (<strong>scope resolution operator</strong>, but the Hebrew version is way cooler) as a namespace separator. But oh no! That caused problems in situations like this:</p>
<pre class="brush: php;">
//bar.php
namespace Bar;

function foo() {}

//meanwhile, in baz.php
require_once bar.php;

class Bar {
  static function foo() {}
}

Bar::foo(); //which foo gets called? in the Bar namespace or in the Bar class?
</pre>
<p>So, the core team realized they had a problem. There were several solutions:</p>
<ol>
<li>Only apply namespaces to OO code (classes, interfaces, etc.)</li>
<li>Change the namespace separator character to something unambiguous</li>
</ol>
<p>Hindsight is always 20/20, but the second option there seems pretty retarded to me. It&#8217;s hard to find an unambiguous character in any language that has previous releases, because they&#8217;re all being used. What happens is you&#8217;ll end up choosing a character that&#8217;s hard to type (i.e. one you have to press shift for), or you&#8217;ll choose something that&#8217;s unambiguous technically (meaning not significantly used) but has ambiguous semantics (like, say, the escape character in every language besides T-SQL).</p>
<p>At one point, the core team actually created a matrix where each row was a different character (I think the triple colon was in the running at one point, which would probably be even more awesome when translated to Hebrew), and each column had funny stuff like &#8220;is hard to type&#8221; with a numeric value. The last column summed up the numeric values and the row with the highest number was the winner. It was all very democratic (THROUGH PURPLE MOUNTAIN MAJESTIES&#8230;).</p>
<p>The backslash won.</p>
<p>Well, kind of. Pretty much everybody who typed code for a living hated the backslash because, you know, IT&#8217;S THE BACKSLASH. Nobody wants to look at that.</p>
<p>But PHP is an open source project, which means most or all of them don&#8217;t get paid to work on it, so that means that the easiest solution will win. And in this case, the easiest solution was the one that was already done. One of the core developers got tired of the bickering and the matrices and the Hebrew and he spent a weekend implementing the backslash namespace separator and committed it to the branch. Then he wrote tests covering all possible cases, and created a patch against trunk.</p>
<p>He had everyone at &#8220;tests&#8221; and &#8220;patch&#8221;. And that&#8217;s how the backslash became the namespace separator for PHP.</p>
<p>This was all a a long way of saying their decision was made with their brains instead of their guts. If they used their guts, they would have realized that NOBODY GIVES A CRAP ABOUT NAMESPACES EXCEPT PEOPLE WHO DO OBJECT-ORIENTED CODE. Nobody cares if the 4000 lines of random functions in <kbd>stuff.php</kbd> is in a namespace. The only people who care about namespaces are those that experienced it in another language (like say, an object-oriented language) and would want to apply the same organizational structure to their PHP code. And those people are only writing classes and interfaces. </p>
<p>Ergo, they should have ignored the collision issues illustrated above, only applied namespaces to classes and interfaces, and rocked the <strong>PAAMAYIM NEKUDOTAYIM</strong> like it was going out of style. But since the PHP core team are experts in C, not PHP, they didn&#8217;t really realize this.</p>
<p>Instead, we are condemned to a life full of backslashes. I&#8217;ve already started a support group.</p>
<h2>PHP 6 is a disaster area</h2>
<p>I don&#8217;t have a lot to say about this, except that it seems like it&#8217;s an absolute disaster. The main thing going on in PHP 6 is unicode support. </p>
<p><code>yay.</code></p>
<p>I&#8217;m not totally sure why that&#8217;s so awesome, but it&#8217;s a lot of work, and it isn&#8217;t going well. Again I&#8217;m not going to cite any sources, but it&#8217;s been in the works for about two years to add unicode support to PHP, and I don&#8217;t think it&#8217;s very close to being done.</p>
<p>The problem seems to be that they can&#8217;t just add unicode support, because every extension would be incompatible. So they&#8217;re trying to retroactively add unicode support to everything at once, which is as terrible as it sounds. I could be making all this up, but it sounds similar to something I might have read once.</p>
<p>Basically, they&#8217;re attempting to add a feature that will be of minimal value, and it&#8217;s taking forever. Instead, they could be adding cool things, like some of these:</p>
<ul>
<li><a href="http://wiki.php.net/rfc/propertygetsetsyntax">C#-style properties</a></li>
<li><a href="http://wiki.php.net/rfc/autoboxing">Auto-boxing</a></li>
<li><a href="http://wiki.php.net/rfc/horizontalreuse">Traits</a></li>
<li><a href="http://wiki.php.net/rfc/enum">Enumerations</a></li>
<li><a href="http://wiki.php.net/rfc/fcallfcall">Function call chaining</a> (oh god yes)</li>
<li><a href="http://wiki.php.net/rfc/static-classes">Static classes</a></li>
</ul>
<h2>In Conclusion</h2>
<p>PHP is dying. Probably. I hope I&#8217;m wrong, because I think PHP is a very expressive, convenient language. It has, by far, the best function library of any language. It also has, by far, the best documentation of any language, as well as a giant, open community around it. For those reasons, I hope it doesn&#8217;t die. But I&#8217;ve seen little evidence that it&#8217;s not going to march straight to hell.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2010/07/php-is-dead/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to be an Awesome Open Source Developer</title>
		<link>http://blargh.tommymontgomery.com/2010/02/how-to-be-an-awesome-open-source-developer/</link>
		<comments>http://blargh.tommymontgomery.com/2010/02/how-to-be-an-awesome-open-source-developer/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 10:46:20 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=411</guid>
		<description><![CDATA[I&#8217;m a big fan of open source. Capitalism is awesome, but it inspires and encourages greed, so it&#8217;s nice to see somebody defying that system by working hard at something, and then giving it away for free.
Of course, you&#8217;re at the mercy of whatever kind of limping scrod they shove out their codehole, but hey, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of open source. Capitalism is awesome, but it inspires and encourages greed, so it&#8217;s nice to see somebody defying that system by working hard at something, and then giving it away for free.</p>
<p>Of course, you&#8217;re at the mercy of whatever kind of limping scrod they shove out their codehole, but hey, it&#8217;s free! </p>
<p><a href="http://dilbert.com/fast/2006-08-02/"><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2010/02/limpingscrod.gif" alt="limpingscrod" title="limpingscrod" width="560" height="174" class="aligncenter size-full wp-image-412" /></a></p>
<p>Quite often, their stuff sucks, or they don&#8217;t maintain it, or it doesn&#8217;t compile, or it doesn&#8217;t work, or it only works in certain environments, or whatever. But every so often, you find that one nugget of well-maintained and well-written rad that makes you love America! Or in this case, it makes you love the Netherlands.</p>
<p><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2010/02/netherlands.png" alt="netherlands" title="netherlands" width="342" height="252" class="aligncenter size-full wp-image-413" /></p>
<p>I was following up on <a href="/2009/08/transliteration-in-php/">on this post</a> and trying to compile the <a href="http://pecl.php.net/package/translit">PECL translit</a> extension on 64-bit Windows. Obviously, I was destined to fail. And fail I did. So then I emailed the author of the extension with a cry for help:</p>
<blockquote style="font-family: Consolas, monospace"><p>I was curious if the translit extension is available for Windows. I noticed there was no configuration file for it, so I attempted to hack together a config.w32 and build it but didn&#8217;t have much luck. Is it conceivable that this extension is buildable on Windows?</p>
<p>I&#8217;m trying to build it for PHP 5.3 on x64, which probably isn&#8217;t helping my chances&#8230;</p>
<p>Anyway, the documentation I found didn&#8217;t mention if it was even viable on PHP 5.3, so I could be barking up a dead tree. For the record, the error was pretty immediate and looked like this:</p>
<p>C:\code\php64\php-5.3.1\ext\translit\data\compact_underscores.c : fatal error C1083: Cannot open compiler generated file: &#8216;x64\Release_TS\ext\translit\data/compact_underscores.obj&#8217;: No such file or directory</p>
<p>Thanks,<br />
Tommy
</p></blockquote>
<p>I didn&#8217;t really expect anything back for a while. I know he&#8217;s a busy guy, and there hadn&#8217;t really been any updates to this extension for a couple years, but I figured I&#8217;d give it a shot. In 3.5 hours, I had a reply that said, basically, &#8220;I&#8217;m not sure if it works on Windows, but you can pull the latest from SVN to make it build. I just built it on 64-bit Windows but I haven&#8217;t tested them.&#8221; And then he <strong>freaking attached the compiled DLLs</strong>. Both thread-safe and non-thread-safe versions. Seriously. Here&#8217;s proof:</p>
<p><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2010/02/fromderick.png" alt="fromderick" title="fromderick" width="651" height="408" class="aligncenter size-full wp-image-421" /></p>
<p>That&#8217;s dedication to maintaining your project. Not only did he answer my question, but he went the extra mile of verifying that it was a solution himself. </p>
<p><a href="http://derickrethans.nl/">Derick Rethans</a>, you are rad. There needs to be more open source developers like you.</p>
<p><strong>PS:</strong> I checked out the latest version of translit from the SVN repository he specified and rebuilt, and it totally worked.</p>
<p><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2010/02/translit.png" alt="translit" title="translit" width="599" height="171" class="aligncenter size-full wp-image-419" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2010/02/how-to-be-an-awesome-open-source-developer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reddit in 61 minutes and 97 lines of PHP</title>
		<link>http://blargh.tommymontgomery.com/2010/02/reddit-in-61-minutes-and-97-lines-of-php/</link>
		<comments>http://blargh.tommymontgomery.com/2010/02/reddit-in-61-minutes-and-97-lines-of-php/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 11:04:29 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[rants]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=398</guid>
		<description><![CDATA[I read this article, about a guy who made a Reddit clone in 10 minutes in Clojure. He was inspired by this guy, who made a Reddit clone in Lisp in 20 minutes and a hundred lines.
I&#8217;m so sick of Lisp hackers. Functional programming is pretty awesome, but every single Lisp/Erlang/Haskell/Clojure/Emacs guy thinks Lisp is [...]]]></description>
			<content:encoded><![CDATA[<p>I read <a href="http://www.bestinclass.dk/index.php/2010/02/reddit-clone-in-10-minutes-and-91-lines-of-clojure/">this article</a>, about a guy who made a Reddit clone in 10 minutes in Clojure. He was inspired by <a href="http://homepage.mac.com/svc/LispMovies/index.html#2">this guy</a>, who made a Reddit clone in Lisp in 20 minutes and a hundred lines.</p>
<p>I&#8217;m so sick of Lisp hackers. Functional programming is pretty awesome, but every single Lisp/Erlang/Haskell/Clojure/Emacs guy thinks Lisp is the greatest thing since list processing (what?).</p>
<p>So I implemented Reddit in (properly formatted) PHP in 97 lines. Granted it took a bit longer, but I had to remember how to use the low-level <kbd>mysql_*</kbd> functions. Oh, and I used MySQL. I don&#8217;t know what the Lisp people used for data persistence. Some of the lines were taken up by CSS and JavaScript, and making things look nice(r).</p>
<div id="attachment_399" class="wp-caption aligncenter" style="width: 341px"><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2010/02/redditclone.png" alt="Reddit in 61 minutes of alone time with Notepad++" title="redditclone" width="331" height="261" class="size-full wp-image-399" /><p class="wp-caption-text">Reddit in 61 minutes of alone time with Notepad++</p></div>
<p><a href="http://tmont.com/experiments/reddit-php-lol/source.php">Source</a> | <a href="http://tmont.com/experiments/reddit-php-lol/">Playground</a></p>
<p>I hate Lisp people.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2010/02/reddit-in-61-minutes-and-97-lines-of-php/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>string.Format() in PHP</title>
		<link>http://blargh.tommymontgomery.com/2010/01/string-format-in-php/</link>
		<comments>http://blargh.tommymontgomery.com/2010/01/string-format-in-php/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 21:22:08 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[c#]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=377</guid>
		<description><![CDATA[.NET&#8217;s sprintf() equivalent has ordered parameters.

var s = string.Format(&#34;My name is {1}, {0}&#34;, &#34;Tommy&#34;, &#34;Montgomery&#34;);
//s = &#34;My name is Montgomery, Tommy&#34;

var s = string.Format(&#34;My name is {{{0}}}&#34;, &#34;Tommy&#34;);
//s = &#34;My name is {Tommy}&#34;

I needed that. Here it is, PHPified:

function format($format) {
	$args = func_get_args();
	$format = array_shift($args);

	preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
	$offset = 0;
	foreach ($matches[1] as $data) {
		$i = [...]]]></description>
			<content:encoded><![CDATA[<p>.NET&#8217;s <a href="http://php.net/sprintf"><kbd>sprintf()</kbd></a> <a href="http://msdn.microsoft.com/en-us/library/txafckwd.aspx">equivalent</a> has ordered parameters.</p>
<pre class="brush: csharp;">
var s = string.Format(&quot;My name is {1}, {0}&quot;, &quot;Tommy&quot;, &quot;Montgomery&quot;);
//s = &quot;My name is Montgomery, Tommy&quot;

var s = string.Format(&quot;My name is {{{0}}}&quot;, &quot;Tommy&quot;);
//s = &quot;My name is {Tommy}&quot;
</pre>
<p>I needed that. Here it is, PHPified:</p>
<pre class="brush: php;">
function format($format) {
	$args = func_get_args();
	$format = array_shift($args);

	preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
	$offset = 0;
	foreach ($matches[1] as $data) {
		$i = $data[0];
		$format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i));
		$offset += strlen(@$args[$i]) - 2 - strlen($i);
	}

	return $format;
}
</pre>
<p>There&#8217;s a lot going on in here that isn&#8217;t used very often in PHP. Here is a terse explanation of the not-so-obvious features:</p>
<ul>
<li>The <a href="http://php.net/manual/en/pcre.constants.php"><kbd>PREG_OFFSET_CAPTURE</kbd></a> constant tells the regex engine to capture the string index offset of each match.</li>
<li><kbd>(?=\{)</kbd> and <kbd>(?!\})</kbd> in the regular expression are <a href="http://www.regular-expressions.info/lookaround.html">positive and negative lookarounds</a>, respectively. The nice thing about that is they&#8217;re also zero-width matching, which means they won&#8217;t be returned as part of the match result. These are needed because to output a literal <kbd>{</kbd> in a C# string you precede it with another <kbd>{</kbd> (a little know fact about C#).</li>
<li><a href="http://php.net/manual/en/function.substr-replace.php"><kbd>substr_replace</kbd></a> is an infrequently used, extremely useful function, that replaces a substring within a string, expanding to the given width.</li>
<li>The <kbd>$offset</kbd> variable tracks the string length delta. Since we&#8217;re modifying the string, the offsets captured in the regex match becomes out of date.</li>
</ul>
<p>Mmmmm&#8230; smells like win.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2010/01/string-format-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun With Closures and Object Caches in PHP</title>
		<link>http://blargh.tommymontgomery.com/2009/12/fun-with-closures-and-object-caches-in-php/</link>
		<comments>http://blargh.tommymontgomery.com/2009/12/fun-with-closures-and-object-caches-in-php/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 10:58:33 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=334</guid>
		<description><![CDATA[Intro to Closures in PHP
PHP 5.3 introduced closures. It&#8217;s already been pointed out that the Closure class in PHP is not necessarily a closure. Lexical scope is optional in PHP&#8217;s implementation, which is a little goofy looking:

//lambda ftw
$lambda = function ($x) {
  echo 'I am an anonymous function ftw.' . &#34;\n&#34; . $x;
};

//closure lol
$closure [...]]]></description>
			<content:encoded><![CDATA[<h2>Intro to Closures in PHP</h2>
<p>PHP 5.3 introduced closures. It&#8217;s <a href="http://bugs.php.net/bug.php?id=48742">already been pointed out</a> that the <a href="http://php.net/manual/en/reserved.classes.php#reserved.classes.closure"><kbd>Closure</kbd> class</a> in PHP is not necessarily a closure. Lexical scope is optional in PHP&#8217;s implementation, which is a little goofy looking:</p>
<pre class="brush: php;">
//lambda ftw
$lambda = function ($x) {
  echo 'I am an anonymous function ftw.' . &quot;\n&quot; . $x;
};

//closure lol
$closure = function ($x) use ($lambda) {
  $lambda('Actually, I am an anonymous function lexically bound in a closure ' . $x '.');
}

$closure('lol');

//I am an anonymous function ftw.
//Actually, I am an anonymous function lexically bound in a closure lol.
</pre>
<p>It&#8217;s all very academic.</p>
<h2>Object-Oriented Closures</h2>
<p>Creating a closure inside a class is easy enough&#8230; until the desideratum is a closure around <kbd>$this</kbd>. It&#8217;s time for some JavaScript-style naming conventions!</p>
<pre class="brush: php;">
class Foo {
  public function bar() {
    $closure = function() use ($this) {}; //syntax error: Cannot use $this as lexical variable
  }
}
</pre>
<p>This yields a syntax error in the form of <kbd>Cannot use $this as lexical variable</kbd>. That is truly misfortunate. Fortunately, we can reach into our bag of JavaScript tricks and do something <a href="http://www.dustindiaz.com/scoping-anonymous-functions/">ridiculous</a>:</p>
<pre class="brush: php;">
class Foo {
  public function bar() {
    $that = $this; //lulz
    $closure = function() use ($that) {
      $that-&gt;baz = &quot;I was set by &quot; . __FUNCTION__;
    }

    $closure();
    var_dump($this);
  }
}

$x = new Foo();
$x-&gt;bar();

/*
object(Foo)#1 (1) {
  [&quot;baz&quot;]=&gt;
  string(22) &quot;I was set by {closure}&quot;
}
*/
</pre>
<p>True to PHP&#8217;s nature, it&#8217;s all magic and voodoo. (ab)Use with discretion.</p>
<h2>A real world example</h2>
<p>So, I was sitting there the other day, <a href="http://websvn.tommymontgomery.com/listing.php?repname=phpmvc&#038;path=%2Fsrc%2Ftrunk%2Fsrc%2FPhpMvc%2F#path_src_trunk_src_PhpMvc_">porting ASP.NET MVC to PHP</a>, and I ran across this class:</p>
<pre class="brush: csharp;">
internal sealed class ControllerDescriptorCache : ReaderWriterCache&lt;Type, ControllerDescriptor&gt; {

    public ControllerDescriptorCache() {
    }

    public ControllerDescriptor GetDescriptor(Type controllerType) {
        return FetchOrCreateItem(controllerType, () =&gt; new ReflectedControllerDescriptor(controllerType));
    }

}
</pre>
<p>Now, the significant part of this class actually takes part in the base class, <kbd>ReaderWriterCache</kbd>, which provides a thread-safe object cache. Basically. In this context, that&#8217;s really all it&#8217;s doing. The <kbd>FetchOrCreateItem()</kbd> method either retrieves an already-existing item in the cache, or creates it, stores it in the cache keyed to the specified type, and then returns it. Simple enough.</p>
<p>Now, thread safety is not a concern in PHP. Well, it&#8217;s of grave concern if you&#8217;re writing an extension, or working on PHP itself, but if you&#8217;re writing PHP code, you need not concern yourself with thread safety. The point is that this <kbd>ReaderWriterCache</kbd> is thoroughly useless in the context of PHP, so I needed to decide what to do with it. It turns out that I actually need it, but I already have a <a href="http://websvn.tommymontgomery.com/filedetails.php?repname=phpmvc&#038;path=%2Fsrc%2Ftrunk%2Fsrc%2FPhpMvc%2FFramework%2FCollection.php">Collection class</a> that does typesafe object storage, which is really all I need. The way it works is that it takes a <kbd>Closure</kbd> as a constructor parameter, and uses that for validation: if it returns true, the object can be stored in the collection.</p>
<pre class="brush: php;">
//a collection of stdClasses. how useful.
$stdClassCollection = new \PhpMvc\Framework\Collection(function($value) {
  return $value instanceof stdClass;
});
</pre>
<p>Now, how to implement a generic object cache? Well, <kbd>Collection</kbd> is already generic (as generic as a dynamically typed language gets, anyway), so really we just need an implementation of <kbd>FetchOrCreateItem()</kbd> and we&#8217;re home free. But, since we&#8217;re awesome, and this post is all about closures, we want to use closures. Also, if you dig a little deeper into the MVC source, you&#8217;ll see the significance of the lambda expression in the second argument given to <kbd>FetchOrCreateItem()</kbd> (hint: look at line 15):</p>
<pre class="brush: csharp;">
protected TValue FetchOrCreateItem(TKey key, Func&lt;TValue&gt; creator) {
    // first, see if the item already exists in the cache
    _rwLock.AcquireReaderLock(Timeout.Infinite);
    try {
        TValue existingEntry;
        if (_cache.TryGetValue(key, out existingEntry)) {
            return existingEntry;
        }
    }
    finally {
        _rwLock.ReleaseReaderLock();
    }

    // insert the new item into the cache
    TValue newEntry = creator(); //OH HAI! I CAN HAZ LAMDUH!
    _rwLock.AcquireWriterLock(Timeout.Infinite);
    try {
        TValue existingEntry;
        if (_cache.TryGetValue(key, out existingEntry)) {
            // another thread already inserted an item, so use that one
            return existingEntry;
        }

        _cache[key] = newEntry;
        return newEntry;
    }
    finally {
        _rwLock.ReleaseWriterLock();
    }
}
</pre>
<p>The reason for a lambda expression instead of just passing in the object instance is because it&#8217;s a cache: we don&#8217;t want a bunch of object instances floating around, so we&#8217;re waiting until the last possible moment to create it. Notice that first we check if the object exists in the cache before creating it; you can&#8217;t have that foreknowledge (well, you could, but lambda expressions are fun, and I&#8217;m assuming that&#8217;s the reason why this method is needlessly complicated).</p>
<p>So, let&#8217;s port it to PHP.</p>
<pre class="brush: php;">
class ObjectCache extends Collection {

	private $creator;

	public function __construct(Closure $creator, Closure $validator = null) {
		parent::__construct($validator);
		$this-&gt;creator = $creator;
	}

	public function offsetGet($key) {
		if (!$this-&gt;offsetExists($key)) {
			$this[$key] = call_user_func($this-&gt;creator, $key);
		}

		return parent::offsetGet($key);
	}

}
</pre>
<p>There&#8217;s some serious magic going on here. I love it. First, recall that <kbd>Collection</kbd> implements the <a href="http://php.net/manual/en/class.arrayaccess.php"><kbd>ArrayAccess</kbd></a> interface, which means we can use array-style indexers on it. What happens behind the scenes when you do that is that it calls the underlying <kbd>offset[Get|Set|Unset|Exists]()</kbd> methods. So we override <kbd>offsetGet()</kbd> and either return the object if it already exists in the cache, or create it, store it, and then return it. Let&#8217;s see it in action:</p>
<pre class="brush: php;">
$cache = new ObjectCache(
  function ($key) {
    return new \ReflectionClass($key); //when adding an object to the cache, this function creates that object
  },
  function ($value) {
    return $value instanceof \ReflectionClass; //only allow instances of ReflectionClass in our collection
  }
);
$stdclass = $cache['stdClass'];
var_dump($stdclass);
var_dump($stdclass === $cache['stdClass']);

/*
object(ReflectionClass)#4 (1) {
  [&quot;name&quot;]=&gt;
  string(8) &quot;stdClass&quot;
}
bool(true)
*/
</pre>
<p>That triple equals, to those of you who forgot, means the object instances are identical, i.e. they refer to the same space in memory. Mostly what it means is that our object cache works.</p>
<h2>Making the Object Cache Better</h2>
<p>So, we can still set stuff in our object cache, since I didn&#8217;t override <kbd>offsetSet()</kbd>. Doing something like this will totally bypass the caching mechanism:</p>
<pre class="brush: php;">
$cache['foo'] = new ReflectionClass('stdClass');
</pre>
<p>That&#8217;s not really very good. There are a couple ways to short circuit that:</p>
<ol>
<li>Abuse the hell out of <kbd>debug_backtrace()</kbd> and fish the calling scope out of the stack frame (awesome)</li>
<li>Make <kbd>offsetSet()</kbd> throw an exception every time it&#8217;s called, and set the data another way</li>
</ol>
<p>Well, it turns out that in my implementation #2 is not even possible, because the internal storage in <kbd>Collection</kbd> is a private variable not available to derived classes. What this means is that the only way to add an object to the collection is via <kbd>offsetSet()</kbd>. But there are ways around that, with a little refactoring. Since both #1 and #2 sound fun, let&#8217;s do both.</p>
<h3>#1: Stack Frame Rape</h3>
<pre class="brush: php;">
public function offsetSet($key, $value) {
	//this method is only allowed to be called from within an offsetGet() in this ObjectCache instance
	$fail = true;
	$stackFrame = debug_backtrace(true);
	foreach ($stackFrame as $frame) {
		if (isset($frame['object']) &amp;&amp; $frame['object'] === $this &amp;&amp; $frame['function'] === 'offsetGet') {
			//called from $this-&gt;offsetGet(), that's okay
			$fail = false;
			break;
		}
	}

	if ($fail) {
		if (count($stackFrame) &lt;= 1) {
			//called without scope
			$type = '{main}';
		} else {
			//the offending stack frame is the last one
			if (isset($frame['class'])) {
				//object scope
				$type = $frame['class'] . $frame['type'] . $frame['function'] . '()';
			} else if (substr($frame['function'], -9) === '{closure}') {
				$type = 'a closure';
			} else if (substr($frame['function'], -13) === '__lambda_func') {
				$type = 'an anonymous function';
			} else {
				$type = $frame['function'] . '()';
			}
		}

		throw new \LogicException(sprintf('You tried to set an object in the cache from %s, plz stop.', $type));
	}

	parent::offsetSet($key, $value);
}
</pre>
<p>I&#8217;ve never felt so dirty. This actually works, too.</p>
<pre class="brush: php;">
$cache = new ObjectCache(
  function ($key) {
    return new \ReflectionClass($key);
  },
  function ($value) {
    return $value instanceof \ReflectionClass;
  }
);
$stdclass = $cache['stdClass']; //ok
var_dump($stdclass);
var_dump($stdclass === $cache['stdClass']);

class Foo {
	function bar(ObjectCache $cache) {
		$cache['foo'] = new \ReflectionClass('ReflectionClass');
	}
}

$foo = new Foo();
$foo-&gt;bar($cache); //LogicException: You tried to set an object in the cache from PhpMvc\Descriptor\Foo-&gt;bar(), plz stop.

$cache['foo'] = new \ReflectionClass('ReflectionClass'); //LogicException: You tried to set an object in the cache from {main}, plz stop.

$lambda = function() use ($cache) {
	$cache['foo'] = new \ReflectionClass('ReflectionClass');
};

$lambda(); //LogicException: You tried to set an object in the cache from a closure, plz stop.

function func(ObjectCache $cache) {
	$cache['foo'] = new \ReflectionClass('ReflectionClass');
}

func($cache); //LogicException: You tried to set an object in the cache from PhpMvc\Descriptor\func(), plz stop.

$func = create_function('$cache', '$cache[\'foo\'] = new \ReflectionClass(\'ReflectionClass\');');
$func($cache); //LogicException: You tried to set an object in the cache from an anonymous function, plz stop.
</pre>
<p>Let&#8217;s just forget we ever saw that&#8230;</p>
<h3>#2: Override <kbd>offsetSet()</kbd></h3>
<p>Like I mentioned earlier, this will require a bit of refactoring, because <kbd>Collection</kbd> hides the internal data storage from derived classes.</p>
<pre class="brush: php;">
class Collection implements ArrayAccess, Countable, Iterator {

	private $validator;
	private $data;
	private $index;
	private $numericIndex;

	public function __construct(Closure $validator = null) {
		$this-&gt;validator = $validator ?: function($value) { return true; };
		$this-&gt;index = 0;
		$this-&gt;numericIndex = 0;
		$this-&gt;data = array();
	}

	//snip

	protected function valueIsValid($value) {
		return call_user_func($this-&gt;validator, $value);
	}

	public function offsetExists($key) {
		return array_key_exists($key, $this-&gt;data);
	}

	public function offsetGet($key) {
		if (!$this-&gt;offsetExists($key)) {
			throw new OutOfBoundsException('The key &quot;' . $key . '&quot; does not exist in the collection');
		}

		return $this-&gt;data[$key];
	}

	public function offsetSet($key, $value) {
		if (!$this-&gt;valueIsValid($value)) {
			throw new InvalidArgumentException('This collection does not allow values of type ' . (is_object($value) ? get_class($value) : gettype($value)));
		}

		//instead of $collection[] = $value, do $collection[null] = $value
		if ($key === null) {
			$key = $this-&gt;numericIndex++;
		}

		$this-&gt;data[$key] = $value;
	}

	public function offsetUnset($key) {
		unset($this-&gt;data[$key]);
	}

	//snip

}
</pre>
<p>What we can do is factor out the actual setting of the data into a protected function that <kbd>offsetSet()</kbd> and all derived classes can use.</p>
<pre class="brush: php;">
protected final function set($key, $value) {
	if (!$this-&gt;valueIsValid($value)) {
		throw new InvalidArgumentException('This collection does not allow values of type ' . (is_object($value) ? get_class($value) : gettype($value)));
	}

	//instead of $collection[] = $value, do $collection[null] = $value
	if ($key === null) {
		$key = $this-&gt;numericIndex++;
	}

	$this-&gt;data[$key] = $value;
}

public function offsetSet($key, $value) {
	$this-&gt;set($key, $value);
}
</pre>
<p>And then in <kbd>ObjectCache</kbd>, we just call <kbd>set()</kbd> from <kbd>offsetGet()</kbd>, and throw an exception if someone tries to call <kbd>offsetSet()</kbd>. While we&#8217;re at it, let&#8217;s make a <kbd>get()</kbd> method so we can avoid the <a href="http://en.wikipedia.org/wiki/Call_super">call super anti pattern</a> as much as possible. Now our get and set methods in <kbd>ObjectCache</kbd> are much cleaner:</p>
<pre class="brush: php;">
public function offsetGet($key) {
	if (!$this-&gt;offsetExists($key)) {
		$this-&gt;set($key, call_user_func($this-&gt;creator, $key));
	}

	return $this-&gt;get($key);
}

public function offsetSet($key, $value) {
	throw new LogicException('Cannot set objects in the object cache');
}
</pre>
<h2>In Conclusion</h2>
<p>Closures are fun. Learn to love them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/12/fun-with-closures-and-object-caches-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Arc Challenge: PHP and JavaScript</title>
		<link>http://blargh.tommymontgomery.com/2009/12/the-arc-challenge-php-and-javascript/</link>
		<comments>http://blargh.tommymontgomery.com/2009/12/the-arc-challenge-php-and-javascript/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 00:17:05 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=321</guid>
		<description><![CDATA[Take the Arc Challenge. For the lazy, here is the problem:
Write a program that causes the url said (e.g. http://localhost:port/said) to produce a page with an input field and a submit button. When the submit button is pressed, that should produce a second page with a single link saying &#8220;click here.&#8221; When that is clicked [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.paulgraham.com/arcchallenge.html">Take the Arc Challenge</a>. For the lazy, here is the problem:</p>
<blockquote><p>Write a program that causes the url said (e.g. http://localhost:port/said) to produce a page with an input field and a submit button. When the submit button is pressed, that should produce a second page with a single link saying &#8220;click here.&#8221; When that is clicked it should lead to a third page that says &#8220;you said: &#8230;&#8221; where &#8230; is whatever the user typed in the original input field. The third page must only show what the user actually typed. I.e. the value entered in the input field must not be passed in the url, or it would be possible to change the behavior of the final page by editing the url.</p>
</blockquote>
<p>I ignored the part about what the URL has to be, because that would just be annoying. The point of Arc is to write things in the most efficient way possible, and the whole language is built around helping you do that. The point of this problem is to illustrate that Arc does this very well.</p>
<p>In Arc, a solution looks like this:</p>
<pre class="brush: plain;">
(defop said req
  (aform [onlink &quot;click here&quot; (pr &quot;you said: &quot; (arg _ &quot;foo&quot;))]
    (input &quot;foo&quot;)
    (submit)))
</pre>
<p>In PHP:</p>
<pre class="brush: php;">
session_start();

if (isset($_SESSION['said'])) {
	echo 'You said: ' . htmlentities($_SESSION['said']); //prevent XSS lol
	unset($_SESSION['said']);
} else if (isset($_POST['said'])) {
	$_SESSION['said'] = $_POST['said'];
	echo '&lt;a href=&quot;&quot;&gt;Click here!&lt;/a&gt;';
} else {
	echo '&lt;form method=&quot;post&quot; action=&quot;&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;said&quot;/&gt;&lt;input type=&quot;submit&quot;/&gt;&lt;/form&gt;';
}
</pre>
<p>And in JavaScript:</p>
<pre class="brush: jscript;">
function getCookie(name) {
	var cookies = document.cookie.split(&quot;;&quot;);
	for (var i = 0, len = cookies.length, cookieParts; i &lt; len; i++) {
		cookieParts = cookies[i].trim().split(&quot;=&quot;);
		if (cookieParts[0] === name) {
			return cookieParts[1];
		}
	}

	return null;
}

var said = getCookie(&quot;said&quot;), page = parseInt(getCookie(&quot;page&quot;));
if (said === null) {
	var input = document.createElement(&quot;input&quot;);
	input.type = &quot;text&quot;;
	var button = document.createElement(&quot;button&quot;);
	button.appendChild(document.createTextNode(&quot;Submit&quot;));
	button.onclick = function() {
		document.cookie = &quot;said=&quot; + input.value;
		document.cookie = &quot;page=2&quot;;
		window.location.href = window.location.href;
	}

	document.body.appendChild(input);
	document.body.appendChild(button);
	document.cookie = &quot;page=1&quot;;
} else if (page === 2) {
	document.cookie = &quot;page=3&quot;;
	var link = document.createElement(&quot;a&quot;);
	link.href = &quot;&quot;;
	link.appendChild(document.createTextNode(&quot;Click here&quot;));
	document.body.appendChild(link);
} else {
	document.body.appendChild(document.createTextNode(&quot;You said: &quot; + said));
	var expires = new Date();
	expires.setDate(expires.getDate() - 100);
	expires = expires.toGMTString();
	document.cookie = &quot;said=;expires=&quot; + expires;
	document.cookie = &quot;page=1&quot;;
}
</pre>
<p>The cookie handling could probably be more compact, but whatever; the hideousness of that is far outstretched by the hideousness of <a href="http://blargh.tommymontgomery.com/2009/11/fluent-dom-manipulation-in-javascript/">the DOM</a>. Try each of them out here:</p>
<ul>
<li><a href="http://tmont.com/experiments/arc-challenge/arc.php">PHP</a></li>
<li><a href="http://tmont.com/experiments/arc-challenge/arc.html">JavaScript</a></li>
</ul>
<p>Arc seems like a cool language. Too bad it&#8217;s based on Lisp, which means it will never get any traction in the demographics that don&#8217;t wear suspenders.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/12/the-arc-challenge-php-and-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling PHP on Windows 64 bit with VC9</title>
		<link>http://blargh.tommymontgomery.com/2009/10/compiling-php-on-windows-64-bit-with-vc9/</link>
		<comments>http://blargh.tommymontgomery.com/2009/10/compiling-php-on-windows-64-bit-with-vc9/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 00:56:42 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=150</guid>
		<description><![CDATA[Update 2009-10-28: added additional information for compiling on Windows 7.
This seems to one of the most difficult things for someone to explain. Hopefully this will shed some light on the subject of PHP Windows compilation and help you out.
There don&#8217;t seem to be any &#8220;Compile PHP on Windows x64&#8243; guides, and even less than zero [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2009-10-28</strong>: added additional information for compiling on Windows 7.</p>
<p>This seems to one of the most difficult things for someone to explain. Hopefully this will shed some light on the subject of PHP Windows compilation and help you out.</p>
<p>There don&#8217;t seem to be any &#8220;Compile PHP on Windows x64&#8243; guides, and even less than zero for the VC9 compiler (VC9 means Visual Studio 2008). I pieced together what I could from other guides I found (all were either woefully incomplete, confusing, and for either 32-bit or older VC versions) and created this guide. Hopefully it helps. My environment looks like this:</p>
<ul>
<li><del>Windows Vista Home Premium 64-bit</del> <ins>Windows 7 Professional 64-bit</ins></li>
<li>Visual Studio 2008 Pro SP1</li>
</ul>
<p>Let&#8217;s begin.</p>
<h2>Preamble</h2>
<p>A word of warning. This is a guide to compiling PHP for development. If you&#8217;re looking for a production-ready PHP binary for Windows 64-bit, you&#8217;re barking up the wrong tree, in many different ways.</p>
<ol>
<li>This is mostly a guide for those of us who develop on Windows with Apache. You shouldn&#8217;t be running Apache on Windows in production anyway, so if that&#8217;s what you&#8217;re looking for, you need to reevaluate your programming skills. PHP itself provides x64 VC9 binaries, but they&#8217;re not linked against Apache.</li>
<li>I know almost nothing about C/C++. Compiling PHP requires no knowledge of C/C++. I only know enough to install what I need to make everything work.</li>
<li>If you all you want is a PHP 5.2 binary for Windows 64-bit, go <a href="http://fusionxlan.com/PHPx64.php">here</a> and go wild. If you want to compile PHP on Windows 32-bit, go <a href="http://blog.astrumfutura.com/archives/327-Compiling-PHP-for-Windows-Vista-using-Visual-C++-Express-2008-Seriously!.html">here</a>; it&#8217;s a good guide (it&#8217;s what got me started). If you&#8217;re looking for a Windows 64-bit PHP 5.3 binary download, get it from me <a href="http://tommymontgomery.com/php64">here</a>.</li>
</ol>
<p>If you&#8217;re looking to compile some futhermucking PHP on Windows 64-bit, read on.</p>
<h2>Let&#8217;s get retarded</h2>
<p>You need to download a bunch of crap. I hope you have a lot of disk space.</p>
<ul>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=FF6467E6-5BBA-4BF5-B562-9199BE864D29&amp;displaylang=en">Windows Vista SDK Update</a> (you only need this if you&#8217;re on Vista) </li>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&amp;displaylang=en">.NET Framework SDK</a> &#8211; A note about this: there are several newer versions of the SDK, and it probably won&#8217;t matter which one you use. I didn&#8217;t need this at all since VS2008 Pro installed the SDK for me (at least on Windows 7).</li>
<li><a href="http://www.microsoft.com/express/download/">Visual Studio 2008 C++</a> (I used the full version, but the express version should work, too)</li>
<li>Something that lets you mount an iso, like <a href="http://www.disk-tools.com/download/daemon">Daemon Tools Lite</a> (use <a href="http://www.slysoft.com/en/virtual-clonedrive.html">Virtual Clone Drive</a> if you&#8217;re on Windows 7)</li>
<li><a href="http://static.tommymontgomery.com/misc/php64/php64-deps.7z">Build dependencies</a></li>
<li><a href="http://www.php.net/downloads.php">PHP source code</a></li>
<li><a href="http://7-zip.org/">7-zip</a></li>
</ul>
<p>This will get you setup to compile PHP linked against Apache 2.2. This builds the CLI, CGI and apache2handler SAPIs (not ISAPI, if you want IIS, download it from PHP).</p>
<h3>Let&#8217;s do it!</h3>
<p>First (only if on Vista), download Daemon Tools Lite (or Virtual Clone Drive) and install it. You might have to reboot. Then download the Vista SDK update and right click on the Daemon Tools tray icon, and mount the SDK .iso. It should autoplay, so allow it and follow the installation instructions. This will take a while. If there&#8217;s a checkbox related to the installation of 64-bit stuff, make sure it&#8217;s checked. Like this:</p>
<p>Second, download Visual Studio 2008 and install it. Make sure to check 64-bit related stuff, like this:</p>
<p><img src="http://blargh.tommymontgomery.com/wp-content/uploads/2009/10/vs2008setup.png" alt="vs2008setup" title="vs2008setup" width="329" height="339" class="aligncenter size-full wp-image-204" /></p>
<p>Go to your start menu, and you should see something similar to this:<br />
<img class="aligncenter size-full wp-image-154" title="vstools" src="http://blargh.tommymontgomery.com/wp-content/uploads/2009/10/vstools1.png" alt="vstools" width="420" height="410" /></p>
<p>That&#8217;s the x64 compiler command prompt. It&#8217;s a <kbd>cmd</kbd> shortcut that sets up all the environment variables needed to compile a C/C++ library for the x64 architecture. It&#8217;s important. Yes, my user icon is the stock cat picture. What?</p>
<p>Thirdly, if you don&#8217;t see something related to the Windows SDK in your start menu, download the .NET SDK and install that. Always check any 64-bit related stuff.</p>
<p>That was the hard part. Since it&#8217;s Windows (Windows Vista, even), I suggest you reboot. Let&#8217;s not upset her now. You&#8217;ve gotten this far only by her grace.</p>
<p>Now, download and install 7-zip. It&#8217;s a free, open-source archiving tool. Stop using stupid crap like WinRar. You aren&#8217;t downloading torrents in 1998 anymore. Then download the PHP build dependencies I created just for you and extract it to a clever place, like <kbd>c:\php64</kbd>. Then download and extract the PHP source code (you can get the bz2, since 7-zip can handle that) to <kbd>c:\php64</kbd>. Your directory structure should look like this:</p>
<pre><code>- php64
-- php-5.x.x
-- deps
</code></pre>
<p>You are now ready to begin building stuff.</p>
<h2>Compiling</h2>
<p>Now it&#8217;s time to lift up your skirt and see if you got a pair.</p>
<p>First, a little explanation. The <kbd>deps</kbd> directory contains all the headers and libs that PHP needs to compile the different extensions (like <kbd>curl</kbd> for example). These came from <a href="http://pecl2.php.net/downloads/php-windows-builds/php-libs/VC9/x64/">PECL</a> except for the apache libs, which came from <a href="http://www.blackdot.be/?inc=apache/binaries">blackbot</a>. The stuff in the <kbd>bin</kbd> directory came from the binary tools provided by PHP <a href="http://pecl2.php.net/downloads/php-windows-builds/php-libs/">here</a>. As near as I can tell, the extensions need to be compiled with VC9. Apache was apparently compiled with VC8, which didn&#8217;t really seem to matter. I don&#8217;t know. The point is, all of these headers and libs work for what you are about to do, and that&#8217;s all that really matters. Right?</p>
<h3>Here we go</h3>
<p>Open up the x64 command prompt I alluded to earlier via the start menu, and <kbd>cd</kbd> to your <kbd>php64</kbd> directory. The environment variables are all set up except for the binary tools (bison, zip and the like), so we need to modify the path. Do this:<br />
<code>path = %PATH%;c:\php64\deps\bin<br />
echo %PATH%</code><br />
That should modify your path and then spit it out. Mine looks like this:<br />
<img class="aligncenter size-full wp-image-161" title="path" src="http://blargh.tommymontgomery.com/wp-content/uploads/2009/10/path.png" alt="path" width="904" height="176" /></p>
<p>Now we are ready to start the compilation process. I suggest you build the simplest possible version of PHP you can, and once you&#8217;ve gotten that to work, you can start enabling extensions. Or , if you&#8217;re man enough, you can skip right to <a href="#big-finish">the big finish</a> and try compiling everything at once. I&#8217;ll walk you through the easier way.</p>
<p><kbd>cd</kbd> into the <kbd>php-5.x.x</kbd> directory and type <kbd>buildconf</kbd>. This will (re)build the configuration file. Then run <kbd>cscript /nologo configure.js --help</kbd> This will show you a list of possible configuration switches.</p>
<h3>The first build</h3>
<p>We&#8217;re going to a very simple build that has most stuff disabled. Use this configure statement:<br />
<code>cscript /nologo configure.js --without-t1lib --without-xml --without-dom --without-simplexml --disable-xmlreader --disable-xmlwriter --without-iconv --disable-zlib --without-gd --disable-zip --disable-odbc --without-libxml</code></p>
<p>This won&#8217;t create a super useful PHP binary, but it&#8217;ll make sure that you have the ability to build PHP with no external dependencies. Type <kbd>nmake</kbd> to build. This will take about 5-10 minutes if there are no problems. If you&#8217;re watching it build, don&#8217;t be alarmed if it sits at <kbd>parse_date.c</kbd> for a minute or so: that&#8217;s normal. You&#8217;ll see a ridiculous amount of warnings, most of them about conversion issues. Disregard them.</p>
<p>When the build is done, <kbd>cd</kbd> to <kbd>x64\Release_TS</kbd> and type <kbd>php -v</kbd> to see your PHP version. Type <kbd>php -m</kbd> to see a list of all the modules we just compiled.<br />
<img class="aligncenter size-full wp-image-168" title="build1" src="http://blargh.tommymontgomery.com/wp-content/uploads/2009/10/build1.png" alt="build1" width="499" height="519" /></p>
<p>Congratulations! You just compiled PHP on 64-bit Windows. You are among an elite group.</p>
<h3>Extension Hell</h3>
<p>Now, it&#8217;s time to make this PHP binary useful. It&#8217;s time to compile in some extensions.</p>
<p>Most of these extensions are built statically, which means they&#8217;re compiled into PHP and cannot be enabled/disabled; in effect they are always enabled. A few of them (gd, curl) are compiled as shared, which is what you&#8217;re probably used to, where you have a<kbd> php_[extension name].dll</kbd> line in your <kbd>php.ini </kbd>that you uncomment/comment with reckless abandon.</p>
<p>Let&#8217;s start easy, by enabling some more core extensions, like <kbd>iconv</kbd> and the xml stuff. <kbd>cd</kbd> back to the <kbd>php-5.x.x</kbd> directory and use this configure statement:<br />
<code>cscript /nologo configure.js --without-t1lib --without-gd --disable-zip --disable-odbc</code></p>
<p>When you run that, you should see a pretty list of enabled extensions. That list should now have <kbd>xmlreader</kbd>, <kbd>xmlwriter</kbd>, <kbd>iconv</kbd>, <kbd>libxml</kbd>, <kbd>xml</kbd> and <kbd>dom</kbd> in it.</p>
<p>If the configure statement failed, you probably don&#8217;t have your libs set up correctly. They should be in a directory called &#8220;deps&#8221; that is a sibling to <kbd>php-5.x.x</kbd>. If they are, and it still didn&#8217;t work, then add this to the configure statement: <kbd>--with-php-build=c:\php64\deps</kbd>. That will force the PHP build system to look for libs in that directory (by default it looks in <kbd>..\deps</kbd>). You can troubleshoot configure errors by looking at the output. Most errors should be something like &#8220;Not found&#8221; for headers/libs.</p>
<p>Type <kbd>nmake</kbd> to build and wait for another 5-10 minutes. Verify that your extensions were built correctly by checking out the modules:<br />
<img class="aligncenter size-full wp-image-171" title="build2" src="http://blargh.tommymontgomery.com/wp-content/uploads/2009/10/build2.png" alt="build2" width="498" height="623" /></p>
<p>If you&#8217;ve made it this far, you&#8217;re pretty much home free. All that&#8217;s left is enabling the apache2handler and the other extensions you want. The <kbd>php64-deps.7z</kbd> I made contains the headers and libs for the extensions that were easily available (i.e. the ones that PHP provided). If you need something more, like memcached for example, you&#8217;ll have to either build it yourself or scour the internet in the hopes that somebody already built it for Windows x64 (unlikely).</p>
<h3><a name="big-finish"></a>The Big Finish</h3>
<p>Run this configure statement:<br />
<code>cscript /nologo configure.js --enable-apache2-2handler --with-curl --with-xsl --with-mcrypt --with-openssl --with-mysql --enable-sockets --enable-pdo --with-pdo-mysql --enable-soap --enable-mbstring --without-t1lib --with-pdo-odbc --with-bz2 --with-ldap --with-tidy --enable-exif --enable-mbregex --with-gettext --enable-shmop --enable-prefix=c:\lib\php --with-sqlite3 --with-xmlrpc --enable-zend-multibyte --with-mysqli</code></p>
<p>One note about the <kbd>--enable-prefix</kbd> switch: after building, you can run <kbd>nmake install</kbd> to install PHP to the directory you specify with this switch. Change the value to where you want PHP to be installed on your machine, or don&#8217;t run <kbd>nmake install</kbd> at all (it&#8217;s not required).</p>
<p>You&#8217;ll probably need to clean up the build output first. The easiest way to do this is to just delete everything in the <kbd>x64\Release_TS</kbd> directory. Now run <kbd>nmake</kbd>, wait another 5-10 minutes, and hope that everything worked.</p>
<h3>Installation</h3>
<p>A few of the extensions require some openssl binaries, namely <kbd>ssleay32.dll</kbd> and <kbd>libeay32.dll</kbd>. I&#8217;ve included these in the <kbd>deps</kbd> directory. You&#8217;ll need to copy them to wherever your <kbd>php.exe</kbd> binary is located. If you try to run PHP and Windows borks an error at you about PHP needing to close, then most likely it was looking for these dlls and didn&#8217;t find them. You&#8217;ll get that error if you try <kbd>nmake install</kbd>. It&#8217;s not serious, just copy those dlls and everything should be fine.</p>
<p>To enable <kbd>curl</kbd> and <kbd>gd</kbd> you&#8217;ll need to enable them in your <kbd>php.ini</kbd>&#8230; which means you need a <kbd>php.ini</kbd>. I&#8217;d just download one of the Windows zip packages from PHP and extract the <kbd>php.ini-recommended</kbd> or <kbd>php.ini-development</kbd> into your PHP binary&#8217;s directory. Make sure to change the <kbd>extension_dir</kbd> to the location of those dlls.</p>
<h2>That&#8217;s it</h2>
<p>And we&#8217;re done. Hopefully that all worked. Here are some common errors and how to troubleshoot them:</p>
<ul>
<li><strong>Unresolved externals</strong>: this means that the headers are referencing things that don&#8217;t exist. This means that you&#8217;re screwed, and you should try and find headers that don&#8217;t have this problem. Or, if you know C, you can try and fix it yourself.</li>
<li><strong>Can&#8217;t find file</strong>: this means one of your source files (probably for an extension) is in the wrong place. You shouldn&#8217;t have this problem if you&#8217;re using my build dependencies archive. Regardless, this one&#8217;s an easy fix: just find the file and put it in the right place.</li>
</ul>
<p>One last note, <a href="http://fusionxlan.com/PHPx64.php">Fusion X-Lan</a> has been providing pre-compiled Windows 64-bit binaries for a while, but it hasn&#8217;t been updated since PHP 5.2.5. The whole reason I wanted to compile PHP was so that I could run PHP 5.3 on my new 64-bit computer. Their binaries are much better than mine: they have all the extensions available, including the apache2 SAPI. Unfortunately, they&#8217;re old (almost two years now) and they also use the VC8 (or earlier) compiler. If you need PHP 5.2, use theirs. If you want to compile PHP 5.3 with VC9, use this guide, or just download the <a href="http://tommymontgomery.com/php64">binary packages I provide</a>.</p>
<p>I hope this was helpful. Leave a comment if you have any problems or find an issue with this guide.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/10/compiling-php-on-windows-64-bit-with-vc9/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Transliteration in PHP</title>
		<link>http://blargh.tommymontgomery.com/2009/08/transliteration-in-php/</link>
		<comments>http://blargh.tommymontgomery.com/2009/08/transliteration-in-php/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 19:07:00 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=111</guid>
		<description><![CDATA[This one time, I read this article about how Unicode is for foreigners, and everybody should learn English. It&#8217;s not quite as offensive as it sounds, but it&#8217;s pretty rude. It was awesome.
Anyway, at the end, he called for transliteration implementations in languages besides ones that suck (my words, not his); here of course I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>This one time, I read <a href="http://teddziuba.com/2009/07/this-is-america-take-your-unic.html">this article</a> about how Unicode is for foreigners, and everybody should learn English. It&#8217;s not <em>quite</em> as offensive as it sounds, but it&#8217;s pretty rude. It was awesome.</p>
<p>Anyway, at the end, he called for transliteration implementations in languages besides ones that suck (my words, not his); here of course I&#8217;m referring to Perl, Python and Java. Luckily, PHP is so blindingly awesome that it only requires a function call to do such things. No compiling extensions or importing libraries.</p>
<pre class="brush: php;">
$string = 'Möbius FTW because my name is Rölph Diäålysis';
echo $string . &quot;\n&quot; . iconv('UTF-8', 'ASCII//TRANSLIT', $string);

//The console says this:
/*
M├╢bius FTW because my name is R├╢lph Di├ñ├Ñlysis
M&quot;obius FTW because my name is R&quot;olph Di&quot;aalysis
*/
</pre>
<p>Obviously, it&#8217;s not totally perfect (it tries to approximate the look of them as closely as possible, which is why quotation marks replace the umlauts). This is compiled into PHP by default unless you&#8217;re stupid and decide to disable the <kbd>iconv</kbd> extension for no reason. Don&#8217;t do that. I believe it&#8217;s un-disablable in PHP 5.3.</p>
<p>You can also use the <a href="http://php.net/strtr">strtr</a> function, but then you have to pass the translation characters yourself.</p>
<pre class="brush: php;">
$string = 'Möbius FTW because my name is Rölph Diäålysis';
echo $string . &quot;\n&quot; . strtr($string, array('ö' =&gt; 'o', 'ä' =&gt; 'a', 'å' =&gt; 'a'));

//The console says:
/*
M├╢bius FTW because my name is R├╢lph Di├ñ├Ñlysis
Mobius FTW because my name is Rolph Diaalysis
*/
</pre>
<p>You could fairly easily and non-painlessly write a reusable library function in PHP using <kbd>strtr()</kbd> that will convert from unicode to ASCII, in the spirit of <a href="http://us.php.net/manual/en/function.strtr.php#56973">this</a>.Obviously you wouldn&#8217;t want to write a conversion array for 65000 unicode characters, but you could at least do the characters you use most often.</p>
<p>Another option is the <a href="http://pecl.php.net/package/translit">translit PECL extension</a>. This would require you to compile an extension, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/08/transliteration-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get Content-Length of Remote File in PHP</title>
		<link>http://blargh.tommymontgomery.com/2009/07/get-content-length-of-remote-file-in-php/</link>
		<comments>http://blargh.tommymontgomery.com/2009/07/get-content-length-of-remote-file-in-php/#comments</comments>
		<pubDate>Sun, 26 Jul 2009 01:10:52 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=72</guid>
		<description><![CDATA[Update: Apparently you can just use the get_headers() function. I am retarded.
I just posted this to the PHP comments, but I figured I&#8217;d put here as well. The stat() suite of functions isn&#8217;t available to the HTTP stream wrapper in PHP, so if you&#8217;re using readfile() to handle downloads (for example, like I was), and [...]]]></description>
			<content:encoded><![CDATA[<p>Update: Apparently you can just use the <a href="http://php.net/get_headers">get_headers()</a> function. I am retarded.</p>
<p>I just posted this to the <a href="http://php.net/manual/en/function.filesize.php#92462">PHP comments</a>, but I figured I&#8217;d put here as well. The <kbd>stat()</kbd> suite of functions isn&#8217;t available to the HTTP stream wrapper in PHP, so if you&#8217;re using <kbd>readfile()</kbd> to handle downloads (for example, like I was), and it&#8217;s coming from a remote site (like it was), then this is useful.</p>
<p>Using the <kbd>Content-Length</kbd> response header is very useful for downloads because it is what displays the progress bar and estimated time left to the user; otherwise, they just see &#8220;unknown&#8221;, which is annoying because they won&#8217;t know if they&#8217;re downloading something that is 4GB or 4KB. And that letter makes all the difference.</p>
<p>Anyway, use this code.</p>
<pre class="brush: php;">
$remoteFile = 'http://us.php.net/get/php-5.2.10.tar.bz2/from/this/mirror';
$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
  echo 'cURL failed';
  exit;
}

$contentLength = 'unknown';
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
  $contentLength = (int)$matches[1];
}

header('Content-Length: ' . $contentLength);
header('Content-Disposition: attachment; filename=&quot;' . basename($remoteFile) . '&quot;');
readfile($remoteFile);
</pre>
<p>Using the <kbd>CURLOPT_NOBODY</kbd> cURL option forces cURL to send a HEAD request instead of a GET request. The difference between the two is that HEAD only retrieves the headers. So even if the file you&#8217;re requesting is 100GB, it will take the same amount of time for a HEAD request as a file that is 100KB.</p>
<p>For example, doing this:</p>
<pre class="brush: php;">
$contentLength = strlen(file_get_contents($remoteFile));
</pre>
<p>accomplishes the same thing, but it retrieves the entire body of the resource, which is very, very bad if it&#8217;s a very large resource. Not to mention the extra memory required to store the contents of the remote file. Stick to the HEAD requests. I knew they were good for something.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/07/get-content-length-of-remote-file-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>array_flatten()</title>
		<link>http://blargh.tommymontgomery.com/2009/06/array_flatten/</link>
		<comments>http://blargh.tommymontgomery.com/2009/06/array_flatten/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 07:33:51 +0000</pubDate>
		<dc:creator>tmont</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blargh.tommymontgomery.com/?p=50</guid>
		<description><![CDATA[How exactly is this function not in the PHP core yet?

function array_flatten($arr) {
	$flattened = array();
	if (is_array($arr)) {
		foreach ($arr as $value) {
			$flattened = array_merge($flattened, array_flatten($value));
		}
	} else {
		$flattened[] = $arr;
	}

	return $flattened;
}

Usage:

$a = array(
	'foo' =&#62; 'bar',
	'baz' =&#62; array(1, 2, 3, 4, 5),
	'bat' =&#62; array(
		'a',
		array(
			'b',
			array(
				'c',
				array('d')
			)
		)
	)
);

print_r(array_flatten($a));

/*
Array
(
    [0] =&#62; bar
    [1] =&#62; 1
   [...]]]></description>
			<content:encoded><![CDATA[<p>How exactly is this function not in the PHP core yet?</p>
<pre class="brush: php;">
function array_flatten($arr) {
	$flattened = array();
	if (is_array($arr)) {
		foreach ($arr as $value) {
			$flattened = array_merge($flattened, array_flatten($value));
		}
	} else {
		$flattened[] = $arr;
	}

	return $flattened;
}
</pre>
<p>Usage:</p>
<pre class="brush: php;">
$a = array(
	'foo' =&gt; 'bar',
	'baz' =&gt; array(1, 2, 3, 4, 5),
	'bat' =&gt; array(
		'a',
		array(
			'b',
			array(
				'c',
				array('d')
			)
		)
	)
);

print_r(array_flatten($a));

/*
Array
(
    [0] =&gt; bar
    [1] =&gt; 1
    [2] =&gt; 2
    [3] =&gt; 3
    [4] =&gt; 4
    [5] =&gt; 5
    [6] =&gt; a
    [7] =&gt; b
    [8] =&gt; c
    [9] =&gt; d
)
*/
</pre>
<p><a href="http://us.php.net/manual/en/function.array-values.php#86784">This version</a> is interesting, but using <kbd>create_function()</kbd> is rarely a good idea, since it&#8217;s never garbage collected.</p>
]]></content:encoded>
			<wfw:commentRss>http://blargh.tommymontgomery.com/2009/06/array_flatten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
