<?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>Proffer&#039;s Ramblings &#187; programming &#8211; PHP</title>
	<atom:link href="http://johnproffer.com/category/programming-php/feed/" rel="self" type="application/rss+xml" />
	<link>http://johnproffer.com</link>
	<description>Development Blog</description>
	<lastBuildDate>Sat, 28 Aug 2010 15:54:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>New Business</title>
		<link>http://johnproffer.com/2009/10/new-business/</link>
		<comments>http://johnproffer.com/2009/10/new-business/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 23:54:55 +0000</pubDate>
		<dc:creator>John Proffer</dc:creator>
				<category><![CDATA[programming - PHP]]></category>

		<guid isPermaLink="false">http://johnproffer.com/?p=88</guid>
		<description><![CDATA[I&#8217;ve started a new business along with 2 good friends.  We&#8217;ll be churning about about 10 products, including 2 hardware products and numerous iPhone applications.
Going to be crazy busy for a while, since I also work for a company in DC, writing a very large, very complicated web application (SOA).  I&#8217;m the only developer for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started a new business along with 2 good friends.  We&#8217;ll be churning about about 10 products, including 2 hardware products and numerous iPhone applications.</p>
<p>Going to be crazy busy for a while, since I also work for a company in DC, writing a very large, very complicated web application (SOA).  I&#8217;m the only developer for that company, so definitely have my work cut out for me <img src='http://johnproffer.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />   It&#8217;s a great company though &#8211; love working with them &#8211; they&#8217;re a small business, very down to earth and dont take themselves too seriously.</p>
<p>As for my business, it&#8217;s called 3 Guys Lab, www.3GuysLabcom (nothing really there yet since we just started it).  3GL will be developing a number of applications that can serve many different business markets simultaneously, targeting both local and international markets.  We&#8217;ll also be writing some very specialized products.  Unfortunately cant list those due to their specialized nature.  Stealth mode and all that <img src='http://johnproffer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://johnproffer.com/2009/10/new-business/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic SEO Keyword Generation from Dynamic Content</title>
		<link>http://johnproffer.com/2009/05/page-seo/</link>
		<comments>http://johnproffer.com/2009/05/page-seo/#comments</comments>
		<pubDate>Mon, 04 May 2009 12:22:23 +0000</pubDate>
		<dc:creator>John Proffer</dc:creator>
				<category><![CDATA[programming - PHP]]></category>

		<guid isPermaLink="false">http://johnproffer.com/?p=48</guid>
		<description><![CDATA[I wrote this over a year ago now &#8211; it was my first attempt at automatic meta compilation based on dynamic page content. It was geared towards sites that needed some basic SEO, but didnt want to hire a SEO professional.  It does a pretty good job, but it can definitely be improved upon [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote this over a year ago now &#8211; it was my first attempt at automatic meta compilation based on dynamic page content. It was geared towards sites that needed some basic SEO, but didnt want to hire a SEO professional.  It does a pretty good job, but it can definitely be improved upon and I plan to do just that sometime soon (when I have time, smile)</p>
<p>But thought I&#8217;d put what I wrote &#8220;out there&#8221; for anyone interested in it.  You&#8217;d call it by initializing the class just after the &lt;HTML&gt; tag, feed it any forced keyword priority (if so desired), and call $yourobj->GenSEO at the end of the page (after &lt;/HTML&gt;).  The class will read your content, determine popular keywoards (with priority towards &lt;H#&gt; tags) and generate meta keyword, title, and description.</p>
<pre class="brush: php;">
  class SEO {
        private $kwarray = array();
        private $words = array();
        private $common = array();
        private $top = array();

        public $desc=&quot;META KEYWORD SEO v1.0&quot;;
        public $title=&quot;PROFFER WAS HERE!&quot;;

        public function __construct() {
              ob_start();
              $this-&gt;Add(&quot;to be or not the them they was were have has had saw a go my mine you your yours our ours theirs of with without within she he his hers him her shall&quot;);
              $this-&gt;Add(&quot;should could would might probably an be does being ought been did going that than also yes no maybe etc get through if any also me b c d e f g h i j k&quot;);
              $this-&gt;Add(&quot;l m n o p q r s t u v w x y z as in by am do we some which here it went goes from is are and for st rd nd th one two three four five six seven eight nine&quot;);
              $this-&gt;Add(&quot;ten its at what how where why this can can zero will now on put when put see non said let each way new call end use try used tried lie lied may need more&quot;);
              $this-&gt;Add(&quot;want all common next just such like done using&quot;);
      }
      public function GenSEO($data,$max=20,$meta=FALSE) {
            $specialitems=array();
            for ($i=1; $i&lt;6; $i++) {
                preg_match_all(&quot;/&lt;[Hh]{$i}[^&gt;]*&gt;(.*?)&lt;\/[Hh]{$i}&gt;/&quot;,$data,$specials,PREG_SET_ORDER);
                if (count($specials)&gt;0) {
                    for ($j=0; $j&lt;count($specials); $j++) { $specialitems[$specials[$j][1]]=15; }
            }
          }
              $this-&gt;words=$specialitems;
            $_d = preg_replace(&quot;/&amp;amp;|&amp;quot;|&amp;copy;|&amp;nbsp;|&amp;dash;|&amp;lt;|&amp;gt;|=|\+|\&lt;|\&gt;|\r|\n|\t|\[|\]|\/|\(|\)|,|\||\.|\*|\%|\$|\d{1,99}|\'|\&quot;|:|\?|\!|\@|\-|\&lt;97&gt;|;|_/i&quot;,&quot; &quot;,strip_tags($data));
            $_d = preg_split(&quot;/\s|$/i&quot;,$_d,-1,PREG_SPLIT_NO_EMPTY);

            for ($i=0; $i&lt;count($_d); $i++) {
                  $word=strtolower($_d[$i]);
                  if (!$this-&gt;common[$word]) { $this-&gt;words[$word]++; }
          }
          array_multisort($this-&gt;words,SORT_DESC);
          $this-&gt;top=array_slice($this-&gt;words,0,$max);
          $top = array_keys($this-&gt;top);

          if ($meta) {
          $meta = &quot;&lt;meta name=\&quot;keywords\&quot; content=\&quot;&quot;.implode(&quot;, &quot;,$top).&quot;\&quot; /&gt;\r\n&quot;;
          $desc = &quot;&lt;meta name=\&quot;description\&quot; content=\&quot;{$this-&gt;desc}\&quot; /&gt;\r\n&quot;;
          echo &quot;
              &lt;HEAD&gt;
                  &lt;TITLE&gt;{$this-&gt;title}&lt;/TITLE&gt;
                  $meta
                  $desc
              &lt;/HEAD&gt;
              $data
          &quot;;
          } else {
                echo &quot;Top $max:&lt;HR&gt;&quot;.implode(&quot;&lt;BR&gt;&quot;,$top).&quot;&lt;hr&gt;&quot;;
          }
      }
      public function Add($e) {
            $s = preg_split(&quot;/\s/i&quot;,$e,-1,PREG_SPLIT_NO_EMPTY);
            foreach ($s as $e) {
                $this-&gt;common[$e]=TRUE;
            }   

      }
      public function Force($word,$score) { $this-&gt;words[$word]=$score; }
  };
</pre>
<p>You&#8217;re free to use this code under the terms of the <a href='http://www.gnu.org/licenses/gpl-3.0.txt' target='blank'>GPL v3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnproffer.com/2009/05/page-seo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>LUHN Algorithm</title>
		<link>http://johnproffer.com/2009/03/luhn-algorithm/</link>
		<comments>http://johnproffer.com/2009/03/luhn-algorithm/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 19:57:50 +0000</pubDate>
		<dc:creator>John Proffer</dc:creator>
				<category><![CDATA[programming - PHP]]></category>

		<guid isPermaLink="false">http://johnproffer.com/?p=36</guid>
		<description><![CDATA[Recently I was chatting with a friend on creditcard validation.  He was looking for ways to validate a creditcard via javascript.    While it&#8217;s certainly possible, and there&#8217;s alot of sample code out there for it,  I just cant bring myself to use any kind of client-side process for verification of [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was chatting with a friend on creditcard validation.  He was looking for ways to validate a creditcard via javascript.    While it&#8217;s certainly possible, and there&#8217;s alot of sample code out there for it,  I just cant bring myself to use any kind of client-side process for verification of what in my opinion is crucial information such as creditcard numbers.</p>
<p>For one, you can disable javascript, which may bypass validation entirely (depending on how the form submit is being handled).  For another, you could, with the right Firefox plugins, just edit the javascript function directly in the page and have it return &#8220;true&#8221; to get a successful submission.  So I was giving him some sample sites utilizing PHP LUHN algorithms, and noticed something interesting &#8211; As with the javascript versions, most of them don&#8217;t work or have flaws that haven&#8217;t been fixed.   One must wonder how many people out there are copy/pasting these buggy versions for use in professional websites.  </p>
<p>I decided to dig up my own LUHN algorithm, and did some tweaks to it before posting it here. It&#8217;s 100% operational, and so far I&#8217;ve been unable to produce any false results with it. </p>
<pre class="brush: php;">
    function IsValidCC($cc) {
	$cc=str_replace(&quot;-&quot;,&quot;&quot;,$cc);
        for($i = strlen($cc); $i &gt;=0; --$i) {
            $dnum .= ($odd = !$odd) ? $cc[$i]*2 : $cc[$i];
        }
        for($i = 0; $i &lt; strlen($dnum); $i++) {
            $sum += (int)$dnum[$i];
        }
        return (($sum % 10 ==0) &amp;&amp; ($sum != 0));
    }
</pre>
<p>Without alot of dramatic analysis of its inner workings and so on, here are the numbers I tested with, their results, and the processing time for the entire bunch.</p>
<p>Validating 55 numbers</p>
<p>true  [5328304431046754]<br />
true  [5103312845585953]<br />
true  [5310941494599177]<br />
true  [5502457933980793]<br />
true  [5526386293832793]<br />
true  [5541030109388076]<br />
true  [5160933962299217]<br />
true  [5516418411392004]<br />
true  [5202598727749606]<br />
true  [5319527039331431]<br />
true  [4539642231959702]<br />
true  [4916962068349733]<br />
true  [4556574648962060]<br />
true  [4556389698328918]<br />
false [4916971931396181]<br />
false [4485099272362583]<br />
true  [4929771078260656]<br />
true  [4532940023485978]<br />
true  [4156763252772170]<br />
true  [4916726708254888]<br />
true  [4929857283556]<br />
true  [4539778019847]<br />
true  [4024007176858]<br />
true  [4556449022851]<br />
true  [4716337992272]<br />
true  [340315629019234]<br />
true  [371245491835627]<br />
true  [348410551014014]<br />
false [374973107447824]<br />
true  [343837789734937]<br />
true  [6011337931905012]<br />
true  [6011750581974742]<br />
true  [6011625028562351]<br />
true  [36673333924894]<br />
true  [30326629585715]<br />
true  [30036607370614]<br />
true  [201463953817936]<br />
false [201466327996032]<br />
true  [201473001172531]<br />
true  [180090307342009]<br />
true  [180045216543949]<br />
true  [210005131596400]<br />
true  [3088574904967422]<br />
true  [3528446407813882]<br />
true  [3158631681355554]<br />
true  [869940964429408]<br />
true  [869953540433067]<br />
true  [869965600155299]<br />
false [10]<br />
false [55]<br />
false [0]<br />
false [-1]<br />
false [-5-5]<br />
false [abcde]<br />
false []</p>
<p><b>Processing time: 0.00612s</b></p>
<p>Not bad, if you ask me. <img src='http://johnproffer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://johnproffer.com/2009/03/luhn-algorithm/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>more updates coming!</title>
		<link>http://johnproffer.com/2009/03/more-updates-coming/</link>
		<comments>http://johnproffer.com/2009/03/more-updates-coming/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 15:58:27 +0000</pubDate>
		<dc:creator>John Proffer</dc:creator>
				<category><![CDATA[programming - PHP]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[moving on]]></category>
		<category><![CDATA[problem]]></category>

		<guid isPermaLink="false">http://johnproffer.com/?p=30</guid>
		<description><![CDATA[Been crazy the past couple of weeks. Work&#8217;s kept me pretty busy..  But, have alot more time now that I dropped a potential partnership which was chewing up whatever free time I had in evenings / weekends.  The guy did nothing but blow alot of hot air and continiously emphasize that he was smarter [...]]]></description>
			<content:encoded><![CDATA[<p>Been crazy the past couple of weeks. Work&#8217;s kept me pretty busy..  But, have alot more time now that I dropped a potential partnership which was chewing up whatever free time I had in evenings / weekends.  The guy did nothing but blow alot of hot air and continiously emphasize that he was smarter than me.  After all, he&#8217;s a self-proclaimed &#8220;marketing genius&#8221;.</p>
<p>But, I won&#8217;t shrink to his level. So, enough of that &#8211; moving on.</p>
<p>Soon I&#8217;ll start updating this page with code snippets I&#8217;ve written to solve various issues. I&#8217;ll also start touching up my whitepaper skills. Been a while since I&#8217;ve written one <img src='http://johnproffer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   One of my favorite pasttimes is research &amp; development.  Taking a real-world problem, analyzing it, and finding solutions to that problem.</p>
<p>So if anyone has a PHP, C++, or AS3 problem they&#8217;d like solved, shoot me an email, jproffer at gmail dot com and I&#8217;ll take a crack at it and post the results here.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnproffer.com/2009/03/more-updates-coming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatically Loading Classes &amp; Modules in PHP</title>
		<link>http://johnproffer.com/2009/03/module-loading-routine/</link>
		<comments>http://johnproffer.com/2009/03/module-loading-routine/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 23:13:08 +0000</pubDate>
		<dc:creator>John Proffer</dc:creator>
				<category><![CDATA[programming - PHP]]></category>
		<category><![CDATA[autoload]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://johnproffer.com/?p=3</guid>
		<description><![CDATA[Any serious developer will tell you, __autoload is your friend.  It greatly reduces your application&#8217;s memory footprint in complex web applications by only loading classes when they&#8217;re actually needed, and can take the pain out of adding new features.  This is especially useful in MVC framework development.
That said, while working on my own [...]]]></description>
			<content:encoded><![CDATA[<p>Any serious developer will tell you, <a href="http://php.net/__autoload">__autoload</a> is your friend.  It greatly reduces your application&#8217;s memory footprint in complex web applications by only loading classes when they&#8217;re actually needed, and can take the pain out of adding new features.  This is especially useful in MVC framework development.</p>
<p>That said, while working on my own MVC framework (not public, sorry! <img src='http://johnproffer.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> ), I came across the need to keep a structured directory and recursively and selectively load certain file types.  While  __autoload can be coded to load files recursively as well as from multiple locations (I&#8217;ll cover that in a later blog post), there&#8217;s serious disadvantages &#8211; the biggest one being that your classes cannot raise exceptions, not without implementing an ugly eval() hack.</p>
<p>Instead I wrote a loader which recursively loads files based on an easily maintainable path/filter array (which I place in my MVC&#8217;s conf/config.php file):</p>
<p><strong>config.php:</strong></p>
<pre class="brush: php;">
$_inc_paths = array(
         &quot;Libraries&quot; =&gt; array(LIB_PATH,&quot;lib_*.php&quot;),
         &quot;Controllers&quot; =&gt; array(CTL_PATH, &quot;*_controller.php&quot;),
         &quot;Utilities&quot; =&gt; array(ROOT_PATH.&quot;/app/utils&quot;, &quot;*.php&quot;)
);
</pre>
<p>Next, since this is a MVC framework and everything is being passed through index.php, we define and execute our load routine here:</p>
<p><strong>index.php:</strong></p>
<pre class="brush: php;">
/**
* @desc Dependency loader routine
* @var $path - absolute path to check
* @var $filter - file filter
* @return none
*/

function LoadRecursively($path,$filter) {
    // include any files matching our filters
    $_inc_list=glob(&quot;$path/$filter&quot;);
    foreach ($_inc_list as $_inc_file) {
        if (substr(basename($_inc_file),0,4)==&quot;lib_&quot;) {
                define(&quot;api_&quot;.basename($_inc_file),TRUE);
        }
        require_once($_inc_file);
    }

    // then scan for any subdirectories
    $_inc_dirlist=glob($path.&quot;/*&quot;, GLOB_ONLYDIR);
    if (!empty($_inc_dirlist)) {
        // if we find subdirs, do recursion and repeat cycle.
        foreach ($_inc_dirlist as $dir) {
                LoadRecursively($dir,$filter);
        }
    }
}

foreach ($_inc_paths as $name=&amp;gt;$obj) {
    LoadRecursively($obj[0],$obj[1]);    // func(path, filter)
}
</pre>
<p>The routine isnt really anything original or ingenious. It&#8217;s basically the same algorithm you&#8217;d use to recursively search for files in most applications.  You&#8217;ll also probably notice the <a href='http://php.net/define'>define()</a> line in my code:</p>
<pre class="brush: php;">
        if (substr(basename($_inc_file),0,4)==&quot;lib_&quot;) {
                define(&quot;api_&quot;.basename($_inc_file),TRUE);
        }
</pre>
<p>It&#8217;s not absolutely necessary, and can be removed.  I use it to prevent people from direct-linking to my library files or using them inappropriately.  The library files have a line like this at the top of the file, which checks if the api_* is defined and throws an exception if not, preventing the file from being parsed and the class loaded:</p>
<pre class="brush: php;">defined(&quot;api_lib_sanitizer.php&quot;) or die(&quot;Error: Cannot call lib_sanitize directly!&quot;);</pre>
<p>Now, some of you purists will probably say, <em>&#8220;this is not a good way to do it (loading files recursively), you could wind up using tons of memory!  It&#8217;s not very scalable!&#8221;</em>  &#8212; well, yes and no.  First off, if you have so many files and each one is so large, you&#8217;re OBVIOUSLY doing something wrong.  Very wrong <img src='http://johnproffer.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Secondly, hardware is cheap these days. Especially with the emergence of <a href="http://aws.amazon.com/ec2/">cloud</a> <a href="http://www.rackspacecloud.com/">computing</a>.  As long as you code efficiently, use proper naming conventions and load based on the appropriate conventions, you should never run into a memory/speed issue.</p>
<p>Case in point:  My current MVC framework implements media management (image scaling, video conversion, thumbnail generation), db (including master/slave scaling), various security features including encryption and token generation, captcha, SEO, sanitization, gmaps, error handling, template management, xml handlers and zip handlers, yet uses only 1.5mb total memory footprint (including php and apache process overhead) per connection.  Load time is 0.002s on average, on an AMD x2 64 running Ubuntu 9.04, Apache 2.2 and PHP 5.3.</p>
<p>You&#8217;re free to use this code under the terms of the <a href='http://www.gnu.org/licenses/gpl-3.0.txt' target='blank'>GPL v3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnproffer.com/2009/03/module-loading-routine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
