<?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>Syndicate Theory</title>
	<atom:link href="http://www.syndicatetheory.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.syndicatetheory.com</link>
	<description></description>
	<lastBuildDate>Tue, 20 Mar 2012 22:53:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Developing on Union Filesystems</title>
		<link>http://www.syndicatetheory.com/labs/developing-on-union-filesystems</link>
		<comments>http://www.syndicatetheory.com/labs/developing-on-union-filesystems#comments</comments>
		<pubDate>Tue, 20 Mar 2012 22:45:52 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.syndicatetheory.com/?p=848</guid>
		<description><![CDATA[Most platforms we work on are very modular: you build components which plug into a larger system. They tend to be isolated into a single directory, and therefore its quite ...]]></description>
			<content:encoded><![CDATA[<p>Most platforms we work on are very modular: you build components which plug into a larger system.  They tend to be isolated into a single directory, and therefore its quite easy to version them.  You can either use svn:externals or git submodules to independently track each component while having a fully working system.</p>
<p>Here is an example&#8230;</p>
<pre>├── ./app
└── ./plugins
    ├── ./plugins/plugin_a
    ├── ./plugins/plugin_b
    └── ./plugins/plugin_c
</pre>
<p><strong>The Problem</strong></p>
<p>Unfortunately, it&#8217;s not a perfect world, and some platforms are not as well architected.  Alternatively, they may be architected that way, but you may still want some files above that isolated area.  This typically poses a problem. How can we effectively combine several components, each with its own tree of files, into one working copy?</p>
<p>What if we&#8217;re stuck with four projects like this &#8211; each with no top level &#8220;plugin&#8221; directory?</p>
<pre>├── ./admincp
├── ./includes
│   └── ./includes/functions_something.php
├── ./index.php
└── ./something.php
</pre>
<pre>├── ./admincp
│   └── ./admincp/security.php
├── ./images
│   └── ./images/secure.png
└── ./includes
    ├── ./includes/functions_security.php
    └── ./includes/xml
        └── ./includes/xml/product-security.xml
</pre>
<p>These two projects have to fit into the core platform&#8217;s filesystem tree in order to work.  We&#8217;ve been dealing with projects made up of a dozen or so smaller projects, and it was a nightmare to manage.  Initially, we had one large repository, which was fine, but as soon as you want to start re-using any component it becomes problematic.  Symbolic links can work, but we didn&#8217;t want to have to maintain that configuration for a growing number of projects, on my computer as well all staff.  </p>
<p>The other headache of a large repository (or project) is the number of files you need to work with. The context of a given task becomes much larger, and it&#8217;s harder to find the files that are relevant.</p>
<p><strong>Enter Union Filesystems</strong></p>
<p>Our first stab at this was looking for a sync program to handle syncing multiple directories into a master one.  That seemed reasonable, but was still not ideal. After more searching, we came across union filesystems.  Specifically, <a href="#">AUFS: Another Union Filesystem</a>.  Now, there may be other better ones at some point, but that&#8217;s beyond the scope of this article&#8230;</p>
<p>AUFS is a type of filesystem that allows you to <em>stack</em> a series of  directories into a single target.  Depending on your development platform, you may not be able to do it.  I made the plunge of switching to Ubuntu a while back for this very reason: if you are developing for Linux systems, you should be building them on a Linux system.  It&#8217;s possible to install for other Linux type systems, but very cautious.</p>
<p>Here is the command&#8230;</p>
<p><code>mount -t aufs -o br=/src1:/src2:/src3 none /path/to/stacked/dir</code></p>
<p>You can essentially pull in those 3 source directories, stack them at /path/to/stacked/dir, and run your application from that directory.  Directories stack from right to left, so anything on the left will take precedence.  You can also specify how the stacked directory behaves when modified.  This is where it gets very cool.</p>
<p>Let&#8217;s say we have 3 plugin directories: <code>plugin1</code>, <code>plugin2</code>, <code>plugin3</code>, and our base system: <code>platform</code>.  Let&#8217;s say we want to perform a fresh install of <code>platform</code> to <code>instance/</code></code>.  </p>
<p>Here is the command... </p>
<p><code>mount -t aufs -o br=local:plugins/plugin1:plugins/plugin2:plugins/plugin3/vendor/platform none instance</code></p>
<p>I've shortened the paths for the sake of readability (you should be using full paths), but that's what the command would look like.  I've introduced a new folder as well called <code>local</code> which would contain all of our changes on it.  We can use this for several things:</p>
<ul>
<li>Versioning our local installation</li>
<li>Having a folder only contain system-created files (log files, uploads, etc.)</li>
</ul>
<p>AUFS creates a bunch of .wh..wh* files in the furthest-left directory.  This keeps track of any deleted files.  This is also very cool: we can delete files from our live instance, and the filesystem reflects that, but the source files are never actually deleted.</p>
<p>The other handy use-case of this is deploying an instance of a platform for users to screw around on without any harm to the source system itself.  If they screw something up, you can restore them easily enough.  You can also run a ton of sites from a single set of source files.</p>
<p>For local development, it makes sense to have your VCS ignore the .wh* files and use it for project configuration and other local project artifacts that you want versioned.</p>
<p><strong>Workflow</strong></p>
<p>Being able to split up repositories may offer some changes to your existing workflow.  It allows you to version more things than you typically could, which means you may end up with more small repositories.</p>
<p>When developing, I'd load the <em>source</em> files in your editor, and never directly edit the stacked directory.  This allows you to work on very small projects, only having to worry about what is needed and relevant to that project.</p>
<p>The only flaw we've run into is the mount command doesn't always pick up new files quick enough.  You may find yourself re-running the mount command as part of your workflow.  To me that is a easy to tradeoff that I'm happy to take.</p>
<p>Also, be warned that these mounts are not permanent unless you either run them at start-up, or put them in your fstab file.  </p>
<p><strong>Rapid Project Development</strong></p>
<p>If you often build projects consisting of a platform and multiple components, you can quickly generate new "builds" (stacked deploys) and mess around with them efficiently. </p>
<p>To be honest, I have no idea how this would perform in a production environment.  If you give it a try, let me know how it goes.</p>
<p><strong>Not a Replacement for Goood Architecture</strong></p>
<p>For the primary use case I've described, this is sort of an anti-pattern.  Versioning and packaging systems handle this problem far better.  However, be aware that not all platforms were created with modularity in mind (or they failed), in which case traditional tools do not work very well.  </p>
<p>I wouldn't do this for any of my newer projects (er-platforms), except perhaps as experimentation, and I much prefer the use of git submodules, or even a packaging system such as <a href="http://github.com/composer/composer">Composer</a> (more on that later!).</p>
<p>This has already saved us piles of time, so hopefully somebody else finds it useful, or at least interesting.  <img src='http://www.syndicatetheory.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/developing-on-union-filesystems/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Navigate Relative URLs in FireFox</title>
		<link>http://www.syndicatetheory.com/labs/navigate-relative-urls-in-firefox</link>
		<comments>http://www.syndicatetheory.com/labs/navigate-relative-urls-in-firefox#comments</comments>
		<pubDate>Thu, 19 Jan 2012 20:13:50 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.syndicatetheory.com/?p=830</guid>
		<description><![CDATA[For a long time I&#8217;ve been wondering how I can navigate around the web using relative URLs (similar to using cd in Linux). Using various content management systems, it&#8217;s a ...]]></description>
			<content:encoded><![CDATA[<p>For a long time I&#8217;ve been wondering how I can navigate around the web using relative URLs (similar to using <code>cd</code> in Linux).  Using various content management systems, it&#8217;s a real pain to have to select the relevant portion of the URL, and type in wp-admin, admin, admincp, etc. Even on some sites, being able to go up a level is very handy when the navigation is lacking.  All without a mouse.  </p>
<p>Ambitious, right?  After searching for a while, I couldn&#8217;t find anything like this out there.  Just today I decided to take another stab at it, and actually came up with an elegant solution.  No plugins or hacky measures required.</p>
<p>Create a new bookmark and set the keyword as something short that you would like to use.  I used <code>cd</code>.  The way smart bookmarks, or keywords, work is you enter <code>keyword</code> <code>everything else</code> into the address bar, and everything following the keyword gets put into the <code>%s</code> placeholder from the bookmark URL.</p>
<p>To navigate to a relative path, we&#8217;d use the following bookmark URL: <code>javascript:window.location="%s"</code></p>
<p>Now, whenever you type something like <code>cd ..</code> or <code>cd /admin</code> into your address bar, you&#8217;ll navigate to the correct relative path.  If you&#8217;re super lazy like me, you can use <code>Ctrl+L</code> to bring the address bar into focus.</p>
<p>It&#8217;s all about the small victories.  <img src='http://www.syndicatetheory.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/navigate-relative-urls-in-firefox/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>vBulletin Large Inline Images &#8220;Exploit&#8221;</title>
		<link>http://www.syndicatetheory.com/labs/vbulletin-large-inline-images-exploit</link>
		<comments>http://www.syndicatetheory.com/labs/vbulletin-large-inline-images-exploit#comments</comments>
		<pubDate>Tue, 10 Jan 2012 20:51:43 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[ForumOps]]></category>
		<category><![CDATA[vBulletin]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[exploit]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.syndicatetheory.com/?p=817</guid>
		<description><![CDATA[Disclaimer: this does not affect newer versions of vBulletin! Only old versions are affected, and only if you have no maximum character limit in posts. Our forum brand, ForumOps works ...]]></description>
			<content:encoded><![CDATA[<p><strong>Disclaimer: this does not affect newer versions of vBulletin! Only old versions are affected, and only if you have no maximum character limit in posts.  </strong></p>
<p>Our forum brand, <a href="http://www.forumops.com/">ForumOps</a> works on a lot of vBulletin forums, primarily running on 3.8.x.  We ran into quite an annoying &quot;exploit&quot; (perhaps not technically, but it&#8217;s caused us problems) that older communities should be interested in. </p>
<p>Whenever you copy/paste an image into the editor, it gets converted into an inline image.  This makes people say &#8220;wow!&#8221; because it&#8217;s so much more convenient than using the attachment system or than using a 3rd party image uploading service.   vBulletin&#8217;s old WYSIWYG editor uses <a href="http://en.wikipedia.org/wiki/Data_URI_scheme">inline images</a>, which get inserted directly into the post with base64 encoding.  There are a few major concerns here&#8230;</p>
<p>However, in order for this to cause problems, you need to have the post character limit disabled.  This is quite common, since without a technical explanation, why would you want to limit the post length?  Some people post long articles and are frustrated by it.  Usually, the inline image is harmless&#8230; people who copy/paste rich content typically only paste in small images or icons, which jut work.  </p>
<p>If you post a large image, and have the character limit disabled, it can cause a myriad of problems.</p>
<p><strong>Database</strong> &#8211; Let&#8217;s say an average post is 1000 characters.  That is approximately 1000 bytes, or roughly 1 kilobyte (assuming they are standard English characters).  Once you paste an image in, that post could now be 1MB, or even 10MB (depending on multiple PHP settings). 1MB is a fairly reasonable image size that we see quite often.  With a single image embedded in the post, that post is now takes up 1000x space.  If you had a few images, or a larger image, it could be up to 100,000x larger!   People tend to see performance problems once they get a few hundred thousand posts, and especially once they get into the millions.  If you have a few posts, you will be hitting those limits a lot faster than you&#8217;d expect.  This can create some obvious database issues with performance and maintainability.  This may even cause your post table to crash and give you a ton of hard to debug problems.  A DBA will notice the table is huge, but will just assume it&#8217;s because of all the post content.</p>
<p><strong>vBulletin Code</strong> &#8211; The biggest problem we ran into was with the BB code parser.  Instead of it having to parse 1kb of text, it now has ~1000x more text to process, which is brutally slow.  This makes viewing that broken thread impossible since it will likely time out, or just hang forever (long enough for people to give up, anyway).  If it&#8217;s buried in a popular thread, it may even be near impossible to remove, since it&#8217;s hard to delete posts without actually going into the specific thread.</p>
<p>Now, our client was lucky since the problem was ran into on accident.  A user had posted a 5MB image, and we received complaints about certain parts of the site being broken (BB Code parser showing new posts, and in a custom moderator section).  A malicious user could easily use this to bring the site down rapidly, giving the moderators little to no chance of fighting back.  </p>
<p><strong>The Solution</strong> &#8211; If you insist on disabling your post limit, please consider setting it high (even very high; say 500,000) since users could still post a huge post and cause issues.  Images are a little trickier since it&#8217;s unintentional.  However, people are set in their ways, so lets at least try to mitigate the root problem&#8230;</p>
<p>If you create a new plugin using the &quot;newpost_process&quot; hook, and use the following code, it should prevent attacks.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'message'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'data:image'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span> and <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'message'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'base64'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$maxSize</span>   <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1024</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">500</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$totalSize</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$matches</span>   <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span>
    	<span style="color: #0000ff;">'#data\:image/(gif|png|jpg|jpeg);base64,([0-9a-zA-Z\+\/\=]+)\[/(img|IMG)\]#'</span><span style="color: #339933;">,</span> 
        <span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'message'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> 
        <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span>
        PREG_SET_ORDER
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$totalSize</span> <span style="color: #339933;">+=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$totalSize</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$maxSize</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$dataman</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span>
            <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;
            	You've copy-pasted some images in your post which are <span style="color: #009933; font-weight: bold;">%s</span> too large.
            	Please remove them and add them as attachments instead.
            &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	    vb_number_format<span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'message'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$maxSize</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This checks for the existence of inline images within a post, and can limit them to a specific file size.  In the above code, I have it set at 500kb, which is probably a little high.  Feel free to tweak the error message the user will receive.</p>
<p>I have no idea which versions this affects.  I know it works on 3.x, and perhaps some of the earlier 4.x versions before the editor was swapped out.  If anyone can verify it for specific versions, I&#8217;ll be sure to mend my post.</p>
<p>Hope this helps someone out there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/vbulletin-large-inline-images-exploit/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#phpKL- Come to Learn, Network or Share</title>
		<link>http://www.syndicatetheory.com/labs/phpkl-come-to-learn-network-or-share</link>
		<comments>http://www.syndicatetheory.com/labs/phpkl-come-to-learn-network-or-share#comments</comments>
		<pubDate>Mon, 03 Oct 2011 17:01:16 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Local Community]]></category>
		<category><![CDATA[accelerate okanagan]]></category>
		<category><![CDATA[phpkl]]></category>

		<guid isPermaLink="false">http://www.syndicatetheory.com/?p=785</guid>
		<description><![CDATA[Calling all local PHP developers! For the past 2 months, I&#8217;ve been putting on a weekly PHP session for those who want to learn interesting new things, network with other ...]]></description>
			<content:encoded><![CDATA[<p>Calling all local PHP developers!  For the past 2 months, I&#8217;ve been putting on a weekly PHP session for those who want to learn interesting new things, network with other developers, or simply share something you&#8217;re working on.  Being a developer is tough; there is an infinite amount of things you need to stay ahead with, and trying to do it all yourself is even harder.  Even as a PHP developer, you can easily specialize in 1 of around 1000 different skill-sets which makes it easy to become a generalist.  The goal of this event is to help share the research and development load with your peers.  Kelowna is a small fish in the tech world; we need to help each other out to compete, and to help grow Kelowna&#8217;s technology community.</p>
<p>My experience is strictly in back-end development, so I try to keep up with the experts in the global PHP community.  Due to the nature my past clients, I&#8217;ve also grown to specialize in performance and security.  If you&#8217;re looking for a mentor, or even to mentor others, this is a great opportunity to learn new things and meet other people who face similar problems to you every day.</p>
<p>We meet every Wednesday morning at 8am-9am, inside Accelerate Okanagan.  The format is an hour a week before work to be consistent enough to continuously re-enforce what you learn, and also give you the chance to quickly apply new things while they are fresh.  There is already a core group of about 4 of us, but we&#8217;d love to see some new faces out!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/phpkl-come-to-learn-network-or-share/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Write Code for Humans</title>
		<link>http://www.syndicatetheory.com/labs/write-code-for-humans</link>
		<comments>http://www.syndicatetheory.com/labs/write-code-for-humans#comments</comments>
		<pubDate>Thu, 29 Sep 2011 05:04:51 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Interface Development]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[assetic]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[zf]]></category>

		<guid isPermaLink="false">http://www.syndicatetheory.com/?p=745</guid>
		<description><![CDATA[After working on high-performance projects for a while (or aspiring to), it gets easy to build things in such a way that favors performance over readability. It&#8217;s good to be ...]]></description>
			<content:encoded><![CDATA[<p>After working on high-performance projects for a while (or aspiring to), it gets easy to build things in such a way that favors performance over readability.  It&#8217;s good to be reminded every once and a while that while we develop code for computers to execute, ultimately it&#8217;ll be humans who will work with them.  </p>
<p>Mobile web applications are an interesting example.  A large portion of the code is downloaded and executed by remote clients, so we tend to pay more attention to total file-size, number of HTTP requests, and ultimately how much code gets executed on the other end.  If we are graded on our work, surely this is what will be looked at. There are benchmarking tools such as <a href="http://developer.yahoo.com/yslow/">Yahoo YSlow</a> and <a href="http://pagespeed.googlelabs.com/pagespeed/">Google Page Speed</a> which help you analyze your site and suggest techniques to apply.  Naturally, everyone wants an A or a high rating.</p>
<p>About a week ago, I was looking over one of my projects, and wondered what the hell happened to the code; it was awful.  White-space was missing in a lot of areas, CSS was condensed (in <em>most</em> places), and even some of the PHP caching code was pretty hackish.  Since I was having to rebuild a large component of the project for other reasons, I made an effort to clean up these concerning areas.</p>
<p>If you can optimize your architecture or design as you go, then by all means do it.  What you shouldn&#8217;t do; however, is try and remove things that affect readability in favor of performance.  I think there are two acceptable ways to do this&#8230; as part of a build/deployment script, or as a filter in production.  Your development copy should always be for humans.  <em>Developer time is often significantly more expensive than server resources.</em>  Let&#8217;s look at some of the various resources we need to deal with&#8230; <span id="more-745"></span></p>
<p><strong>CSS / JavaScript</strong></p>
<p>Tools like <a href="http://code.google.com/p/minify/">minify</a> are awesome for this.  Simply pass your external CSS/JS files as a query parameter, and it generates a combined and minified version of the resources so the client only downloads one file.  You can also use this or similar tools for inline CSS/JavaScript, though those can usually be avoided unless you&#8217;re dealing with truly dynamically generated code.</p>
<p>If you&#8217;re using Zend Framework, check out <a href="https://github.com/bubba-h57/zf-helpers">these view helpers</a> to use Minify with <code>Zend_View_Helper_HeadScript</code> and <code>Zend_View_Helper_HeadLink</code>.  Similarly, if you&#8217;re using <a href="http://symfony.com/">Symfony2</a>, check out the builtin component, <a href="https://github.com/kriswallsmith/assetic">assetic</a>.  </p>
<p><strong>Whitespace / HTML File Size</strong></p>
<p>Make your templates as readable as possible.  There are two ideal choices to deal with this: gzip/deflate compression or a simple filter that removes extraneous white-space.  Here&#8217;s an example of how you could set up compression.  Add any of the following lines to your</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_deflate.c&gt;
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/plain
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/html
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/xml
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/css
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE application/xml
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE application/xhtml+xml
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE application/rss+xml
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE application/javascript
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE application/x-javascript
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;</pre></div></div>

<p>Each particular line would enable deflate compression for the associated mime type.   You can usually expect around 2/3 to 3/4 of your filesize to disappear when compressed.  The other approach, which was a filter, would look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/&gt;\s+&lt;/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&gt;&lt;'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This is blatantly taken from <a href="http://twig.sensiolabs.org/doc/templates.html">Twig</a>&#8216;s <code>spaceless</code> filter.  Note, there isn&#8217;t much point in using both of these techniques.  It&#8217;s best to benchmark both (resulting file-size, server compression time, client decompression time) and decide for yourself.  </p>
<p><strong>Images</strong></p>
<p>Although not in scope of this post, you can do similar processing to images.  There are command-line tools available to compress images, or remove meta data from them to help eliminate a few percent of file-size.  This is definitely not the low hanging fruit, but interesting nonetheless.  Don&#8217;t spend too much time optimizing specific images when it&#8217;s possible to run batch processing across all of your images at deploy or update time.</p>
<p>Do yourself and your peers a favor, write code with them in mind.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/write-code-for-humans/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinking Asynchronously in PHP</title>
		<link>http://www.syndicatetheory.com/labs/thinking-asynchronously-in-php</link>
		<comments>http://www.syndicatetheory.com/labs/thinking-asynchronously-in-php#comments</comments>
		<pubDate>Mon, 26 Sep 2011 19:57:09 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[asynchronous]]></category>
		<category><![CDATA[beanstalkd]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[gearman]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[queuing]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://labs.syndicatetheory.com/?p=627</guid>
		<description><![CDATA[PHP is an excellent language for developing on the web. It&#8217;s portable, versatile and has matured a lot over the past few years. Web applications are becoming more complex each ...]]></description>
			<content:encoded><![CDATA[<p>PHP is an excellent language for developing on the web.  It&#8217;s portable, versatile and has matured a lot over the past few years.  Web applications are becoming more complex each day: they are processing massive amounts of data, talking to other services, and are expected to do so quickly.  They get to a point where processing is either too server intensive, or it may be making your site less responsive to users if its doing too much.  If you take a step back and think about PHP applications asynchronously, you can build faster, more scalable applications. <span id="more-627"></span></p>
<h2>Web Application Flow</h2>
<p>A typical web application&#8217;s job is to turn a request into a response.  In order for this to appear responsive, applications should generate that response as quickly as possible &#8211; I usually find anything under half a second acceptable.  If we were to build the application asynchronously, we&#8217;d delegate any complex logic, service calls, or other expensive tasks.  These tasks can usually be broken down into two categories&#8230;</p>
<h2>Preparing Data For This Page</h2>
<p>If a page requires us to perform complex queries, pull data from web services, etc. then that will likely add considerable delays to page generation.  The usual response is caching, but people tend to naturally still use it in a synchronous fashion.  Let&#8217;s take a twitter feed as an example (showing latest 10 tweets).  </p>
<p>You&#8217;ll see code like this quite often:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getTweets<span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$tweets</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;tweets_<span style="color: #006699; font-weight: bold;">$username</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$tweets</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$tweets</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_twitter<span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;tweets_<span style="color: #006699; font-weight: bold;">$username</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tweets</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$tweets</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>It checks to see if our cache entry exists, and returns it if it does.  If not, it calls the routine that fetches the tweets from Twitter, and caches that result (assuming our default cache expiration).  Let&#8217;s say this is 30 minutes.  The problem with this approach is every 30 minutes, it needs to download the information again, making the user wait while the page loads.  The other major problem is that when Twitter is down (or for whatever reason, we are unable to connect), the page is broken, because the cache has expired.</p>
<p>A much better approach is to never even attempt to do this work in the main application flow.  Instead, let&#8217;s have a cron job run every 30 minutes that downloads this information and caches it with no expiration.  This way, even if Twitter is down, the cached copy is always expected to work.  You could still use the above code as a safeguard, but with this approach it should never have to be used as a fallback.  You&#8217;d only want to ever update the cache if you successfully retrieve your information.</p>
<p>This model works with almost any data you can cache.  You&#8217;ll need to decide if you&#8217;d rather only perform these tasks on demand (when a user visits a page), or if you want to do a little extra work to ensure the data is always available.  Depending on the traffic of the site, or the amount of unique cacheable items you are working with, you&#8217;ll have to weigh the benefits.</p>
<h2>Processing Needed Later</h2>
<p>The other category usually comes from requests that actually need some sort of action performed.  One concept we&#8217;re going to look at which really helps scale your applications is a <em>work queue</em> or <em>job queue</em>.  With a queue in place, we can defer execution of actions so we can quickly complete our request to response cycle.  Just because something is delayed, it doesn&#8217;t mean there will be a lapse in our accurate data.  By simply delaying something for 1, or even 0 seconds, it can be run immediately, but from another process.</p>
<p>The way this works is we need to have a few different processes in place:</p>
<dl>
<dt>Job Queue</dt>
<dd>Storage of tasks to be executed.  Example: print spooler</dd>
<dt>Job Worker</dt>
<dd>A process that reads tasks from the queue, and executes them.  Workers can be spread across multiple physical machines, if necessary.</dd>
<dt>Client</dt>
<dd>A client would be our application, which adds items to the job queue.  Similar to workers, we could have multiple applications using the same queue.</dd>
</dl>
<p>Let&#8217;s look at some examples&#8230;</p>
<h3>Sending Mail</h3>
<p>Using PHP to send mail is a relatively simple task.  If your server can directly send mail, then it is probably very quick, too.  A lot of servers will use some sort of mail queue internally to ensure mail gets sent at a steady pace and doesn&#8217;t overload the server.  However, if you are sending mail via remote web servers (for example, using GMail), then it will take a lot longer, especially if you are sending lots of mail.</p>
<p>Instead of making the user wait a few extra seconds, we can instead toss the mail into a queue (which should be very quick) and not worry about it.  Then, one of our mail queue workers can process it as soon as they are available.  Depending on your set up, this could be instant, or it could be very delayed.  It&#8217;s up to you to decide how important the timing of your mail delivery is.</p>
<h3>Rebuilding Stats, Caches, etc.</h3>
<p>Another common scenario is performing clean-up processing after making changes to your data.  Delaying execution until another process can pick it up is usually harmless to the user, and gets them to their next task that much faster.</p>
<h2>Different Types of Queues</h2>
<p>There are two very common implementations or approaches you can take.  </p>
<h3>Running as a Daemon</h3>
<p>If you need to minimize time between queuing and execution, or more importantly, between scheduled execution and actual execution, you should look at something like <a href="http://gearman.org/">Gearman</a> or <a href="http://kr.github.com/beanstalkd/">beanstalkd</a> .  These applications run as <a href="http://en.wikipedia.org/wiki/Daemon_%28computing%29">daemon</a> and can immediately process queued tasks as they are ready to be executed.  However, since it requires software to be running, it may not be available or possible in some hosting environments, and takes a little more work to set up.  I&#8217;d argue, for the accuracy, it will faster than the alternatives since it is not having to continually poll to get new data.</p>
<h3>Running Scheduled Tasks</h3>
<p>If you are limited, a simple option is to set up a scheduled task for your worker.  It should be a simple PHP script that connects to your queue (you could store it in the database), and processes items as they are available.  If you want things to run as quickly as possible, you can make your cron job run more frequently, however this may also burden your system depending how frequently you poll, and how intensive your scripts are.</p>
<p>I&#8217;m going to follow this post up with some examples of implementing this with both a database-based queue, running as a scheduled task, and also with either gearman or beanstalkd.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/thinking-asynchronously-in-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Community in Software</title>
		<link>http://www.syndicatetheory.com/labs/community-in-software</link>
		<comments>http://www.syndicatetheory.com/labs/community-in-software#comments</comments>
		<pubDate>Fri, 16 Sep 2011 18:57:07 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://labs.syndicatetheory.com/?p=604</guid>
		<description><![CDATA[I&#8217;m of the opinion that software without community fails.  When I&#8217;m looking at software to use, whether it&#8217;s development tools, content management systems, or other applications, there is almost always ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m of the opinion that software without community fails. </p>
<p>When I&#8217;m looking at software to use, whether it&#8217;s development tools, content management systems, or other applications, there is almost always a direct correlation between quality of product and size of community. When I talk about &#8220;product&#8221;, I don&#8217;t necessarily mean the actual downloaded package or even the code. </p>
<p>I&#8217;ll admit, I&#8217;m usually quick to point out poorly designed software.  As a developer, I hate WordPress with a passion, but because it has such a strong community, the ecosystem around it is incredible.  I can get by simply by installing plugins and themes, and hopefully not ever have to touch any code.  If I get stuck, with anything, there is so much community, support and documentation on the web that it&#8217;s a very positive and usually fruitful experience.</p>
<p>This past week I&#8217;ve been working with another seemingly popular CMS.  I thought it would be easy to work through whatever issues I had, because I&#8217;ve heard of it before, and you know, if it&#8217;s anything like WordPress I&#8217;ll have no problem&#8230; do a quick search, find a plugin, configure, profit.  I very quickly found a screencast by one of the few (only?) companies supporting the product.  It was outdated, and on the version I was working with, did not work correctly.  I immediately asked on Twitter and my extended network.  Nothing.</p>
<p>For examples sake, let&#8217;s say this product was technically far superior to WordPress.  It doesn&#8217;t matter.  No amount of technical superiority will ever amount to anything if it has no strong community to back it.</p>
<p>Since the rise of social networks, forums, GitHub || SouceForge (they need some love, too), the global software community has become a lot more united. It&#8217;s not just the geeks on mailing lists and IRC anymore.  If you&#8217;re developing software for the public, embrace community.  Community wins.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/community-in-software/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook Page Like Redirect</title>
		<link>http://www.syndicatetheory.com/labs/facebook-page-like-redirect</link>
		<comments>http://www.syndicatetheory.com/labs/facebook-page-like-redirect#comments</comments>
		<pubDate>Wed, 10 Aug 2011 20:12:34 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[facebook]]></category>

		<guid isPermaLink="false">http://adrianschneider.ca/?p=597</guid>
		<description><![CDATA[We encountered some pretty nasty Facebook behavior late last night during a launch. Usually when you &#8220;Like&#8221; a page, the iframe application refreshes normally. However, if your application is the ...]]></description>
			<content:encoded><![CDATA[<p>We encountered some pretty nasty Facebook behavior late last night during a launch. Usually when you &#8220;Like&#8221; a page, the iframe application refreshes normally. However, if your application is the page&#8217;s default tab, the on &#8220;Like&#8221; redirect goes back to the wall. Apparently this is by design. There is a <a href="http://bugs.developers.facebook.net/show_bug.cgi?id=15226">bug report</a> filed, which states</p>
<blockquote><p>&#8220;Once a user Likes a page, by design, the landing page for future visits will be the Wall tab. Thanks for the report.&#8221;</p></blockquote>
<p>This is not what you&#8217;d expect &#8211; since it only appears to happen when the application is the default tab. I&#8217;d expect it would always redirect back to the tab you had open. They can still satisfy their above quote this way.</p>
<p>We couldn&#8217;t come up with any fixes, but found a few workarounds:</p>
<ul>
<li>Don&#8217;t use it as the default tab</li>
<li>Point your marketing material to the actual tab and not the generic page URL</li>
</ul>
<p>I also came up with a potential solution the next morning, which should work, though not tested:</p>
<ul>
<li>Add some JS code (pseudocode): if window.top.href == &#8216;generic page URL&#8217;, set window.top.href = &#8216;page URL with specified application tab&#8217;</li>
</ul>
<p>Hope this helps someone!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/facebook-page-like-redirect/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Local Facebook Development</title>
		<link>http://www.syndicatetheory.com/labs/local-facebook-development</link>
		<comments>http://www.syndicatetheory.com/labs/local-facebook-development#comments</comments>
		<pubDate>Fri, 29 Jul 2011 00:53:53 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[local development]]></category>

		<guid isPermaLink="false">http://adrianschneider.ca/?p=589</guid>
		<description><![CDATA[I&#8217;ve started doing a little Facebook application development again lately, so I&#8217;ve been on the prowl on how to do things more efficiently. Working local is efficient (we all know ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started doing a little Facebook application development again lately, so I&#8217;ve been on the prowl on how to do things more efficiently.  Working local is efficient (we all know that by now, I hope)&#8230;</p>
<p>Facebook has always been a bit of a pain with things like FBML, but now that page tabs support iframes, I thought I&#8217;d revisit it a little.  It turns out that you can simply use your localhost (or any private) address, and the iframe will load.  However, there are some major problems in the authentication process with this method.  I moved on, and continued to do things the old fashioned way with a remote development server, and set up all my application settings accordingly.</p>
<p>However, since Facebook simply needs to check the URL, and expect valid responses once and a while, you can edit your local hosts file and map the remote hostname to 127.0.0.1.  This way, when Facebook performs its checks, the remote server responds properly, but you can still rapidly develop locally with the iframe pointing to your local development server.</p>
<p>Example, assuming our development server is set up at dev.somefbapp.mycompany.com, we&#8217;d configure the app with that (public) address.  Then, when we want to test things more rapidly, we can enable this in our hosts file:</p>
<pre>127.0.0.1    dev.somefbapp.mycompany.com</pre>
<p>This seems to be working flawlessly for me as of today (July 28th, 2011) and on PHP SDK 3.2.  Hopefully this brings a little light to someones day who gets as frustrated as I do with Facebook&#8217;s documentation. <img src='http://www.syndicatetheory.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/local-facebook-development/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Zend_Db With Silex</title>
		<link>http://www.syndicatetheory.com/labs/using-zend_db-with-silex</link>
		<comments>http://www.syndicatetheory.com/labs/using-zend_db-with-silex#comments</comments>
		<pubDate>Fri, 15 Jul 2011 20:41:10 +0000</pubDate>
		<dc:creator>Adrian Schneider</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[silex]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[zend_db]]></category>

		<guid isPermaLink="false">http://adrianschneider.ca/?p=562</guid>
		<description><![CDATA[I&#8217;ve been messing around with Silex (and of course Symfony2) a lot lately, and I was excited to see a Doctrine extension. However, it was only for the DBAL and ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been messing around with Silex (and of course Symfony2) a lot lately, and I was excited to see a Doctrine extension.  However, it was only for the DBAL and not the ORM.  In my symfony2 apps, I&#8217;ve finally adjusted to using Doctrine&#8217;s ORM, but for some reason, I&#8217;ve really grown to like the DBAL that Zend_Db offers over the pseudo SQL (DQL) that Doctrine has.  Here is a quick Extension to get you started with Zend_Db.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> SyndExtension<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> SilexApplication<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> SilexExtensionInterface<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ZendDb implements ExtensionInterface
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> register<span style="color: #009900;">&#40;</span>Application <span style="color: #000088;">$app</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'autoloader'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerPrefix</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'zend.class_path'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$app</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">share</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">use</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$app</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> Zend_Db<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db.adapter'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'host'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db.host'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'dbname'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db.dbname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'username'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db.username'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'password'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db.password'</span><span style="color: #009900;">&#93;</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Create that under ./src/Synd/Extension/ZendDb.php.  To use it, you&#8217;ll need to add Synd to your autoloader, and then register the extension in your application:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'autoloader'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerNamespace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Synd'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$app</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">register</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> SyndExtensionZendDb<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'db.adapter'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mysqli'</span><span style="color: #339933;">,</span>    
    <span style="color: #0000ff;">'db.dbname'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'your_db'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'db.host'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'db.username'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'root'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'db.password'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'zend.class_path'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'/path/to/zf/library'</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Please note that this is a quick and dirty bridge, and is for ZF1 not ZF2.  If I&#8217;m breaking any best practices with naming and combining libraries, be sure to let me know. I&#8217;m hoping to explore the Zend_Db and Zend_Form combination since I use them heavily in my apps.  This provides a very lightweight infrastructure in order to throw up quick proof of concept applications.</p>
<p>Hopefully this helps someone&#8230; or at least gives enough familiarity for my ZF buddies to start looking at Silex / Symfony2.  <img src='http://www.syndicatetheory.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.syndicatetheory.com/labs/using-zend_db-with-silex/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

