<?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"
	>

<channel>
	<title>Developer Tutorials' Webmaster Blog &#187; PHP</title>
	<atom:link href="http://www.developertutorials.com/blog/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.developertutorials.com/blog</link>
	<description>Keeping webmasters up-to-date on technology.</description>
	<pubDate>Thu, 07 Aug 2008 06:42:22 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>Easy Screen Scraping in PHP with the Simple HTML DOM Library</title>
		<link>http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/</link>
		<comments>http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 07:10:54 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/</guid>
		<description><![CDATA[Client-side developers always had it easy - libraries such as jQuery and Prototype make finding elements on the page reliable and efficient. In PHP, regular expressions tend to get rather messy, DOM calls can be confusing and verbose, and often the string functions just aren&#8217;t enough. In this tutorial, I&#8217;ll show you how to use [...]]]></description>
			<content:encoded><![CDATA[<p>Client-side developers always had it easy - libraries such as jQuery and Prototype make finding elements on the page reliable and efficient. In PHP, regular expressions tend to get rather messy, DOM calls can be confusing and verbose, and often the string functions just aren&#8217;t enough. In this tutorial, I&#8217;ll show you how to use the middle ground - the open source PHP Simple HTML DOM Parser library, which provides jQuery-grade awesomeness for easy screen scraping without messy regular expressions.<span id="more-398"></span></p>
<p>The <a href="http://simplehtmldom.sourceforge.net/">Simple HTML DOM Parser</a> is implemented as a simple PHP class and a few helper functions. It supports CSS selector style screen scraping (such as in jQuery), can handle invalid HTML, and even provides a familiar interface to manipulate a DOM.</p>
<p>Here&#8217;s a sample of simplehtmldom in action:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000033;">$html</span> <span style="color: #339933;">=</span> file_get_dom<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://www.google.com/'</span><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: #000033;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'a'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000033;">$element</span><span style="color: #009900;">&#41;</span>
    <span style="color: #990000;">echo</span> <span style="color: #000033;">$element</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">href</span><span style="color: #339933;">;</span></pre></div></div>

<p>This snippet is fairly self explanatory - <code>file_get_dom()</code> is a simple helper function in the library that fetches the page and constructs a new simplehtmldom object around it. Once the object is available, we can easily use simple CSS selectors to find our elements - in this case, anchors - and iterate over them just as we would with PHP 5&#8217;s standard DOM classes. (The equivalent code with the standard DOM classes is twice as long.)</p>
<p>But the library doesn&#8217;t stop there - as well as traversing the DOM and extracting information, you can also alter it. Consider this snippet:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000033;">$html</span> <span style="color: #339933;">=</span> str_get_html<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'
&lt;div id=&quot;hello&quot;&gt;Hello&lt;/div&gt;
&lt;div id=&quot;world&quot;&gt;World&lt;/div&gt;
&nbsp;
'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">class</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'bar'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div[id=hello]'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">innertext</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'foo'</span><span style="color: #339933;">;</span></pre></div></div>

<p>The library supports many DOM-style approaches for manipulation, from exposing real attributes as shown here, to a few helper methods. It also includes other methods to traverse the current node - <code>children()</code>, <code>parent()</code>, <code>first_child()</code> and so on.</p>
<p>Real scraping? Easy. Here&#8217;s their Slashdot sample:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000033;">$html</span> <span style="color: #339933;">=</span> file_get_html<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://slashdot.org/'</span><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: #000033;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div.article'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000033;">$article</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000033;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span>     <span style="color: #339933;">=</span> <span style="color: #000033;">$article</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div.title'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">plaintext</span><span style="color: #339933;">;</span>
    <span style="color: #000033;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'intro'</span><span style="color: #009900;">&#93;</span>    <span style="color: #339933;">=</span> <span style="color: #000033;">$article</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div.intro'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">plaintext</span><span style="color: #339933;">;</span>
    <span style="color: #000033;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'details'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$article</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div.details'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">plaintext</span><span style="color: #339933;">;</span>
    <span style="color: #000033;">$articles</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$item</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$articles</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And finally, there&#8217;s always a simple save mechanism:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000033;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'altered-dom.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ready to get started? Head over to the <a href="http://simplehtmldom.sourceforge.net/">project website</a>, <a href="http://simplehtmldom.sourceforge.net/manual.htm">online documentation</a> or the <a href="https://sourceforge.net/projects/simplehtmldom/">project page on SourceForge</a>.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d398" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/&amp;title=Easy+Screen+Scraping+in+PHP+with+the+Simple+HTML+DOM+Library" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/&amp;title=Easy+Screen+Scraping+in+PHP+with+the+Simple+HTML+DOM+Library" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/&amp;title=Easy+Screen+Scraping+in+PHP+with+the+Simple+HTML+DOM+Library" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/easy-screen-scraping-in-php-simple-html-dom-library-simplehtmldom-398/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Four CSS Tricks Every PHP / Web Developer Should Know</title>
		<link>http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/</link>
		<comments>http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/#comments</comments>
		<pubDate>Thu, 31 Jul 2008 05:00:27 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/</guid>
		<description><![CDATA[It&#8217;s not easy being a web developer - in addition to a server-side language, we also have to learn a markup language, yet another (client-side) language and a presentation system. As a result, we tend to focus on what we&#8217;re closest to - the business logic - and neglect the front-end.
But you don&#8217;t have to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s not easy being a web developer - in addition to a server-side language, we also have to learn a markup language, yet another (client-side) language and a presentation system. As a result, we tend to focus on what we&#8217;re closest to - the business logic - and neglect the front-end.</p>
<p>But you don&#8217;t have to be a web dev guru to build great applications: with just a few simple tricks, you can make your web based interfaces more usable and more visually appealing. Here are a few simple CSS tricks every PHP / web developer should know.<span id="more-391"></span></p>
<p>Here&#8217;s a quick preview of how we&#8217;re going to transform our page:</p>
<p><img src="http://www.developertutorials.com/blog/wp-content/uploads/2008/07/css-1.png" alt="" title="CSS Before" width="166" height="166" class="alignnone size-full wp-image-389" /> <img src="http://www.developertutorials.com/blog/wp-content/uploads/2008/07/css-2.png" alt="" title="CSS After" width="166" height="166" class="alignnone size-full wp-image-390" /></p>
<p><strong>1. Styling Form Inputs, Buttons</strong><br />
When you pop an &lt;input&gt; onto your page, it&#8217;s at the mercy of the end user&#8217;s system for appearance, behaviour - even size. For example, Firefox handles unstyled inputs differently from IE, and both take many cues from the local OS styling; the same goes for Safari. This is okay on modern OSes &#8212; if you aren&#8217;t concerned with controlling your visuals &#8212; but quite a few users still run &#8220;Classic&#8221; interfaces, and it&#8217;s especially annoying for buttons. Here are some basic styles you should consider for your inputs.</p>

<div class="wp_syntax"><div class="code"><pre class="css">input <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #3333ff;">:<span style="color: #933;">3px</span></span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #3333ff;">:<span style="color: #933;">1px</span></span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#F0F0F0</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>These will first add a bit of padding to your text boxes and buttons, and set in stone your border color to a soft gray. In particular, most browsers will render a clean rectangular button with this style present. Consider defining a width in pixels or percents (if inside a container) as well.</p>
<p><strong>2. Styling Tables</strong><br />
Remember to style tables nicely, with table row hover colors, reasonable borders and maybe even striped tables. After all, tables can be dull and boring:</p>
<table border="1">
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
</tr>
<tr>
<td>Value</td>
<td>Value</td>
</tr>
<tr>
<td>Value</td>
<td>Value</td>
</tr>
</table>
<p>There are two key areas to this: using semantic markup, and taking advantage of CSS selectors. Let&#8217;s first fix up our table HTML:</p>

<div class="wp_syntax"><div class="code"><pre>&lt;table border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td&gt;Heading 1&lt;/td&gt;
&lt;td&gt;Heading 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</pre></div></div>

<p>And then add some styles:</p>

<div class="wp_syntax"><div class="code"><pre class="css">table <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">border-collapse</span><span style="color: #66cc66;">:</span> <span style="color: #993333;">collapse</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #66cc66;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#CCC</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">font-size</span><span style="color: #66cc66;">:</span> <span style="color: #933;">12px</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
table thead td <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">font-weight</span><span style="color: #66cc66;">:</span> <span style="color: #993333;">bold</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #66cc66;">:</span> <span style="color: #cc00cc;">#E1E1E1</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
table tbody tr<span style="color: #3333ff;">:hover</span> td <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #66cc66;">:</span> <span style="color: #cc00cc;">#F3F3F3</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
table td <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #66cc66;">:</span> <span style="color: #933;">5px</span> <span style="color: #933;">10px</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>First, notice the use of border collapse - this prevents the blocky double-borders on cells. Next, we take advantage of our &lt;thead&gt; and &lt;tbody&gt; to apply a background color to our header row, but a hover effect on body rows. The :hover is on the table row, but the actual background needs to be applied to the cell. Finally, we add a neat padding that keeps text in order. A smaller font size on your table will also cut it down to size and fit more figures on a page.</p>
<p><strong>3. Button Links</strong><br />
Often you want a button-style link to execute a simple action or lead the user to another page. Let&#8217;s create a simple &#8220;Next&#8221; link with this markup:</p>

<div class="wp_syntax"><div class="code"><pre>&lt;a href=&quot;#&quot; class=&quot;button&quot;&gt;Next &amp;raquo<SEMI>&lt;/a&gt;</pre></div></div>

<p>We can then style it nicely with this CSS:</p>

<div class="wp_syntax"><div class="code"><pre class="css">a<span style="color: #6666ff;">.button</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #66cc66;">:</span> <span style="color: #cc00cc;">#AAA</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">color</span><span style="color: #66cc66;">:</span> <span style="color: #cc00cc;">#FFF</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #66cc66;">:</span> <span style="color: #933;">3px</span> <span style="color: #933;">5px</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
a<span style="color: #6666ff;">.button</span><span style="color: #3333ff;">:hover</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #66cc66;">:</span> <span style="color: #cc00cc;">#<span style="color: #933;">888</span></span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>We first set a simple background color on the anchor to make it stand out, and ensure the text is still visible. However, feedback is important here - by adding a simple hover color, we make it clear that this is an interface element and not some ordinary link.</p>
<p><strong>4. Typography</strong><br />
It isn&#8217;t hard to use simple, clean text on your pages, as opposed to the serif-heavy fonts IE and Firefox will default to on Win/Linux. Try adding this to your main stylesheet:</p>

<div class="wp_syntax"><div class="code"><pre class="css">body <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">font-family</span><span style="color: #66cc66;">:</span> Arial<span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">font-size</span><span style="color: #66cc66;">:</span> <span style="color: #933;"><span style="color: #933;">95</span>%</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>Arial isn&#8217;t terribly fantastic, but it isn&#8217;t too bad either. (Verdana is also a standard option.) By explicitly setting a font here, you avoid leaving at the mercy of the browser/OS, especially when you may not have testing machines of a particular OS available (e.g. OS X).</p>
<p>With all these techniques in play, we have a nice and usable interface:</p>
<p><img src="http://www.developertutorials.com/blog/wp-content/uploads/2008/07/css-2.png" alt="" title="CSS After" width="166" height="166" class="alignnone size-full wp-image-390" /></p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d391" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/&amp;title=Four+CSS+Tricks+Every+PHP+%2F+Web+Developer+Should+Know" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/&amp;title=Four+CSS+Tricks+Every+PHP+%2F+Web+Developer+Should+Know" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/&amp;title=Four+CSS+Tricks+Every+PHP+%2F+Web+Developer+Should+Know" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/four-css-tricks-every-php-web-developer-should-know-391/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Parallel web scraping in PHP: cURL multi functions</title>
		<link>http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/</link>
		<comments>http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 13:00:43 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/</guid>
		<description><![CDATA[For anyone who&#8217;s ever tried to fetch multiple resources over HTTP in PHP, the logic is trivial, but one key challenge is ever-present: latency delays. While web servers have perfectly good downstream links, latencies can increase script execution time tenfold just by downloading a few external URLs. But there&#8217;s a simple solution: parallel cURL operations. [...]]]></description>
			<content:encoded><![CDATA[<p>For anyone who&#8217;s ever tried to fetch multiple resources over HTTP in PHP, the logic is trivial, but one key challenge is ever-present: latency delays. While web servers have perfectly good downstream links, latencies can increase script execution time tenfold just by downloading a few external URLs. But there&#8217;s a simple solution: parallel cURL operations. In this tutorial, I&#8217;ll show you how to use the &#8220;multi&#8221; functions in PHP&#8217;s cURL library to get around this quickly and easily.<span id="more-375"></span></p>
<p>Caching alleviates the latency issue to some extent, but retrieving more than a few files is always going to be a problem, and, well, <a href="http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/">sometimes users just can&#8217;t wait</a>. cURL&#8217;s parallel processing allows you to fire off multiple requests at a time and handle responses as they arrive, instead of linear operations - waiting for each request to complete (or worse, time out) before starting the next.</p>
<p>Consider this basic cURL example:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000033;">$ch</span> <span style="color: #339933;">=</span> curl_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;http://example.com/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$data</span> <span style="color: #339933;">=</span> curl_exec<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
curl_close<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>This will fetch the initial resource of http://example.com/ and put the data (the HTML) in <code>$data</code>. If we wanted to do this multiple times, we could use a simple <code>for</code> loop around this code block and repeat. However, through this method script execution time increases are linear, proportionate to the latencies of each network request, and latencies of 50-100ms x 10 requests don&#8217;t help when you barely spend &lt;10ms executing all your PHP code.</p>
<p>Instead, we&#8217;ll use cURL&#8217;s parallel processing system. This requires a bit of a context shift - instead of running each operation, you now have to tell cURL all the operations to run, let it do it&#8217;s stuff, and then continue on once it has finished. The difference is that it doesn&#8217;t wait for each request - it runs them all simultaneously (network permitting). Here&#8217;s a basic example:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// Create two cURL handlers</span>
<span style="color: #000033;">$ch1</span> <span style="color: #339933;">=</span> curl_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000033;">$ch2</span> <span style="color: #339933;">=</span> curl_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set options on both</span>
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch1</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;http://example.com/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch2</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;http://example2.com/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch1</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_setopt<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch2</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$mh</span> <span style="color: #339933;">=</span> curl_multi_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_multi_add_handle<span style="color: #009900;">&#40;</span><span style="color: #000033;">$mh</span><span style="color: #339933;">,</span><span style="color: #000033;">$ch1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_multi_add_handle<span style="color: #009900;">&#40;</span><span style="color: #000033;">$mh</span><span style="color: #339933;">,</span><span style="color: #000033;">$ch2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$running</span><span style="color: #339933;">=</span><span style="color: #000000; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
    curl_multi_exec<span style="color: #009900;">&#40;</span><span style="color: #000033;">$mh</span><span style="color: #339933;">,</span><span style="color: #000033;">$running</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$running</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000033;">$data1</span> <span style="color: #339933;">=</span> curl_multi_getcontent<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000033;">$data2</span> <span style="color: #339933;">=</span> curl_multi_getcontent<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
curl_multi_remove_handle<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_multi_remove_handle<span style="color: #009900;">&#40;</span><span style="color: #000033;">$ch2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
curl_multi_close<span style="color: #009900;">&#40;</span><span style="color: #000033;">$mh</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Here, we first create a cURL connection object for each request we want to make - an array of these is perfectly acceptable - and set the options on each. Instead of <code>curl_init()</code>, we then call <code>curl_multi_init()</code> and point the library at each of our connection objects. We have to cede control from cURL at this point: <code>curl_multi_exec()</code> now runs all the sub-connections of the current cURL object - that is, <code>$ch1</code> and <code>$ch2</code>.</p>
<p>The <code>curl_multi_exec()</code> function takes a second parameter, a reference to a flag of whether operations are still running. When that parameter - for us, <code>$running</code> - is 0, cURL&#8217;s finished taking care of requests and we can proceed. Timeouts are the only concern - remember to set the timeout option to a reasonable value to avoid being held up by requests that won&#8217;t complete.</p>
<p>As you increase in requests, however, remember that the next bottleneck you will hit is memory. Given PHP&#8217;s memory_limit flag (especially on shared servers), you can actually hit this quicker than you think. cURL can&#8217;t read part of a file or stream, even if it&#8217;s packet-based. Ever seen <code>fread($handle, 8192)</code>? The second parameter results in 8KB chunks, avoiding memory limits elegantly. cURL, however, will simply collect up all your request responses: if you hit your memory limit, you either get a fatal error or a &#8220;white screen of death&#8221;. Consider parallel cURL-ing in <a href="http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/">a background process</a>. Also, these simple routines can get quite lengthy - consider building an abstraction layer for your app/framework, to maintain an array of cURL connection objects and interface requests.</p>
<p>Parallel HTTP requests in cURL are quick and easy, despite the architectural differences with libraries for single-threaded cURL. To learn more, just check out the detailed documentation on the <a href="http://php.net/manual/en/function.curl-multi-exec.php">PHP manual page</a>.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d375" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/&amp;title=Parallel+web+scraping+in+PHP%3A+cURL+multi+functions" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/&amp;title=Parallel+web+scraping+in+PHP%3A+cURL+multi+functions" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/&amp;title=Parallel+web+scraping+in+PHP%3A+cURL+multi+functions" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Debugging PHP with Firebug and FirePHP</title>
		<link>http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/</link>
		<comments>http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 09:00:32 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/</guid>
		<description><![CDATA[FirePHP is a plugin for Firebug, the web development plugin for Firefox, that allows PHP scripts to talk to a Firebug panel. FirePHP installs alongside Firebug, and provides a simple PHP library to bridge the two. FirePHP provides a window of insight into your PHP applications, with a simple debugging interface that won&#8217;t interfere with [...]]]></description>
			<content:encoded><![CDATA[<p>FirePHP is a plugin for Firebug, the web development plugin for Firefox, that allows PHP scripts to talk to a Firebug panel. FirePHP installs alongside Firebug, and provides a simple PHP library to bridge the two. FirePHP provides a window of insight into your PHP applications, with a simple debugging interface that won&#8217;t interfere with your page content. If you already use Firebug on PHP-powered applications, FirePHP is definitely worth a look. Here&#8217;s a quick guide to getting started.<span id="more-365"></span></p>
<p>FirePHP is implemented as a native Firefox extension, and is available from <a href="https://addons.mozilla.org/en-US/firefox/addon/6149">Mozilla Addons</a>. After a basic setup procedure, you can start printing everything from status messages to multi-dimensional arrays straight to your Firebug console. FirePHP achieves this using extension HTTP headers - in particular, X-FirePHP-Data headers in the response.</p>
<p>The PHP library provides a function, <code>fb()</code>, which handles sending data across to the client side. From here, you simply open up your Firebug console, and your data is displayed in a highly functional manner.</p>
<p>To get started with FirePHP, grab the extension from <a href="https://addons.mozilla.org/en-US/firefox/addon/6149">Mozilla Addons</a> and the core library from the <a href="http://www.firephp.org/" target="_blank">FirePHP project page</a> (the &#8220;Download&#8221; link). You&#8217;ll need to install Firebug first, then the FirePHP Firefox addon. Next we get to the PHP library - either add the &#8220;FirePHPCore&#8221; folder to somewhere in your include_path, or just pop it into your script directory, and include it:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FirePHPCore/fb.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Remember to change the relative path as required (no pun intended). Then, simply call the <code>fb()</code> function anywhere in your code, passing a single argument - the info you want to send to your FirePHP console. Here are some examples:</p>

<div class="wp_syntax"><div class="code"><pre class="php">fb<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'The value of $var is '</span><span style="color: #339933;">.</span><span style="color: #000033;">$var</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fb<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Just logging this event.'</span><span style="color: #339933;">,</span>FirePHP<span style="color: #339933;">::</span><span style="color: #990000;">LOG</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fb<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Error in the email module.'</span><span style="color: #339933;">,</span>FirePHP<span style="color: #339933;">::</span><span style="color: #004000;">ERROR</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fb<span style="color: #009900;">&#40;</span><span style="color: #000033;">$_SERVER</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'$_SERVER array'</span><span style="color: #339933;">,</span> FirePHP<span style="color: #339933;">::</span><span style="color: #990000;">LOG</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
try <span style="color: #009900;">&#123;</span>
  throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Exception'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch<span style="color: #009900;">&#40;</span>Exception <span style="color: #000033;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  fb<span style="color: #009900;">&#40;</span><span style="color: #000033;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see, we can output basic messages, use Firebug&#8217;s standard styles to identify message importance (also, INFO and WARN), output labelled assocative arrays, and even debug exceptions - FirePHP will display a neat little stack trace.</p>
<p>Remember that this information is sent via headers, so it needs to be output before any of your HTML. If you&#8217;re using a framework with view templates, this is probably not an issue, but otherwise, you can get around the problem by using output buffering. Just run this line somewhere near the beginning of your script execution:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This will initialise output buffering, so that any HTML you output is held up till the end of script execution (or till the next call to <code>ob_flush()</code> and derivatives). Calling the <code>fb()</code> function will then work fine any time before the end of your script, as the headers will be flushed immediately. (Alternatively you can use <code>php_flag output_buffering on</code> in your .htaccess / apache virtual host configuration.)</p>
<p>FirePHP has all sorts of neat tips and tricks - just check out the <a href="http://www.firephp.org/Wiki/Main/QuickStart">quick start guide</a> and <a href="http://www.firephp.org/Wiki/Reference/Protocol">protocol reference</a>. If you use the Zend Framework, have a look at the <a href="http://www.firephp.org/Wiki/Libraries/ZendFramework" target="_blank">Zend library for FirePHP</a>; similar libraries exist for Symfony and Prado as well.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d365" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/&amp;title=Debugging+PHP+with+Firebug+and+FirePHP" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/&amp;title=Debugging+PHP+with+Firebug+and+FirePHP" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/&amp;title=Debugging+PHP+with+Firebug+and+FirePHP" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/debugging-php-with-firebug-and-firephp-365/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Running background processes in PHP</title>
		<link>http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/</link>
		<comments>http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 10:00:14 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/</guid>
		<description><![CDATA[So you&#8217;ve just built a fantastic processing routine for your application. You&#8217;ve checked and double checked the integrity of user input, and you&#8217;re doing some serious processing. There&#8217;s only one problem: it&#8217;s too slow. There&#8217;s a simple solution: forking your processing script, and running the code as a background process asynchronously. It can email your [...]]]></description>
			<content:encoded><![CDATA[<p>So you&#8217;ve just built a fantastic processing routine for your application. You&#8217;ve checked and double checked the integrity of user input, and you&#8217;re doing some serious processing. There&#8217;s only one problem: it&#8217;s too slow. There&#8217;s a simple solution: forking your processing script, and running the code as a background process asynchronously. It can email your user when it&#8217;s done: they&#8217;ll wait. In this tutorial, I&#8217;ll show you how to get started with background processes in PHP.<span id="more-349"></span></p>
<p>When we want some kind of background process running our PHP code, we have a simple challenge: we can&#8217;t leave it up to the client. On the web, people hit their stop button, their browsers lock up and they force quit, they even have the odd power outage. When we want to do complex processing on the server side, we need to detach from the client-server model of a web-served script. PHP can fork a script, but the parent script is still facing an unreliable client.</p>
<p>Our best option, then, is to launch a background process from the command line. There are three steps to this: starting the background script, passing it information to do its job, and checking when it&#8217;s finished.</p>
<p><strong>Starting the background script</strong><br />
On UNIX systems, we can easily call another PHP script via the shell, set it to run off in the background and send its output to /dev/null. Here&#8217;s a sample:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #990000;">exec</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/usr/bin/php proc.php &gt;/dev/null &amp;#038;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Here, we call the <code>exec</code> function; instructing it to run our local PHP binary - usually at /usr/bin/php or /usr/local/bin/php, check with your host/sysadmin. We pass it a single argument: the filename of the PHP script that handles our background process. We then send the output to /dev/null, effectively destroying it. The last character, the &amp; symbol, is important - this tells the system to start this process in the background and to let us continue.</p>
<p><strong>Talking to the background process</strong><br />
It&#8217;s all very well to start a background process, but now it needs to know what to do. We handle this through command line arguments. Let&#8217;s update the previous example:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #990000;">exec</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/usr/bin/php proc.php --task=50 &gt;/dev/null &amp;#038;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Our proc.php file might look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;Handling process &quot;</span><span style="color: #339933;">.</span><span style="color: #000033;">$argv</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Running &#8220;php proc.php &#8211;task=50&#8243; on command line produces the following output:</p>
<pre>Handling process --task=50</pre>
<p>From here, you can easily design your script to do what it needs to.</p>
<p><strong>Monitoring the background process</strong><br />
There&#8217;s just one last detail: how do we monitor the progress of our background process? It&#8217;s best to use an independent datastore that can be relied upon, instead of communicating with running threads - your application&#8217;s MySQL database would be perfect. You can create a &#8220;sessions&#8221; or &#8220;jobs&#8221; table with an ID column, a status column (started, in progress, finished - 0, 1, 2), and any other information you need. Before you start your background process, create a new entry in this table and check the insert ID, then pass it to the background process when you start it:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #990000;">exec</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/usr/bin/php proc.php --some_info=50 --job=1234 &gt;/dev/null &amp;#038;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Your proc.php file can then update the table row with the ID you supply it, and your front end applications can provide status updates to end users by checking up on all pending jobs for the current user - relatively straightforward business logic.</p>
<p>If you&#8217;re going to be running many background processes, a job queue and an &#8220;always-on&#8221; script running on your server may also be an option. In this case, consider looking into <a href="http://php.net/pcntl_fork">pcntl_fork()</a> and the <a href="http://www.developertutorials.com/php-manual/ref.exec.html">program execution functions</a>.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d349" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/&amp;title=Running+background+processes+in+PHP" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/&amp;title=Running+background+processes+in+PHP" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/&amp;title=Running+background+processes+in+PHP" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/running-background-processes-in-php-349/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SimpleTest: Unit Testing for PHP</title>
		<link>http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/</link>
		<comments>http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 14:00:06 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/</guid>
		<description><![CDATA[We recently looked at front-end testing of web applications with Selenium. Today, we&#8217;ll take another approach to testing your PHP applications: backend unit testing for your actual PHP code. As part of our posts on test driven development, here&#8217;s a quick intro to using SimpleTest to test your PHP applications.
SimpleTest is a PHP unit testing [...]]]></description>
			<content:encoded><![CDATA[<p>We recently looked at <a href="http://www.developertutorials.com/blog/web/selenium-ide-front-end-web-application-testing-322/">front-end testing of web applications with Selenium</a>. Today, we&#8217;ll take another approach to testing your PHP applications: backend unit testing for your actual PHP code. As part of our posts on test driven development, here&#8217;s a quick intro to using SimpleTest to test your PHP applications.<span id="more-332"></span></p>
<p><a href="http://simpletest.org/" target="_blank">SimpleTest</a> is a PHP unit testing and web testing framework along the lines of <a href="http://www.junit.org/">JUnit</a> and JWebUnit. It provides a comprehensive set of APIs for testing everything from your class methods to your SSL-secured authentication pages.</p>
<p>Unit testing in PHP generally validates that individual sections of your source code are functioning as expected. As your project grows, it&#8217;s hard to remember what each and every module is responsible for, especially with multiple developers. Unit tests help check that a function or method does what it&#8217;s meant to, and when run during a build process or around version control commits, can check that recent changes haven&#8217;t broken expected functionality.</p>
<p>Let&#8217;s look at a simple SimpleTest example:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SIMPLE_TEST'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'simpletest/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span>SIMPLE_TEST <span style="color: #339933;">.</span> <span style="color: #0000ff;">'autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'arithmetic_class.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> TestOfArithmetic <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">function</span> TestOfArithmetic<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000033;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">UnitTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Test of Arithmetic'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> testAddition<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000033;">$arithmetic</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Arithmetic<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000033;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$arithmetic</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000033;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>SimpleTest provides PHP classes that serve as the ground work for unit testing. When we define a new unit test case - in this case, &#8220;TestOfArithmetic&#8221;, SimpleTest automatically works out what tests you&#8217;ve defined in order to run them. We then simple create new methods for our tests, run whatever logic we need, and use assert calls to check that we have achieved our expected outcome. In this case, we want to assert that the return value of Arithmetic::add(1, 1) equals 2.</p>
<p>This may seem rather lengthy for a single test, but additional tests can be added on in as little as a single line of code, and an entire application can be quickly checked for reliability with just a few hundred lines of unit tests. Once this is in place, we can run our unit tests by loading up this script in our browser, and if everything is in order, we see a nice and concise status page displaying the results of the tests.</p>
<p>Of course, why write tests after you write your application code, when you could write it sooner and sooner, and maybe even before? That&#8217;s the approach of test driven development (TDD) - SimpleTest is perfectly happy with writing tests for code that doesn&#8217;t exist yet. TDD, from one of the guys who created Extreme Programming (XP), basically involves writing tests to define the design of code, and then working away at the code till it passes the tests, and SimpleTest is a great way to achieve it in PHP.</p>
<p>SimpleTest is hosted on SourceForge, so <a href="http://sourceforge.net/projects/simpletest">head over and try it out</a>. They&#8217;ve also got <a href="http://simpletest.org/en/first_test_tutorial.html">a great tutorial</a> on their <a href="http://simpletest.org/">main project site</a>.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d332" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/&amp;title=SimpleTest%3A+Unit+Testing+for+PHP" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/&amp;title=SimpleTest%3A+Unit+Testing+for+PHP" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/&amp;title=SimpleTest%3A+Unit+Testing+for+PHP" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/simpletest-unit-testing-for-php-332/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting Started with ORM in PHP</title>
		<link>http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/</link>
		<comments>http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 13:00:00 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/</guid>
		<description><![CDATA[ORM, or Object Relational Mapping, is a database design approach that simplifies managing complex databases for programmers. Instead of direct database access, an ORM layer in a PHP framework can make &#8220;objects&#8221; stored in a database behave like actual objects from a programming perspective - for example, creating a new &#8220;car&#8221; stored in the database [...]]]></description>
			<content:encoded><![CDATA[<p>ORM, or Object Relational Mapping, is a database design approach that simplifies managing complex databases for programmers. Instead of direct database access, an ORM layer in a PHP framework can make &#8220;objects&#8221; stored in a database behave like actual objects from a programming perspective - for example, creating a new &#8220;car&#8221; stored in the database could involve a call to <code>$car->new()</code>. By abstracting actual database access, web development can be more productive and result in more reliable applications. Here&#8217;s a quick intro to ORM in PHP.<span id="more-331"></span></p>
<p>ORM brings data closer to a programming paradigm, where actual information is stored and accessed through interfaces that resemble actual objects. In PHP frameworks, this is typically achieved through the framework providing classes representing database information, that can then be manipulated as actual objects such as a car or a booking. This is almost always a level above actual database operations - when using an ORM layer, writing actual SQL queries is taken care of, although an understanding of how to is always helpful.</p>
<p>Let&#8217;s consider a simple database, consisting of users and posts. ORM defines relationships between objects (and in general, also between tables) where an object either has one or has many of another object. For example, a post might have one author, while an author would have many posts. By adding foreign keys to the actual database, and defining these simple relationships (usually hard-coded), an ORM layer can take care of working with related data.</p>
<p><a href="http://cakephp.org/">CakePHP</a>&#8217;s ORM layer is possibly one of the most used ORM layers of any PHP framework, and is a good example of how a simple ORM implementation should function. In Cake, when an author model is defined as having many posts, any calls to fetch a particular author will automatically fetch all posts related to that author. The entire database logic is taken care of, and instead of thinking in terms of SQL queries, we get to think in terms of actual objects.</p>
<p><a href="http://www.symfony-project.org/">Symfony</a> also has quite a nice ORM layer, although the symfony implementation is a little more hands-off, based around database design conventions and it&#8217;s YAML schema file approach. But you don&#8217;t need to be using a PHP framework to take advantage of ORM; the <a href="http://www.phpdoctrine.org/">Doctrine</a> project provides a powerful ORM layer that can be implemented on its own or within an MVC framework. Doctrine also provides an object-oriented SQL-like language to write database queries - the Doctrine Query Language is is great for complex object retrieval. <a href="http://propel.phpdb.org/trac/">Propel</a> is another popular option, and is actually the ORM layer behind Symfony.</p>
<p>At the end of the day, ORM provides a fundamental advantage over writing raw SQL queries: it&#8217;s designed to retrieve information, not record sets. While thinking about data in terms of objects is a major paradigm shift from hands-on PHP scripting, it&#8217;s a great way to deal with the challenge of complex databases. So what are you waiting for? Grab <a href="http://cakephp.org/">a</a> <a href="http://www.symfony-project.org/">framework</a> or <a href="http://www.phpdoctrine.org/">a</a> <a href="http://propel.phpdb.org/trac/">library</a>, and dive in to the world of ORM.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d331" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/&amp;title=Getting+Started+with+ORM+in+PHP" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/&amp;title=Getting+Started+with+ORM+in+PHP" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/&amp;title=Getting+Started+with+ORM+in+PHP" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/getting-started-with-orm-in-php-331/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Load testing your web application with Apache Bench</title>
		<link>http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/</link>
		<comments>http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 04:00:26 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/</guid>
		<description><![CDATA[Often you need solid metrics on the performance of your web application. Benchmarking your website can provide insight into which sections of your application might need major optimizations, and helps in dealing with scalability issues. Apache Bench, or &#8216;ab&#8217;, is a command line load testing utility which ships with Apache, and allows you to simulate [...]]]></description>
			<content:encoded><![CDATA[<p>Often you need solid metrics on the performance of your web application. Benchmarking your website can provide insight into which sections of your application might need major optimizations, and helps in dealing with scalability issues. Apache Bench, or &#8216;ab&#8217;, is a command line load testing utility which ships with Apache, and allows you to simulate load on a web server. In this tutorial, I&#8217;ll show you how to get started with ab.<span id="more-316"></span></p>
<p>If you have an Apache installation locally, you&#8217;ve probably got ab already. Check your path - just run `ab`. Otherwise, head to your apache/bin folder. If you&#8217;re running Windows and don&#8217;t have Apache, grab a copy of XAMPP Lite from <a href="http://www.apachefriends.org/en/xampp-windows.html#646" target="_blank">the project page</a>.</p>
<p>The ab executable is independent of Apache, and doesn&#8217;t actually care if it&#8217;s testing an Apache installation - ab will load test Apache web servers, LigHTTPD servers, anything that speaks HTTP. Still, ab will give the most accurate results when run without latency on a local server, and you probably don&#8217;t want to load-test on a production server. Given this, it&#8217;s best to setup Apache and your application locally as a staging server, then load test it with ab.</p>
<p>Work out the path to your ab executable - for example, mine&#8217;s D:\dev\apache\bin\ab.exe - and open up a command line window to run it.</p>
<blockquote><pre>D:\dev\apache\bin\>ab
ab: wrong number of arguments
Usage: ab [options] [http[s]://]hostname[:port]/path
Options are:
    -n requests     Number of requests to perform
    -c concurrency  Number of multiple requests to make
    -t timelimit    Seconds to max. wait for responses
    -p postfile     File containing data to POST
    -T content-type Content-type header for POSTing
    -v verbosity    How much troubleshooting info to print
    -w              Print out results in HTML tables
    -i              Use HEAD instead of GET
    -x attributes   String to insert as table attributes
    -y attributes   String to insert as tr attributes
    -z attributes   String to insert as td or th attributes
    -C attribute    Add cookie, eg. 'Apache=1234. (repeatable)
    -H attribute    Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
                    Inserted after all normal header lines. (repeatable)
    -A attribute    Add Basic WWW Authentication, the attributes
                    are a colon separated username and password.
    -P attribute    Add Basic Proxy Authentication, the attributes
                    are a colon separated username and password.
    -X proxy:port   Proxyserver and port number to use
    -V              Print version number and exit
    -k              Use HTTP KeepAlive feature
    -d              Do not show percentiles served table.
    -S              Do not show confidence estimators and warnings.
    -g filename     Output collected data to gnuplot format file.
    -e filename     Output CSV file with percentages served
    -h              Display usage information (this message)
    -Z ciphersuite  Specify SSL/TLS cipher suite (See openssl ciphers)
    -f protocol     Specify SSL/TLS protocol (SSL2, SSL3, TLS1, or ALL)
</pre>
</blockquote>
<p>Calling ab without arguments will display this list of options. We are primarily interested in -n and -c. The -n switch represents the number of requests to perform - a figure in the low thousands is generally appropriate for a web application. The -c switch represents concurrency, or how many requests to make at the same time. This value can vary depending on what you expect for your application.</p>
<p>Work out a URL to an average page of your web application. For example, I&#8217;m load testing a local CakePHP application, so my URL is http://cake.local/users/list. Call ab as follows:</p>
<blockquote><pre>ab -n 1000 -c 10 http://cake.local/users/list</pre>
</blockquote>
<p>If you need to use a proxy (e.g. for testing remote servers), use the -X switch, in the format -X proxyhost:proxyport e.g. -X proxy.local:3128.</p>
<p>After displaying some status reports every 100 requests or so, it will print out a fairly detailed report, including document length, bytes transferred, completed and failed requests, requests per second and some statistics on connection times.</p>
<p>For further information, check out <a href="http://httpd.apache.org/docs/2.2/programs/ab.html">the documentation page for ab</a>.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d316" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/&amp;title=Load+testing+your+web+application+with+Apache+Bench" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/&amp;title=Load+testing+your+web+application+with+Apache+Bench" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/&amp;title=Load+testing+your+web+application+with+Apache+Bench" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/load-testing-your-web-application-with-apache-bench-316/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Benchmarking PHP frameworks</title>
		<link>http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/</link>
		<comments>http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 12:00:15 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/</guid>
		<description><![CDATA[Over on the AVNet Labs blog, Ekerete Akpan has posted a few results from his recent framework benchmarks to much controversy. His tests covered a few major PHP frameworks, such as CodeIgniter, CakePHP and Zend Framework, along with baseline results for serving static HTML and procedural PHP versions of the same page. He also covered [...]]]></description>
			<content:encoded><![CDATA[<p>Over on the AVNet Labs blog, Ekerete Akpan has posted a few results from his recent framework benchmarks to much controversy. His tests covered a few major PHP frameworks, such as CodeIgniter, CakePHP and Zend Framework, along with baseline results for serving static HTML and procedural PHP versions of the same page. He also covered some basic Ruby on Rails, including Passenger (mod_rails?) and Ruby Enterprise. Here are some of his more interesting findings.<span id="more-315"></span></p>
<p>After running the tests on a production grade box, he recorded these basic results, without any caching in place.</p>
<table>
<tr>
<td></td>
<td>Run 1</td>
<td>Run 2</td>
<td>Run 3</td>
<td>Run 4</td>
<td>Average</td>
</tr>
<tr>
<td>Baseline HTML</td>
<td>3431.2</td>
<td>3311.8</td>
<td>3427.7</td>
<td>3395.0</td>
<td>3391.4</td>
</tr>
<tr>
<td>Baseline PHP</td>
<td>1912.1</td>
<td>1932.3</td>
<td>1983.3</td>
<td>1911.3</td>
<td>1934.7</td>
</tr>
<tr>
<td>CakePHP</td>
<td>15.6</td>
<td>15.6</td>
<td>15.6</td>
<td>15.6</td>
<td>15.6</td>
</tr>
<tr>
<td>CodeIgniter</td>
<td>83.5</td>
<td>83.0</td>
<td>82.0</td>
<td>83.2</td>
<td>82.9</td>
</tr>
<tr>
<td>Zend Framework</td>
<td>34.7</td>
<td>34.6</td>
<td>34.6</td>
<td>34.6</td>
<td>34.6</td>
</tr>
</table>
<p>Some basic indications are obvious - frameworks create massive overheads, with hefty overall performance costs. Per these results, using CakePHP over a static HTML site was 226 times slower. CodeIgniter fared the best, at about 40 times slower, while the Zend Framework was somewhere in between.</p>
<p>While the actual numbers may be surprising, how each framework fared in relation to the others is not.</p>
<p>All of these frameworks provide levels of abstraction, taking care of many common tasks and moving the logic away from the developer&#8217;s application. Each framework offers a varying level of this &#8220;hand holding&#8221;, and it&#8217;s generally accepted that CakePHP leads the race in this area. By making more assumptions and relying on more default behaviours, Cake will always have a far greater overhead.</p>
<p>CodeIgniter, on the other hand, is far more efficient in what it does - but doesn&#8217;t do as much. An application built on CodeIgniter will always be more efficient than one built in Cake, but development time will be considerably longer.</p>
<p>Another interesting area to note was ORM - Cake&#8217;s inbuilt ORM layer couldn&#8217;t be reasonably &#8220;disabled&#8221; to run benchmarks without the added overhead, and so the benchmark of frameworks without their ORM layer excluded Cake entirely. Ekerete also notes that CodeIgniter doesn&#8217;t have much of an ORM implementation, possibly leading to its vastly increased performance over the other frameworks.</p>
<p>However, the final point to consider was caching. The performance (measured in requests per second) of CodeIgniter and Zend Framework increased by about 4x when the eAccelerator cache was used. On the other hand, Cake&#8217;s requests per second figure barely doubled, suggesting that Cake&#8217;s architecture imposes some limitations on the performance gains achievable through caching. With eAccelerator, CodeIgniter was serving over ten times as many requests per second than Cake.</p>
<p>In the end, the choice is really up to the developer. If your applications tend to grow in complexity very quickly, your choice of framework (or language, for that matter) will be increasingly irrelevant. On the other hand, if you&#8217;re building small applications, CakePHP will clearly save you time in development, CodeIgniter will offer massive performance benefits, and Zend will give you a reasonable middle ground.</p>
<p>Check out <a href="http://www.avnetlabs.com/php/php-framework-comparison-benchmarks">the post on AVNet Labs</a> for more details.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d315" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/&amp;title=Benchmarking+PHP+frameworks" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/&amp;title=Benchmarking+PHP+frameworks" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/&amp;title=Benchmarking+PHP+frameworks" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/benchmarking-php-frameworks-315/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Phing: A build system for PHP</title>
		<link>http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/</link>
		<comments>http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/#comments</comments>
		<pubDate>Thu, 26 Jun 2008 11:44:05 +0000</pubDate>
		<dc:creator>Akash Mehta</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/</guid>
		<description><![CDATA[As PHP applications grow in size and complexity of structure, developers often find themselves putting together a &#8220;deployment plan&#8221; - that is, a set of steps to go through each time they want to take the code and package, deploy or test it. This process could involve creating some deployment-specific configuration files, packaging up the [...]]]></description>
			<content:encoded><![CDATA[<p>As PHP applications grow in size and complexity of structure, developers often find themselves putting together a &#8220;deployment plan&#8221; - that is, a set of steps to go through each time they want to take the code and package, deploy or test it. This process could involve creating some deployment-specific configuration files, packaging up the code, storing the current state in version control, even setting up the database. <a href="http://phing.info/">Phing</a> is a build system for PHP, based on <a href="http://ant.apache.org/">Apache Ant</a>, that aims to automate many of these processes and simplify application deployment for PHP developers.<span id="more-249"></span></p>
<p>Phing uses XML files to define automated build processes. Each buildfile includes some basic information about the project, and then a series of tasks. XML tags represent each task - for example, an &lt;copy file=&#8221;&#8230;&#8221; tofile=&#8221;&#8230;&#8221;&gt; is used for a file copy operation. Here&#8217;s a sample extract from one of these buildfiles:</p>

<div class="wp_syntax"><div class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="font-weight: bold; color: black;">?&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;project</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;FooBar&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;dist&quot;</span> <span style="color: #000066;">basedir</span>=<span style="color: #ff0000;">&quot;.&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;prepare&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;echo</span> <span style="color: #000066;">msg</span>=<span style="color: #ff0000;">&quot;Making directory ./build&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;mkdir</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;./build&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/target<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;build&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;prepare&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;echo</span> <span style="color: #000066;">msg</span>=<span style="color: #ff0000;">&quot;Copying files to build directory...&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;copy</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;./about.php&quot;</span> <span style="color: #000066;">tofile</span>=<span style="color: #ff0000;">&quot;./build/about.php&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/target<span style="font-weight: bold; color: black;">&gt;</span></span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/project<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></div></div>

<p>Phing comes with quite a few tasks built in out of the box, such as file operations, PHPUnit and Subversion tasks, compression tasks and even a ZendCodeAnalyzer operation to analyse source files with the Zend Code Analysis tool. Phing is also extendible with PHP classes, and has access to the command line, giving it virtually limitless possibilities in what can be done during a build process.</p>
<p>Build systems like Phing are well suited to larger projects, where continuous integration is important. With Phing, your application can be prepared and built overnight, ready to test in the morning and saving hours of hacking around with deployment or one-liner install scripts. Some systems, Apache Ant especially, even integrate with IDEs - for example, some scripts can be run from within Zend Studio for Eclipse at the click of a button.</p>
<p>Getting started with Phing is easy; the project has a PEAR channel for quick and easy download, as well as <a href="http://phing.info/docs/guide/current/">thorough documentation</a> covering every area of the system. PHPUnit, XDebug and PhpDocumentor can also be installed for added functionality, such as the inbuilt unit testing system. If you&#8217;re working on a sizable project and could use some decent automated build tools, head over to the <a href="http://phing.info/trac/">Phing website</a> for more details.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark" style="float:left;">
<div class="d249" style="overflow:hidden">
<div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/&amp;title=Phing%3A+A+build+system+for+PHP" title="Add to&nbsp;Del.icio.us">Del.icio.us</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/&amp;title=Phing%3A+A+build+system+for+PHP" title="Add to&nbsp;Digg This">Digg This</a></div><div id="socialstyles"><a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit.php?url=http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/&amp;title=Phing%3A+A+build+system+for+PHP" title="Add to&nbsp;Stumble">Stumble</a></div></div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.developertutorials.com/blog/php/phing-a-build-system-for-php-249/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
