<?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>Brian Bell &#187; PHP</title>
	<atom:link href="http://webguru.org/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://webguru.org</link>
	<description>Bits of web-dev, travel and personal musings...</description>
	<lastBuildDate>Mon, 09 Nov 2009 21:36:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to use Google Charts API in your Secure, HTTPS webpage</title>
		<link>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/</link>
		<comments>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 21:36:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google charts]]></category>
		<category><![CDATA[https]]></category>

		<guid isPermaLink="false">http://webguru.org/?p=42</guid>
		<description><![CDATA[So you love Google Charts API and want to spice up your app with lots of pretty bar charts, Venn diagrams, Google-o-meters and 2D bar codes (QR Codes) &#8211; only problem is, you require that users connect to your site using a secure connection (https://yoursite.com/whatever).  Well, as you are probably aware, the Google Charts [...]]]></description>
			<content:encoded><![CDATA[<p>So you love Google Charts API and want to spice up your app with lots of pretty bar charts, Venn diagrams, Google-o-meters and 2D bar codes (QR Codes) &#8211; only problem is, you require that users connect to your site using a secure connection (<strong>https</strong>://yoursite.com/whatever).  Well, as you are probably aware, the Google Charts API doesn&#8217;t ex</p>
<p>actly support SSL connections&#8230; directly.</p>
<p>Have no fear! If you are willing to give up a little bit of your own bandwidth, you can work around this problem.  We are going to do this using a simple PHP script and if you want to get really fancy, Memcached to keep the redundant API calls to a minimum.</p>
<p>Let&#8217;s get started.<br />
<span id="more-42"></span><br />
First, let&#8217;s make sure we understand why it is a problem to include a non-secure Google Charts API into your otherwise secure page.  When your users are browsing to your page using an address starting with <strong>https://</strong>, their browser is going to negotiate an TLS/SSL connection which will encrypt all the data flowing between your client and the server.  If any element on the page (image, external CSS or JavaScript, etc.) is not being called from a secured connection as well, then the browser will throw up a warning.  Each browser is different, but most will alert the user with a broken lock and/or a popup message.  The user can usually accept this warning and proceed at their own risk, but this is not acceptable for a production website or application.</p>
<p>The obvious answer to this problem is to make sure that all external elements on the page are loaded over a secure connection.  So &#8211; how do we do that with Google Charts? Google does not allow you to just take a traditional API call and slap a &#8220;https://&#8221; in front of it in lieu of the expected http://.  Your request will be <strong>denied</strong>.</p>
<h2>Basic Implementation</h2>
<p>Here&#8217;s what we do:</p>
<ol>
<li>Create a simple PHP script that will fetch a chart from Google Charts API</li>
<li>Change your web page to call the new PHP &#8220;fetcher&#8221; instead of Google Charts directly.</li>
<li>Make sure the PHP script is being called by your page over your https:// connection</li>
</ol>
<p>It is pretty much that simple.</p>
<p>Here is the before example:</p>
<pre class="brush: xml;">
&lt;!-- HTML snippet --&gt;
&lt;img src='http://chart.apis.google.com/chart?cht=p&amp;chd=s:Uf9a&amp;chs=200x100&amp;chl=January|February|March|April' alt='Pie Chart'/&gt;
</pre>
<p>Here is the after example:</p>
<pre class="brush: xml;">
&lt;!-- HTML snippet --&gt;
&lt;img src='https://mywebsite.com/gchart.php?api_url=http%3A%2F%2Fchart.apis.google.com%2Fchart%3Fcht%3Dp%26chd%3Ds%3AUf9a%26chs%3D200x100%26chl%3DJanuary%7CFebruary%7CMarch%7CApril' alt='Pie Chart'/&gt;
</pre>
<p>Notice, the same API URI is used in the &#8220;after&#8221; example, <strong>but it is URL Encoded</strong>.  This just makes it safer to pass along to the PHP script.</p>
<p>Here is the PHP script that makes this work:</p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);

$image_contents = file_get_contents($url);
echo $image_contents;
exit;
</pre>
<p>A quick note about this: you may be saying &#8211; where is your closing PHP tag!?!  Well, PHP doesn&#8217;t require that you have a closing PHP tag, as the PHP interpreter will automatically close any open tags.  I do this on just about every file that will be used as an include of some sorts &#8211; particularly in something like this where any extra, inadvertent white space at the end of the file can alter the output adversely and cause errors in the page.</p>
<h2>Advanced Implementation w/ Caching</h2>
<p>The script as it is above, is fine and dandy, but terribly inefficient.  You see, every time the user requests the page, your script is going out and using <strong>your bandwidth</strong> to make the request to the Google Charts API instead of the client.  You are becoming the proxy for all requests to and from Google Charts.  This will not fly &#8211; especially if you are in a high volume environment.</p>
<p>So what is the solution? I chose Memcache to store a copy of the image contents for a certain period of time before having to re-query the Charts API and re-fetch the data again.</p>
<p>It looks something like this:</p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);
$cache_key = md5($url);
$item_cache_expire = 3600;
$mc_host = '127.0.0.1';
$mc_port = 11211;

# Connect to Memcache
$memcache = new Memcache;
$memcache-&gt;connect($mc_host, $mc_port) or die (&quot;Could not connect&quot;);

if ( $get_result = $memcache-&gt;get($cache_key) ) {
    $image_contents = $get_result-&gt;chart_image;
}
else {
    $image_contents = file_get_contents($url);

    $tmp_object = new stdClass;
    $tmp_object-&gt;chart_image = $image_contents;

    $memcache-&gt;set($cache_key, $tmp_object, false, $item_cache_expire) or die (&quot;Failed to save data at the server&quot;);

}
echo $image_contents;
exit;
</pre>
<p>Here&#8217;s what is happening. </p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);
$cache_key = md5($url);
$item_cache_expire = 3600;
$mc_host = '127.0.0.1';
$mc_port = 11211;
</pre>
<p>Setup some variables we&#8217;ll need in the script.  Grab the api_url value from the GET array, create an MD5 hash of the request URL (we&#8217;ll use this as our memcache item key), set the expiration time of the cached item to 3600 seconds (a.k.a. 1 hour) and finally provide the connection information to your memecached server. </p>
<pre class="brush: php;">
# Connect to Memcache
$memcache = new Memcache;
$memcache-&gt;connect($mc_host, $mc_port) or die (&quot;Could not connect&quot;);
</pre>
<p>Instantiate a new Memcache object using the connection info provided above.</p>
<pre class="brush: php;">
if ( $get_result = $memcache-&gt;get($cache_key) ) {
    $image_contents = $get_result-&gt;chart_image;
}
else {
    $image_contents = file_get_contents($url);

    $tmp_object = new stdClass;
    $tmp_object-&gt;chart_image = $image_contents;

    $memcache-&gt;set($cache_key, $tmp_object, false, $item_cache_expire) or die (&quot;Failed to save data at the server&quot;);
}
</pre>
<p>Using the MD5 hash that we created above, check to see if there is a valid cached object on the memcache server for us to retrieve.  If not, go out and grab a fresh version from Google Charts API and stick it into memcache.  Either way, we end up with a variable $image_contents which contains the desired chart image.</p>
<pre class="brush: php;">
echo $image_contents;
exit;
</pre>
<p>All that is left to do now is print out the image contents and exit the script.  Again, I do not use a closing PHP tag on purpose to avoid extra whitespace.</p>
<h2>All ye, all ye, now hear this&#8230;</h2>
<p>This is a very basic example.  It should probably be categorized more as a proof of concept. It does NOT, I repeat &#8211; DOES NOT &#8211; take into account a variety of security concerns such as SQL injection or CSRF (cross-site request forgeries), etc. Notice that I didn&#8217;t even validate the user input from the GET variable.  Who does that!?!  So, in other words, don&#8217;t just copy and paste and then come back and blame me for getting your site hacked.  Be smart about employing something like this.</p>
<p>BTW, if you want to know more about how to make your PHP scripts more secure, go see Chris Shifflet&#8217;s excellent blog at <a href="http://shiflett.org/" target="_blank">http://shiflett.org/</a>.  </p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Object Get/Set Generator</title>
		<link>http://webguru.org/2009/04/17/php/php-object-getset-generator/</link>
		<comments>http://webguru.org/2009/04/17/php/php-object-getset-generator/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 21:49:23 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webguru.org/?p=39</guid>
		<description><![CDATA[Well, I know I haven&#8217;t created anything new here &#8211; but as Frank said, &#8220;I did it my way!&#8221;
I recently found myself creating more and more objects to store data within apps. I&#8217;m not going to get into all the ins and outs of why this is good practice, but it lead me to whipping [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I know I haven&#8217;t created anything new here &#8211; but as Frank said, &#8220;I did it my way!&#8221;</p>
<p>I recently found myself creating more and more objects to store data within apps. I&#8217;m not going to get into all the ins and outs of why this is good practice, but it lead me to whipping up this simple script. I had seen a few other similar tools on the inter-webs but none of them worked quite like I needed. </p>
<p>If you&#8217;e not familiar with the OO approach for storing data within a script (is there a better way to describe this?) here the gist. </p>
<p>Say you are storing user profile information in your favorite RDBMS. You have a user profile page and will pull data for a specific profile to use in that page. Well, instead of just doing a fetch and grabbing data &#8211; creating a bunch of variables, etc., you can take the OO approach. Load all those vars into an object, with nice features like getters and setters &#8211; which may manipulate the data, etc. Then you have a clean interface to the data. </p>
<p>My IDE doesn&#8217;t have any wizards for this stuff (I think Eclipse can &#8211; or has plugins that can) and it can be a bit time consuming to do. Also &#8211; its very repetitive to get your basic class structure together. SO &#8211; why not write a little script to do this! Like I said, I have seen some others out there that were apparently written for PHP4 or just didn&#8217;t format the methods like I prefer. </p>
<p>Check it out and let me know what you think.<br /> <a href="http://webguru.org/getset">http://webguru.org/getset</a></p>
<p>The resulting class allows you to do stuff like this:</p>
<pre class="brush: php;">
&lt;?php

// create an array of basic user data
$data = array();
$data[&quot;user_id&quot;] = 3;
$data[&quot;name&quot;] = &quot;Brian Bell&quot;;
$data[&quot;email&quot;] = &quot;brian@example.com&quot;;

$user = new UserDataObj( $data );
echo &quot;User {$user-&gt;get_name()} has an id of {$user-&gt;get_id()} and an email address of {$user-&gt;get_email()}. &quot;;

/*
  You can also instantiate the object with no argument,
  and set things manually
*/
$user = new UserDataObj();
$user-&gt;set_name(&quot;Brian Bell&quot;);
$user-&gt;set_email(&quot;brian@example.com&quot;);

// also comes in handy to pass the data object to your CrUD methods
$new = new Users();
/*
  pass in the data object from above so
  the create_user() method has everything it needs.
*/
$new-&gt;create_user( $user );

?&gt;
</pre>
<p>Let me know if you have any comments or suggestions. I don&#8217;t have a lot of time to contribute to it &#8211; but I can easily see how it could be extended to give the user some options on formatting, etc. </p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2009/04/17/php/php-object-getset-generator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memory-tight, multi-threaded PHP Daemon</title>
		<link>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/</link>
		<comments>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 15:49:02 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/</guid>
		<description><![CDATA[Came across this nifty project on Google Code.  It&#8217;s a multi-threaded, object-oriented PHP daemon which is very nicely written and easy to use.
http://code.google.com/p/phpmultithreadeddaemon/
Here&#8217;s their example of how to implement it.  Everything needed to run the daemon is in the single included file &#8220;class.MTDaemon.php&#8221; &#8211; cool!


&#60;?php

error_reporting(E_ALL);

require_once(include/class.MTDaemon.php);

class MTTest extends MTDaemon {

public function getNext($slot)
{
$this-&#62;lock();
$num = $this-&#62;getVar(&#34;num&#34;);
if [...]]]></description>
			<content:encoded><![CDATA[<p>Came across this nifty project on Google Code.  It&#8217;s a multi-threaded, object-oriented PHP daemon which is very nicely written and easy to use.</p>
<p><a href="http://code.google.com/p/phpmultithreadeddaemon/" title="PHP Daemon Project on Google Code">http://code.google.com/p/phpmultithreadeddaemon/</a></p>
<p>Here&#8217;s their example of how to implement it.  Everything needed to run the daemon is in the single included file &#8220;class.MTDaemon.php&#8221; &#8211; cool!</p>
<pre class="brush: php;">

&lt;?php

error_reporting(E_ALL);

require_once(include/class.MTDaemon.php);

class MTTest extends MTDaemon {

public function getNext($slot)
{
$this-&gt;lock();
$num = $this-&gt;getVar(&quot;num&quot;);
if ($num == null) $num = 1;
if ($num &gt; 100) {
$this-&gt;unlock();
return null;
}
$this-&gt;unlock();

$rand = rand(0, 5);
echo &quot;Next for slot &quot; . $slot . &quot; : &quot; . $rand . &quot;\n&quot;;
if ($rand == 0) return null;
else return $rand;
}

public function run($next, $slot)
{
$rand = rand(3, 10);
$this-&gt;lock();
$num = $this-&gt;getVar(&quot;num&quot;);
$this-&gt;setVar(&quot;num&quot;, $this-&gt;getVar(&quot;num&quot;) + 1);
$this-&gt;unlock();
echo &quot;## Iteration #&quot; . number_format($num) . &quot; in &quot; . $rand . &quot;sec&quot; . &quot;\n&quot;;

sleep($rand);
return 0;
}

}

$mttest = new MTTest(2);
$mttest-&gt;handle();

?&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to use PHP&#8217;s sprintf() on a MySQL query utilizing DATE_FORMAT()</title>
		<link>http://webguru.org/2008/08/02/php/how-to-use-phps-sprintf-on-a-mysql-query-utilizing-date_format/</link>
		<comments>http://webguru.org/2008/08/02/php/how-to-use-phps-sprintf-on-a-mysql-query-utilizing-date_format/#comments</comments>
		<pubDate>Sat, 02 Aug 2008 15:24:28 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webguru.org/2008/08/02/php/how-to-use-phps-sprintf-on-a-mysql-query-utilizing-date_format/</guid>
		<description><![CDATA[It is good practice (common sense?) to filter your SQL queries.  One way to accomplish this in PHP is to utilize a function like sprintf() which will format a given string and integrate values into the string using conversion specifications which are passed in as arguments to the function.  In plain english, that means you [...]]]></description>
			<content:encoded><![CDATA[<p>It is good practice (common sense?) to filter your SQL queries.  One way to accomplish this in PHP is to utilize a function like sprintf() which will format a given string and integrate values into the string using conversion specifications which are passed in as arguments to the function.  In plain english, that means you can call the function, pass in a value and require that value to be a integer, for example.  If the value you passed in is a string, roughly speaking, it will sanitize your output.</p>
<p>An example in a MySQL query would be this.</p>
<pre class="brush: php;">
&lt;?php
// build our sql string.
$sql = &quot;SELECT * FROM table WHERE field=%d&quot;;
$sqlf = sprintf( $sql, $somevalue );
$db-&gt;query($sqlf);
?&gt;
</pre>
<p>As you can see, you can designate where the substitution will take place in the $sql string.  That&#8217;s easy.  But what happens if you need to use MySQL&#8217;s DATE_FORMAT() function?  It requires that you pass in arguments to define its output (ie. Day as a word, day as a date, month as a number, etc).</p>
<pre class="brush: php;">
&lt;?php
// build our sql string.
$sql = &quot;SELECT DATE_FORMAT( %b %M %d %Y, some_date_field ) as myDate FROM table WHERE field=%d&quot;;
$sqlf = sprintf( $sql, $somevalue );
$db-&gt;query($sqlf);
?&gt;
</pre>
<p>This will fail.  sprintf() will complain because you haven&#8217;t passed in enough arguments.  It is expecting 5 values as part of the call, instead of just the one that you are trying to replace (in the SQL WHERE clause).</p>
<p>So what&#8217;s the solution? You have to &#8220;comment-out&#8221; the % that aren&#8217;t part of your sprintf() substitution.  You can do this by putting another % in front of the &#8216;%&#8217; symbols in the DATE_FORMAT() function.  This deems them as a literal percent-sign instead of the start of another sprintf() &#8220;variable&#8221;.</p>
<pre class="brush: php;">
&lt;?php
// build our sql string.
$sql = &quot;SELECT DATE_FORMAT( %%b %%M %%d %%Y, some_date_field ) as myDate FROM table WHERE field=%d&quot;;
$sqlf = sprintf( $sql, $somevalue );
$db-&gt;query($sqlf);
</pre>
<p>Hope that helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2008/08/02/php/how-to-use-phps-sprintf-on-a-mysql-query-utilizing-date_format/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>I may need protection from myself&#8230;</title>
		<link>http://webguru.org/2008/08/01/php/i-may-need-protection-from-myself/</link>
		<comments>http://webguru.org/2008/08/01/php/i-may-need-protection-from-myself/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 14:22:21 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webguru.org/2008/08/01/php/i-may-need-protection-from-myself/</guid>
		<description><![CDATA[Today, I spent almost an hour staring at this line of code:
if ($this-&#62;dbi-&#62;affectedRows&#62;0) {
Oh &#8211; and it would be helpful for you to know that affectedRows is a method in a database class.
A method, that&#8217;s right.  Unfortunately for me, method is not spelled, v-a-r-i-a-b-l-e.
Amazing what two little ( ) can do to your stress level.
if [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I spent almost an hour staring at this line of code:<br />
<code>if ($this-&gt;dbi-&gt;affectedRows&gt;0) {</code></p>
<p>Oh &#8211; and it would be helpful for you to know that affectedRows is a method in a database class.</p>
<p>A <em>method</em>, that&#8217;s right.  Unfortunately for me, method is not spelled, v-a-r-i-a-b-l-e.</p>
<p>Amazing what two little ( ) can do to your stress level.<br />
<code>if ($this-&gt;dbi-&gt;affectedRows<font color="#ff0000"><strong>()</strong></font>&gt;0) {</code></p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2008/08/01/php/i-may-need-protection-from-myself/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouble with PHP regular expression; REG_ERANGE error</title>
		<link>http://webguru.org/2007/11/29/php/trouble-with-php-regular-expression-reg_erange-error/</link>
		<comments>http://webguru.org/2007/11/29/php/trouble-with-php-regular-expression-reg_erange-error/#comments</comments>
		<pubDate>Thu, 29 Nov 2007 06:53:15 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webguru.org/2007/11/29/php/trouble-with-php-regular-expression-reg_erange-error/</guid>
		<description><![CDATA[I had a situation where I needed to validate an email address that included an apostrophe.  It is not widely known that the apostrophe (and a bunch of other symbols for that matter) are valid characters in the official RFC2822 specification for email address formats.
Anyway, I kept getting an error when I tried to [...]]]></description>
			<content:encoded><![CDATA[<p>I had a situation where I needed to validate an email address that included an apostrophe.  It is not widely known that the apostrophe (and a bunch of other symbols for that matter) are valid characters in the official RFC2822 specification for email address formats.</p>
<p>Anyway, I kept getting an error when I tried to add the apostrophe to my character classes in my regex.  It gave me a strange error referencing REG_ERANGE.  After some googling, I came across <a href="http://17thdegree.com/archives/2006/06/29/problems-with-regular-expressions-in-php/trackback/">this blog post</a> which led me to the answer.  The problem is related to the placement of the dash (&#8221;-&#8221;) character in the regex.</p>
<blockquote><p>
<strong>Example 1:</strong></p>
<pre class="brush: php;">
if (ereg(&quot;[^a-zA-Z0-9_-.]&quot;, $userid)) {
    echo 'bad';
}
else {
    echo 'good';
}
</pre>
<p>The problem? The dash, or hyphen, being before the period. It thinks it’s a range, like you see in a-z. This may not be a bug, per se, but it’s certainly not smart enough for me.</p>
<p>The solution? Simply put the dash at the end of the regex.</p>
<p><strong>Example 2:</strong></p>
<pre class="brush: php;">
if (ereg(&quot;[^a-zA-Z0-9_.-]&quot;, $userid)) {
    echo 'bad';
}
else {
    echo 'good';
}
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2007/11/29/php/trouble-with-php-regular-expression-reg_erange-error/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why I switched to a new IDE for PHP development</title>
		<link>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/</link>
		<comments>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/#comments</comments>
		<pubDate>Tue, 27 Nov 2007 16:09:09 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>
		<category><![CDATA[dreamweaver]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[nusphere]]></category>

		<guid isPermaLink="false">http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/</guid>
		<description><![CDATA[I've been using Dreamweaver for about 10 years in some form or fashion.  It actually started when I purchased Allaire HomeSite 3.0 in 1997.  Macromedia purchased Allaire in 2001 and eventually merged HomeSite with their Dreamweaver product.  Dreamweaver 8 is what I've been using for the past 2 years; that is, until I found PHP nirvana!

I have tried other IDE's off and on for the past 5 years - trying to get more of a Visual Studio experience.  I was really jealous of the code-completion and hinting features that were available in VS.  Dreamweaver does ok at basic function hints for PHP, but nothing I found did a great job of combining all the site management features of Dreamweaver with the intelligent code parsing (ie. reading my classes and adding them to the code-completion hints).   I've tried Eclipse with its PHP plug-in, UltraEdit, Zend Studio, phpDesigner and probably some others that I'm not listing.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Dreamweaver for about 10 years in some form or fashion.  It actually started when I purchased Allaire HomeSite 3.0 in 1997.  Macromedia purchased Allaire in 2001 and eventually merged HomeSite with their Dreamweaver product.  Dreamweaver 8 is what I&#8217;ve been using for the past 2 years; that is, until I found PHP nirvana!</p>
<p>I have tried other IDE&#8217;s off and on for the past 5 years &#8211; trying to get more of a Visual Studio experience.  I was really jealous of the code-completion and hinting features that were available in VS.  Dreamweaver does ok at basic function hints for PHP, but nothing I found did a great job of combining all the site management features of Dreamweaver with the intelligent code parsing (ie. reading my classes and adding them to the code-completion hints).   I&#8217;ve tried Eclipse with its PHP plug-in, UltraEdit, Zend Studio, phpDesigner and probably some others that I&#8217;m not listing.</p>
<div align='center'><img src="http://webguru.org/content/phped-workspace-thumb.png" alt="PhpED Workspace" width="550" /></div>
<p><span id="more-14"></span><br />
I can&#8217;t remember exactly when I first downloaded NuSphere PhpED for the first time; but recently I thought I&#8217;d give it yet another shot.  Man, was I surprised! I&#8217;m using version 5.2 and it is awesome.  It is the first time that I have what I consider to be a truly fully integrated development environment.  It has projects (who doesn&#8217;t), an SSH client, SFTP/FTP, intelligent code completion based on my classes, an excellent code navigator which details class methods &amp; variables, an integrated debugger with its own WAMP stack, server-side debugging (optional) and more!  </p>
<p>I can already tell after using it for a week that its going to save me a ton of time and help me write better code.  </p>
<p>Here are my top 5 features that I really love (in no particular order)&#8230;</p>
<ol>
<li><strong>Code Snippets:</strong> just type something like &#8220;func&#8221; and hit Ctrl+J to insert a full function block.  You can add whatever snippets you want and even choose where to place the cursor when it is inserted (crucial time saver and major annoyance avoider).</li>
<li><strong>Code/Variable completion:</strong> when you start typing a object it will provide you with all the available class methods along with their parameters.  It will auto-complete variable names with respect to the document scope, based on your cursor position.  In other words, if you&#8217;re working inside function it will know to only show you variables that were declared in that function or class-wide vars.</li>
<li><strong>Internal Debugger:</strong> you can step through your code and instantly see where there are problems without having to do the save, upload, open browser, check for error dance.</li>
<li><strong>Extremely customizable:</strong> I was quickly able to modify the keyboard shortcuts to what I was used to using in Dreamweaver.</li>
<li><strong>Integrated SSH client:</strong> I love PuTTY just as much as the next person, but how cool is it that you can have a shell open in a tab right next to the document you&#8217;re working on.</li>
</ol>
<p>The only downside is that NuSphere PhpED is not F/OSS.  I paid $199 for the professional version; but really &#8211; that isn&#8217;t bad compared to Dreamweaver &#8211; and it&#8217;s proving to be an awesome tool for my purposes.</p>
<p>What are you using?</p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
