tag:blogger.com,1999:blog-67937745330957664862024-02-18T18:05:43.368-08:00The PHP Coder's Judy ChopPHP Optimization, Coding Standards, Cookie Information, Sessions, Mobile, Off Site Hack Attacks, etc...Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-6793774533095766486.post-45704089141633893432010-01-14T18:19:00.001-08:002010-01-14T18:20:31.586-08:00The PHP Coder's Judy Chop gets a new home!This blog will now live at <a href="http://www.phpadvocate.com">http://www.phpadvocate.com</a>.Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-80030901848351159762010-01-11T20:13:00.000-08:002010-01-12T07:00:07.317-08:00Simple Optimizing Tips for PHP Part IV - By Example (Part I)Ss we write PHP code (or any language for that matter) we begin to start thinking about optimizing code. But even though our intentions are for "the greater good", we sometimes miss things that should be obvious.<br /><br />Today's article takes a look at:<br /><br /><span style="font-size:130%;">By Example</span><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiesbm3cuOmYrjkS77NcYIoiseYVQ1LikAtkbzXFsETlAcfdx_gXbIsE73a6uvFgQO2ZdQqH5-jqYWs0loYBrsAlyU2jjXs_vXjo4mPffXk4W9ghgXpHAyPyMr-lNvzYD_114_Fiiqi5a3/s1600-h/symbol-coding-example.jpg"><img style="margin: 0px 10px 10px 0px; width: 287px; float: left; height: 320px;" id="BLOGGER_PHOTO_ID_5425725957280705794" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiesbm3cuOmYrjkS77NcYIoiseYVQ1LikAtkbzXFsETlAcfdx_gXbIsE73a6uvFgQO2ZdQqH5-jqYWs0loYBrsAlyU2jjXs_vXjo4mPffXk4W9ghgXpHAyPyMr-lNvzYD_114_Fiiqi5a3/s320/symbol-coding-example.jpg" border="0" /></a><br /><div>All developers progress at their own rate. As we progress, a few things that become evident is the existence of built-in php functions that can replace many of our own custom code, simply because we didn't know any other way. We also learn how to see repetition in our code and how to simplify it, when we should separate functionality into their own functions (or even classes!), and also just *know* when something will or will not work from personal experience. During this phase in life, we're becoming a senior developer.<br /><br />Before we get to this point though, we are intermediate developers. Intermediate developers (in my honest opinion) is where a LOT of innovation comes from. It's from this level of developer that they are exploring PHP's full potential and how to exploit it to their benefit. When we are reaching the end of intermediate level and are looking to become the senior level developer on our team, we begin to try to search for ways to better ourselves as a developer. Unfortunately, such tutorials are very scarce and hard to find.<br /><br />This tutorial is not to be the end-all be-all, but it is intended to help an intermediate find that next level. And we do this by examples.<br /><br />Since even simple examples can lead to a book's worth of information, I plan to break this 4th part of <a href="http://coderjudychop.blogspot.com/search/label/Simple%20Optimizing%20Tips%20for%20PHP">Simple Optimizing Tips for PHP</a> into sub parts. This will help reduce the amount of time it takes you to read this article, but also not try to slam too much information into your brain. Please keep in mind that while some of these examples won't exactly speed php's performance up, they will instead inadvertently teach you new methods and in turn try to warp your mind into a more sophisticated developer.<br /><br />So without further ado, let's begin!<br /><br />Our first example is the following function:<br /><br /><pre><br />function multi_array_search($search_value, $the_array)<br />{<br /> if (is_array($the_array))<br /> {<br /> foreach ($the_array as $key => $value)<br /> {<br /> $result = multi_array_search($search_value, $value);<br /> if (is_array($result))<br /> {<br /> $return = $result;<br /> array_unshift($return, $key);<br /> return $return;<br /> }<br /> elseif ($result == true)<br /> {<br /> $return[] = $key;<br /> return $return;<br /> }<br /> }<br /> return false;<br /> }<br /> else<br /> {<br /> if ($search_value == $the_array)<br /> {<br /> return true;<br /> }<br /> else return false;<br /> }<br />}<br /></pre><br /><br />This function is perfectly valid, and works exactly as intended. However, there are a few things that one should notice right away:<br />1) The spacing and tabing of the data is not lined up nor consistant, making it hard to read.<br /><br />2) The function is not taking advantage of the typehints that are now available in php 5.<br /><br />3) Some of the code is a bit long and can be reduced to smaller lines without obfuscating the code.<br /><br />4) The naming of some of the variables could be redefined to make understanding their purpose easier.<br /><br />4) There exists absolutely no commenting in this function to explain it's purpose.<br /><br />5) The possible return value is either boolean (true AND false) OR array!<br /><br />6) The 2 parts of this function (the first if and the following else statements) could be refactored to make more sense and be more useful.<br /><br />So now that we know this, how can we make this function better? Here is a revised, optomized solution.<br /><pre><br />/**<br />* @author John Doe<br />*<br />* Takes an array and searching for a value within.<br />*<br />* @param string $search_value<br />* @param array $search_array<br />* @return boolean // Returns true if a search value found, false if not.<br />*/<br />function multi_array_search($search_value, array $search_array) {<br /> $search_result = false;<br /> foreach($search_array as $key => $value) {<br /> if(is_array($value)) {<br /> # We have an array, so let's recursively search the subarray values<br /> $search_result = multi_array_search($search_value, array_unshift($value));<br /> } else {<br /> # We have a string, so let's compare and see if we have a match<br /> if($value == $search_value) return true;<br /> }<br /> }<br /> return $search_result;<br />}<br /></pre><br /><br />Notice that we are using the recursive method that was explained in my <a href="http://coderjudychop.blogspot.com/2009/11/simple-optomizing-tips-for-php-part-ii.html">second tutorial</a> on recursively looping through arrays. Also, we are now only returning a boolean value from this point on. In the case that we find a value, we return only a true, otherwise (and by default) we return false.<br /><br />Now the above may or may not run faster (I haven't exactly run a test on this), but it is more simple, less code, and more understandable with comments that guide the way.<br /><br />For the second part of <a href="http://coderjudychop.blogspot.com/2010/01/simple-optimizing-tips-for-php-iv-by.html">By Example</a>, we will be looking at redundant functionality and definitions, and learn how to better adjust our code to be more useful rather than bloated.</div>Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-66498285738115848902009-12-24T08:35:00.000-08:002009-12-28T09:41:52.596-08:00Progressive Upload with PHP and APC<p>A year or two ago, I was given the task to make a Progress Bar work with PHP. From my own research a few years ago, this task was impossible and so I thought I would need some sort of Flash + Javascript + PHP combination to make this happen.</p><p>Until now.<br /></p><p>I found a nice recipe from IBM that actually makes this process much simpler. It's by using a simple PECL extension called Alternative PHP Cache (APC for short). This brilliantly simple extension allows us to FINALLY be able to monitor file upload progress! I read the tutorial and right away, I was throwing my fists into the air: it's finally possible to do progress bars with PHP WITHOUT THE NEED OF CGI !!!!<br /></p><p>For anyone who has ever run into this issue, you are probably the only ones to truly respect this awesome new toy. What's even more bizarre is that this functionality has been out since PHP 5.2 and this is truly the first I've ever heard about it.<br /></p><p>My problems though soon caught up with me. Apparently IBM's little "tutorial" is a little short-winded and doesn't exactly cover all the bases that are needed to make this new extension work. So, being the great guy I am, I decided to write a step-by-step tutorial on how to use this for the weak at heart.</p>==========================================================<br /><p>*** INSTALLATION ***</p>First, you need to get the APC module. There are 2 downloads available:<strong><br /></strong><a href="http://pecl.php.net/package/APC">Linux</a> and <a href="http://pecl4win.php.net/download.php/ext/5_2/5.2.1/php_apc.dll">Windows</a><br /><br />* Please note that the Windows link above may be broken as the team is trying to move this box over to a new server... *<br /><br />Next, you need to Install the modue.<br /><br /><span style="FONT-WEIGHT: bold">-- FreeBSD/Linux Users only --</span><br />First things first: you'll need root to make all this work, so su into the root user.<br /><p>After downloading the APC package (I downloaded the 3.0.18 stable bundle), you need to unpackage it. Once you have untar'ed the file, you need to cd into the apc directory and run the following set of commands:<br /></p><pre>phpize<br />./configure --enable-apc --enable-mmap<br />make install<br />cp modules/apc.so /usr/local/lib/php/<br /></pre>The phpize command is used to prepare the build environment for a PHP extension. If you don't have phpize installed, you will want to do so via RPM, ports, or whatever method your nix distro supports.<br /><p>Here are some commands for a few linux distros:</p><strong>Fedora Core x:</strong><br /><pre>yum -y install php-devel</pre><strong>Gentoo </strong><a href="http://www.gentoo.org/proj/en/php/php-upgrading.xml">Click here for the gentoo quick guide</a><br /><p><strong>FreeBSD </strong>Installed by default with PHP</p>I can't cover them all, but these 3 seem to be the most popular (along with Ubuntu but I'm not familiar with it)<br /><p>Next, you'll need to open the php.ini file to make a few quick changes.</p><pre>vi /usr/local/etc/php.ini</pre>Locate where the Windows Extensions are loaded (yes I know you aren't using Winblows, but you'll see what I'm getting at next).<br /><p>Below the ;extension=php_zip.dll line, add a new line and enter the following extension:</p><pre>extension=apc.so</pre>Return a few lines down and enter the following:<br /><pre>;;;;;;;;;;;;;;;;;;;;;;;<br />; APC LAYER CONTROL ;<br />;;;;;;;;;;;;;;;;;;;;;;;<br />apc.rfc1867=on<br />apc.max_file_size=200M<br />upload_max_filesize=200M<br />post_max_size=200M<br /></pre><p>Now, you do NOT have to use 200M. I simply did to test out uploading huge 191M video files to see if this progress bar truly works. Adjust this to suit your own personal needs.</p><p>Finally, save the file and exit by typing:</p><pre>:wq!</pre>You'll need the bang(!) because php.ini is by default a read-only file.<br /><p>The last step now is just to restart apache:</p><pre>apachectl restart</pre>apachectl is the command that restarts Apache in FreeBSD. However, it may or may not be available in your distro/PATH (user's profile) so you may need to browse into that directory and run the appropriate server command used in your distro (example: /etc/rc.id/init.d/httpd -k restart).<br /><p>Since I have never done this on windows, I'm just going to copy/paste IBM's installation method here. NOTICE: It's asking you to use the WAMP install package, but most developers here manually have their's installed. If you have issues, just post it here and we'll see if a solution can't be found.</p><p><strong>--- WINDOWS USERS ONLY ---</strong></p><p>APC is not enabled by default in PHP V5.2. Since the new hooks are a part of APC, we need to make sure to install the extension and make it available to the PHP interpreter. This is accomplished by downloading the php_apc extension files. In our case, we are using an installation of WAMP, a freely available packaged PHP for Windows®, which includes Apache and MySQL. It offers a nice user interface and is easy to manage with menus that support configuration options. </p><p>To set up APC on WAMP:<br /></p><pre>1. See Resources to download the libraries and WAMP.<br />2. Install WAMP.<br />3. Put the php_apc.dll file in the extensions folder for PHP. This is <wamproot>/php/ext by default.<br />4. Use the system tray WAMP menu to select PHP settings>PHP Extensions>Add Extension.<br />5. In the command-line interface that pops up, type php_apc.dll and press Enter.<br />6. Using a text editor, open <wamproot>/php/php.ini and add the line apc.rfc1867 = on (it doesn't matter where). If you're trying to test locally and plan to upload large files so you can actually see progress, you'll also want to add the following directives: apc.max_file_size = 200M, upload_max_filesize = 200M, and post_max_size = 200M. Don't do this on a live production server, though, or you're likely to use up bandwidth and disk space allotments, not to mention slowing everyone else down to a crawl.<br />7. Restart the webserver.<br /></wamproot></wamproot></pre><p>APC should now be set up and initialized. The RFC1867 features of APC — the features that enable you to track file uploads — should now be enabled as an option, and you should be ready to look into our file uploads to enable real-time status.</p><p>If you have trouble installing this on windows, just post and I'm sure we can figure it out. In the meantime, I think these steps are self-explanatory enough to get you started.</p><p>==========================================================</p><p><strong>Testing out the installation</strong></p><p>Testing out the installation is pretty simple. Just go into the directory where you initially unpackaged the APC bundle and find the file apc.php. Copy this file into your docroot and open it up in your browser. If the installation worked, you should see a big long explanation about all of APC's features, along with a nice pie chart if the GD library is also installed.</p><p>==========================================================</p><strong>Making A Progress Bar Test</strong><br /><p>Finally, we're ready to test out this progress bar stuff! It's very freaking easy, and I'm first going to just give you all the code you'll need.</p><br /><p>__________________________________________________________</p><br /><p><strong>progress.php</strong></p><pre><?php<br />$id = uniqid("");<br />?><br /><html><br /><head><title>Upload Example</title><br /><script type="text/javascript"><br />function getProgress() {<br /> CDownloadUrl('get', "getprogress.php?progress_key=<?php echo($id)?>",<br /> function(percent) {<br /> document.getElementById("progressinner").style.width = percent+"%";<br /> if (percent < 100) {<br /> setTimeout("getProgress()", 100);<br /> }<br /> });<br />}<br /><br />function CDownloadUrl(method, url, func) {<br /> var httpObj;<br /> var browser = navigator.appName;<br /> if(browser.indexOf("Microsoft") > -1)<br /> httpObj = new ActiveXObject("Microsoft.XMLHTTP");<br /> else<br /> httpObj = new XMLHttpRequest();<br /><br /> httpObj.open(method, url, true);<br /> httpObj.onreadystatechange = function() {<br /> if(httpObj.readyState == 4) {<br /> if(httpObj.status == 200) {<br /> var contenttype = httpObj.getResponseHeader('Content-Type');<br /> if(contenttype.indexOf('xml')>-1) {<br /> func(httpObj.responseXML);<br /> } else {<br /> func(httpObj.responseText);<br /> }<br /> } else {<br /> func('Error: '+httpObj.status);<br /> }<br /> }<br /> };<br /> httpObj.send(null);<br />}<br /><br />function startProgress(){<br /> document.getElementById("progressouter").style.display="block";<br /> setTimeout("getProgress()", 1000);<br />}<br /><br /></script><br /></head><br /><body><br /><iframe id="theframe" name="theframe" src="upload.php?id=<?php echo($id); ?>" style="border: none;<br />height: 100px; width: 400px;" > </iframe><br/><br/><br /><div id="progress_win"></div><br /><br /><div id="progressouter" style="width: 500px; height: 20px; border: 6px solid red; display:none;"><br /><div id="progressinner" style="position: relative; height: 20px; background-color: purple;<br />width: 0%;"></div><br /></div><br /><br /></body><br /></html><br /></pre><p>__________________________________________________________</p><strong>upload.php</strong><br /><pre><?php<br />$id = $_GET['id'];<br />?><br /><form enctype="multipart/form-data" id="upload_form" action="target.php" method="POST"><br /><input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $id?>"/><br /><input type="file" id="test_file" name="test_file"/><br/><br /><input onclick="window.parent.startProgress(); return true;" type="submit" value="Upload!"/><br /></form><br /></pre><p>__________________________________________________________</p><strong>target.php</strong><br /><pre><?php<br />if($_SERVER['REQUEST_METHOD']=='POST') {<br /> $filename = $_FILES["test_file"]["tmp_name"];<br /> $destination = "/path/to/apache22/data/progressbar/uploads/" . $_FILES["test_file"]["name"];<br /> move_uploaded_file($filename, $destination);<br /> echo "<p>File uploaded. Thank you!</p>";<br />}<br />?><br /></pre><p>__________________________________________________________</p><strong>getprogress.php</strong><br /><pre><?php<br />header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');<br />header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");<br />header('Cache-Control: no-store, no-cache, must-revalidate');<br />header('Cache-Control: post-check=0, pre-check=0', FALSE);<br />header('Pragma: no-cache');<br /><br />if(isset($_GET['progress_key'])) {<br />$status = apc_fetch('upload_'.$_GET['progress_key']);<br />echo $status['current']/$status['total']*100;<br />}<br />?><br /></pre>========================================================== <p><strong>Some Explaining to Do</strong><br /></p><p>First, let me say that the above code is direct code examples from IBM, but altered a little bit to make our lives much simpler.<br /></p><p>In the first file, progress.php, IBM originally had a Google MAPS API work-around using the GDownloadUrl function. As anyone knows who has tried to use this behind a firewalled web server, you can't validate your KEY (i.e.: <script src="http://maps.google.com/maps?file=api&v=2&key=YOURKEYHERE" type="text/javascript"></script>) without Google being able to access your server. Since this is true, the now awesome GDownloadUrl function is unusable. Fortunately I found the same idea they use for this function already exists in a separate implementation called CDownloadUrl that does not require Google Authentication. As I suspected, it's basically just an XHTTPRequest method that asks for the results of getprogress.php<br /></p><p>Also in progress.php there is a bit of confusion as to what exactly the $id value does. Well, the $id value, even though it appears blank, is anything but. It holds a unique ID value, so that we can track our current session without worrying about compromising it with someone else's results. To see it's value, just put "echo $id;" somewhere after the tag to view its result.<br /></p><p>Next, is target.php. This file basically just tells our application WHERE to store the new Uploaded file.<br /></p><p>Finally, getprogress.php. In this file is one more foreign entry that IBM does not give you: no-caching.<br /></p><pre>header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');<br />header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");<br />header('Cache-Control: no-store, no-cache, must-revalidate');<br />header('Cache-Control: post-check=0, pre-check=0', FALSE);<br />header('Pragma: no-cache');<br />//....<br /></pre>We HAVE to put the no-cache statement in there for this to work in both Firefox and IE 6+. IE 7 (maybe IE 6, I haven't tested this in that browser yet) CACHES your value. So unless you put this no-cache statement in there, the result you are going to see is the progress bar jump 1 time only (usually around 4-7% on big files or 90% to 100% on smaller files). This is because once IE's Ajax call retrieves the value once, it freaking caches the value and just sits there. And this little annoyance smurf ME OFF (sorry, but it did). I can't believe that not only I have to put hacks in place for IE in css, but now also because it caches VALUES when I don't want it to??????? Sigh........<br /><p>==========================================================<strong><br /></strong></p><p><strong>Conclusion</strong><br /></p><p>Run the progress bar example. It works. Works like a freaking dream!! I couldn't believe it but it has finally made me smile once again<br /></p><p>It should also be noted here that APC is NOT just for progressive uploads, but instead a caching service. We're basically just using APC's caching ability in order to grant us the nice method of progressive uploads...<br /></p>Anyways, I hope you enjoyed this tutorial. Take it easy.<br /><p>==========================================================</p><strong>Resources</strong><br /><a href="http://www.ibm.com/developerworks/opensource/library/os-php-v525/">What's new in PHP V5.2, Part 5: Tracking file upload progress</a><br /><a href="http://us.php.net/apc">PHP Manaul for APC</a><br /><a href="http://coolersport.info/30/new-replacement-tag-for-phpwcms/">CDownloadURL Javascript Function</a><br /><p>@author: Jonathon Hibbard</p><p><br />I originally wrote this article in April, 2008, which can be found <a href="http://forums.devnetwork.net/viewtopic.php?f=28&t=80960">here</a>.</p><p></p>Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-91264844738602961342009-12-11T23:13:00.000-08:002010-01-11T21:57:09.804-08:00Simple Optimizing Tips for PHP Part III - CommentingAs we write PHP code (or any language for that matter) we begin to start thinking about optimizing code. But even though our intentions are for "the greater good", we sometimes miss things that should be obvious.<br /><br />Today's article takes a look at:<br /><br /><span style="font-size:130%;">Commenting </span><br /><br />Commenting, to some, doesn't make sense to be an "optimizing" tip. I'm here to tell you that this is wrong. Commenting <em>is</em>, without a doubt, a key part to optimizing your code!<br /><br />If we consider all the scripts we have built over the years, one of the fundamental things that allow a script to be a "strong" and "well written" script is its commenting structure.<br /><br />Comments allow developers to find key methods and components that make a script operate much easier. Comments also allow for maintaining code and, in the process, make debugging these scripts easier. Thus it optimizes not only PHP, but also YOU!<br /><br />There are 3 supported methods of commenting blocks in PHP. They are:<br /><pre><br /> <strong>//</strong> (2 forward slashes) - This commenting break comments out one line.<br /><br /> <strong>#</strong> (or hash) - This commenting break also comments out one line.<br /><br /> The only difference is this method was (and still is) used in Unix<br /><br /> programming.<br /><br /><br /> <strong>/* */</strong> - This commenting style is for one to many lines of code.<br /><br /></pre><br /><br />While knowing the commenting blocks is all good and great, there exists 3 main questions that are asked by all levels of developers:<br />1) Where should I comment?<br /><br />2) How often should I comment?<br /><br />3) What kind of commenting style should I use?<br /><br /><strong>Where should I comment?</strong><br />This is perhaps the trickest question of all. The key here is if we define where to make comments, we could inadverdently convince a developer to make comments more often then he should. So to answer this quesiton without misleading and causing more harm than good, I have a few examples of "where" one should comment.<br /><br />You <strong>should</strong> comment on functions, variables, or complex blocks of code in which:<br />a) the meaning of the definition is unclear,<br />b) where it wasn't written in the most optimal way,<br />c) where it was a "hack",<br />d) where an "important" piece that solves a complex issue,<br />e) where a "change" from a privious method existed,<br />f) when commenting "out" an old method,<br />g) when setting ground rules for said definitions.<br /><br />Since there are obviously a lot of instances commenting is great, we must be careful not to over do our comments. Which leads us to the next question...<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUEY0Sf7eeoeVGpJ3SynJtbn4RgK0dmrfgH2eU1zdLgqY3VT28f97t8i7GZ9q7wkScc6q9nC3f153pbsNt_9dzolPd2rPnk1wyXdYscOSsuVZ7eequse2lmc5o0FVSHA5q-NWhlIfJUu3o/s1600-h/comments.jpg"><img style="MARGIN: 0px 10px 10px 0px; FLOAT: LEFT; WIDTH: 307px; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5425726595310376754" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUEY0Sf7eeoeVGpJ3SynJtbn4RgK0dmrfgH2eU1zdLgqY3VT28f97t8i7GZ9q7wkScc6q9nC3f153pbsNt_9dzolPd2rPnk1wyXdYscOSsuVZ7eequse2lmc5o0FVSHA5q-NWhlIfJUu3o/s320/comments.jpg" /></a><br /><br /><strong>How often should I comment?</strong><br />You should not comment too heavily, and you should not comment too lightly. An even medium is suggested, with an influence on the lighter side.<br /><br />While some will say lots of comments help people understand things, I will disagree and say it causes more complexity than is needed. If we end up having 100 lines of a 300 line file being code, and the other 200 lines of code being comments and whitespace, it very evident that the code is either written so poorly that lots of comments are needed to explain how it works, or that the author himself is not sure how the code works.<br /><br />Whlie some will say this is not true that they just "like" to make long, elaquent comments, I can respond with that there is a time and place (such as a wiki) for such long-winded explanations.<br /><br />So, how do we solve this issue of not writing too much, or too little comments?<br /><br />It's very simple. As stated in the "Where to comment" above, you should mainly be commenting on pieces of code that are not very easy to follow. So, to explain these pieces, here are a few scenarios that should help you on your way:<br /><br />1) Imagine that you have a variable that has been defined by an included file. A comment where the variable first appears would be an extremely helpful spot to point a new developer (or even your future self!) in the right direction.<br /><br />2) Say we have a new class or function that we have writte to save ourselves some time. Make a comment explaining the purpose of this class/function!<br /><br />3) Imagine that you have a few included files that perform other operations that will make the script you're currently viewing operate correctly. You could make 1 comment for all these includes, explaining why they are there and what purpose they have.<br /><br />4) One day you have to debug a piece of code but you forgot how it works. So you start back-tracking through the code and figure out, piece by piece, everything that was needed to make the end result work. Find the most vital part of your code, and create a comment there explaining just what you found! There may be a workound later.<br /><br />Whlie these examples are small, the concept should be quite clear. Try to consolidate your comments, but try to keep them short and sweet and to the point! The comments are there to leave breadcrumb trails and help debug, NOT to create a new bestseller book!<br /><br /><strong>What kind of commenting style should I use?</strong><br />The commenting style I will suggest here is using phpDoc commenting format. To learn about phpDoc, I would recommend <a href="http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.pkg.html">their website</a> for more information.<br /><br />Why phpDoc? Because, for me and the teams I've worked with, the style is clean, organized, and even supported in IDE's such as Zend and Eclipse!<br /><br />While I know this article was very short, I must break here. A whole book could be focused on the issue of commenting methods (and books DO exist on the subject!), but today just isn't the time for that sort of article. For now, have a merry christmas!<br /><br />Be sure to check out my next optimizing tutorial : <a href="http://coderjudychop.blogspot.com/2010/01/simple-optimizing-tips-for-php-iv-by.html">By Example</a>Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-33321290763512504142009-12-03T07:45:00.000-08:002009-12-03T08:06:30.768-08:00How to Fix svn: Directory __DIR__ containing working copy admin area is missing (and other misc SVN shortcuts)So, you have a directory called myclass, you've added the directory to SVN, and then you issue a commit. During the commit, you get a message saying either a file is outdated, or a directory already exists that causes this commit to fail. No big deal right? So you fix those issues and try to commit again... Only this time, you get a totally different error that can cause a pretty ugly headache when you're trying to solve it.<br /><br /><span style="font-weight:bold;">Problem</span>: svn: Directory 'myclass' containing working copy admin area is missing (and other misc SVN shortcuts)<br /><br /><span style="font-weight:bold;">Solutions</span><br />1) You could try and "checkout" the whole project again with the command <span style="font-weight:bold;">svn co http://svn.mydomain/my_project/ my_project</span>. This works for some, but in the case above, it may or may not work...<br /><br />2) You could try and "checkout" only the folder that's having the issues into a temporary directory, then move the .svn folder into the SVN controlled directory where your project lives with the commands:<br /><span style="font-weight:bold;">svn co http://svn.mydomain/my_project/myclass my_temp_folder</span><br /><span style="font-weight:bold;">mv my_temp_folder/myclass/.svn /path/to/my_project/myclass/</span><br /><br />Again, this will work for some, but in the case above it may yet again not solve your issue.<br /><br />3) Finally, you could copy the folder (in this case, myclass) to a temporary location, force delete it from svn's repository, and copy the folder back in, issue the add, and then commit again with the following commands:<br /><span style="font-weight:bold;">cp -r myclass /home/myuser/myclass_temp/</span><br /><span style="font-weight:bold;">svn --force delete myclass</span><br /><span style="font-weight:bold;">cp -r /home/myuser/myclass_temp/ /path/to/my_project/myclass </span><br /><span style="font-weight:bold;">svn add myclass</span><br /><span style="font-weight:bold;">svn commit -m "Added myclass folder"</span><br /><br />This 3rd step works for me everytime, though the others could work for you as well.<br /><br /><br />Since we're talking about SVN, here are some helpful commands should you need them...<br /><br /><span style="font-weight:bold;">Checkout a SVN Repository</span> : svn co http://svn.mydomain.com/myrepo/my_project myproject<br /><br /><span style="font-weight:bold;">Force and ADD recursively to all files and directories inside a working SVN folder:</span> svn add --force ./*<br /><br /><span style="font-weight:bold;">UPDATE a SVN project: </span> svn update<br /><br /><span style="font-weight:bold;">Commit a change to your SVN project: </span> svn commit -m "My Message here..."<br /><br /><span style="font-weight:bold;">Delete some files or folders from SVN</span> svn --force delete my_file_or_folderJonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-619409403989566912009-11-20T14:38:00.001-08:002009-12-03T08:49:55.189-08:00MySQL Quick ReferenceThis is just a simple quick reference for normal mysql routines that I forget from time to time and have to lookup.<br /><br /><span style="font-weight: bold;font-size:180%;" >MySQL</span><span style="font-weight: bold;"><br /><br />Index</span>es (from <a href="http://articles.sitepoint.com/article/optimizing-mysql-application/4">SitePoint</a>)<br /><strong><br />Adding a “normal” index via <code>CREATE INDEX:</code></strong><code><span style="color: #FFF;"><br /></span></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">CREATE INDEX [index_name] ON tablename (index_columns);</span></code><br /><span style="font-weight: bold;">Example</span><span style="color: #FFF;"> </span><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE INDEX fname_lname_age ON people (firstname,lastname,age);</code> <p> <strong>Adding a unique index via <code>CREATE INDEX:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">CREATE UNIQUE INDEX [index_name] ON tablename (index_columns);</span></code><br /><span style="font-weight: bold;">Example:</span> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE UNIQUE INDEX fname_lname_age ON people (firstname,lastname,age);</code></p> <p> <strong>Adding a “normal” index via <code>ALTER TABLE:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename ADD INDEX [index_name] (index_columns);</span></code><br /><span style="font-weight: bold;">Example:</span> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);</code></p> <p> <strong>Adding a unique index via <code>ALTER TABLE:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename ADD UNIQUE [index_name] (index_columns);</span></code><br /><span style="font-weight: bold;">Example:</span><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code> <code style="color: #FFF;">ALTER TABLE people ADD UNIQUE fname_lname_age (firstname,lastname,age);</code></p> <p> <strong>Adding a primary key via <code>ALTER TABLE:</code></strong><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE tablename ADD PRIMARY KEY (index_columns);</code><br /><span style="font-weight: bold;">Example:</span> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE people ADD PRIMARY KEY (peopleid);</code></p> <p> <strong>Adding a “normal” index via <code>CREATE TABLE:</code></strong><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE TABLE tablename (<br />rest of columns,<br />INDEX [index_name] (index_columns)<br />[other indexes]<br />);<br /></code><br /><span style="font-weight: bold;">Example:</span><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE TABLE people (<br />peopleid SMALLINT UNSIGNED NOT NULL,<br />firstname CHAR(50) NOT NULL,<br />lastname CHAR(50) NOT NULL,<br />age SMALLINT NOT NULL,<br />townid SMALLINT NOT NULL,<br />INDEX fname_lname_age (firstname,lastname,age)<br />);</code></p> <p> <strong>Adding a unique index via <code>CREATE TABLE:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">CREATE TABLE tablename ( </span><br /><span style="color: #FFF;"> rest of columns, </span><br /><span style="color: #FFF;"> UNIQUE [index_name] (index_columns) </span><br /><span style="color: #FFF;"> [other indexes] </span><br /><span style="color: #FFF;">);</span></code><br /><span style="font-weight: bold;">Example:</span><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE TABLE people (<br />peopleid SMALLINT UNSIGNED NOT NULL,<br />firstname CHAR(50) NOT NULL,<br />lastname CHAR(50) NOT NULL,<br />age SMALLINT NOT NULL,<br />townid SMALLINT NOT NULL,<br />UNIQUE fname_lname_age (firstname,lastname,age)<br />);</code></p> <p> <strong>Adding a primary key via <code>CREATE TABLE:</code></strong><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE TABLE tablename (<br />rest of columns,<br />INDEX [index_name] (index_columns)<br />[other indexes]<br />);</code><span style="color: #000;font-family:monospace;" ><br /></span><span style="font-weight: bold;">Example:</span><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">CREATE TABLE people (<br />peopleid SMALLINT NOT NULL AUTO_INCREMENT,<br />firstname CHAR(50) NOT NULL,<br />lastname CHAR(50) NOT NULL,<br />age SMALLINT NOT NULL,<br />townid SMALLINT NOT NULL,<br />PRIMARY KEY (peopleid)<br />);</code></p> <p> <strong>Dropping (removing) a “normal” or unique index via <code>ALTER TABLE:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename DROP INDEX index_name;</span></code><br /><span style="font-weight: bold;">Example:</span> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE people DROP INDEX fname_lname_age;</code></p> <strong>Dropping (removing) a primary key via <code>ALTER TABLE:</code></strong><code><br /></code><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename DROP PRIMARY KEY;</span></code><br /><span style="font-weight: bold;">Example:</span> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE people DROP PRIMARY KEY;</code><br /><br />-----------------------------------------------------------------------<br /><br /><span style="font-weight: bold;">Add Column</span><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename ADD COLUMN <span style="font-family:Georgia,serif;">[Col_Name] [Col_Definitions]<br /><br /></span></span></code><span style="font-weight: bold;">Add TinyINT Column<span style="font-weight: bold;"><span style="color: #FFF;"><span style="font-weight: bold;"><span style="font-weight: bold;"><br /></span></span></span></span></span><code></code> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE customers ADD COLUMN age tinyint unsigned NOT NULL default '0';<br /><br /></code><span style="font-weight: bold;">Add Varchar Column</span><br /><code></code> <code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code style="color: #FFF;">ALTER TABLE customers ADD COLUMN first_name varchar(40) NULL;</code><br /><br /><span style="font-weight: bold;"><br />Drop Column<br /></span><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename DROP COLUMN <span style="font-family:Georgia,serif;">[Col_Name]</span></span></code><br /><span style="font-weight: bold;">Example<br /></span><code style="color: #FFF;"><code style="color: #FFF;">mysql> </code></code><code><span style="color: #FFF;">ALTER TABLE tablename DROP COLUMN age;<br /><br /></span></code>-----------------------------------------------------------------------<br /><br /><span style="font-weight: bold;">Import/Export DB and Tables<br /><br />DB Import Example</span><br /><code></code> mysql -u [username] -p [password] [database] < [filename]<span style="font-weight: bold;"><br /></span><code style="color: #FFF;">~$ mysql -u my_user -p < customers_backup.sql<br /><br /></code><span style="font-weight: bold;">Full DB Export Example</span><br />mysqldump [options...] -u [username] -p [password] [database] > [filename]<br /><code style="color: #FFF;"><code style="color: #FFF;"><code style="color: #FFF;">~$ mysqldump -u my_user -p customers > customers_backup.sql</code><br /><br /></code></code><span style="font-weight: bold;">Full DB Export with Drop Table</span><code style="color: #FFF;"><code style="color: #FFF;"><span style="font-weight: bold;"><br /></span></code></code>mysqldump [options...] -u [username] -p [password] [database] > [filename]<code style="color: #FFF;"><code style="color: #FFF;"><span style="font-weight: bold;"><br /></span><code style="color: #FFF;">~$ mysqldump --add-drop-table -u my_user -p customers > customers_backup.sql</code><br /><br /></code></code><span style="font-weight: bold;">DB Export with Specific Tables</span><code style="color: #FFF;"><code style="color: #FFF;"><span style="font-weight: bold;"><br /></span></code></code>mysqldump -u [username] -p [password] [databasename] [table1 table2 ...] > [filename]<code style="color: #FFF;"><code style="color: #FFF;"><span style="font-weight: bold;"><br /></span><code style="color: #FFF;">~$ mysqldump --add-drop-table -u my_user -p customers account_info blog_entries > customers_backup.sql<br /><br /></code></code>-----------------------------------------------------------------------<br /><br /></code><span style="font-weight: bold;">Table Stats</span><code style="color: #FFF;"><br /><code class="literal"><span style="font-weight: bold;"><br /></span></code></code>SHOW TABLE STATUS<code style="color: #FFF;"><code class="literal"><br /></code></code>SHOW TABLE STATUS [ {FROM | IN} DB_NAME ] [LIKE '%' | WHERE<br />The following example uses a database name of "stats" and a table name of "Server"<code style="color: #FFF;"><br /><code style="color: #FFF;"><code style="color: #FFF;">mysql> SHOW TABLE STATUS FROM `stats` WHERE `Name` = 'Server' </code></code></code><br /><br />-----------------------------------------------------------------------<br /><br /><span style="font-weight: bold;">Misc</span><br /><br /><span style="font-weight: bold;">Create User</span><br /><code style="color: #FFF;"><code style="color: #FFF;"><code style="color: #FFF;"></code></code></code>CREATE USER user [IDENTIFIED BY [PASSWORD] 'password'];<br /><code style="color: #FFF;"><code style="color: #FFF;"><code style="color: #FFF;">mysql> Create USER my_username IDENTIFIED BY 'my_password';</code></code></code><br /><br /><span style="font-weight: bold;">Create Database</span><br />$ mysqladmin -u <username> -p create <nameofdatabase><br /><code style="color: #FFF;"><code style="color: #FFF;"><code style="color: #FFF;">~$ mysqladmin -u my_username -p create my_database<br /><br /></code></code></code><span style="font-weight: bold;">Drop/Delete Database</span><br />$ mysqladmin -u <username> -p drop <nameofdatabase><br /><code style="color: #FFF;"><code style="color: #FFF;"><code style="color: #FFF;">~$ mysqladmin -u my_username -p drop my_database</code></code></code>Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-21057822169862811232009-11-16T08:58:00.000-08:002010-01-11T21:40:08.748-08:00Simple Optimizing Tips for PHP Part II - Recursive FunctionsAs we write PHP code (or any language for that matter) we begin to start thinking about optimizing code. But even though our intentions are for "the greater good", we sometimes miss things that should be obvious.<br /><br />Today's article takes a look at:<br /><br /><span style="FONT-WEIGHT: bold">Recursive Functions</span><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBkMWEfDIgOp3Mrw69xgk-m6_nQEHlHmiz0cwSBPmrcriRdMBR8_eNOnxnFeHwrPk1aq9cP-QLnmWZN2cvLnDNbAsChEzJ_b4_RLWa8VeMnbW8f2g26TdTiN0e7UkMHptpBMqjuCqsbsEs/s1600/infinite.jpg"><img style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; MARGIN: 0px 10px 10px 0px; WIDTH: 120px; FLOAT: left; HEIGHT: 120px; BORDER-TOP: medium none; CURSOR: hand; BORDER-RIGHT: medium none" id="BLOGGER_PHOTO_ID_5404762192885477058" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBkMWEfDIgOp3Mrw69xgk-m6_nQEHlHmiz0cwSBPmrcriRdMBR8_eNOnxnFeHwrPk1aq9cP-QLnmWZN2cvLnDNbAsChEzJ_b4_RLWa8VeMnbW8f2g26TdTiN0e7UkMHptpBMqjuCqsbsEs/s320/infinite.jpg" /></a> Functions are one of the most important tools we have for developing reusable, structured code. When we build our functions, we are mainly looking at ways to reduce redundancy and create effective ways to perform the same operations we use in either 1 script or all our scripts.<br /><br />In our attempts to reduce redundancy, we inadvertently create more redundancy or miss opportunities to simplify how our code executes.<br /><br />Consider this situation. We have a multidimensional array set that we want to display not only in a div, but also divs inside of divs. One method we could solve this with involves something like the following code:<br /><br /><pre><br />$array = array("info" => array("employees" => array("name" => array(array("first" => "John",<br /> "last" => "Doe",<br /> ),<br /> array("first" => "Bob",<br /> "last" => "Henry",<br /> ),<br /> ),<br /> ),<br /> "departs" => array("building_1" => array("Sales",<br /> "PR",<br /> "HR",<br /> ),<br /> "building_2" => array("Developers",<br /> "Management",<br /> ),<br /> ),<br /> ),<br /> "misc" => "Created in 2009",<br /> );<br /><br />function display_information(array $data_array) {<br /> foreach($data_array as $key => $value) { // info<br /> if(is_array($value)) {<br /> foreach($value as $sub_key => $sub_value) {<br /> if(is_array($sub_value)) {<br /> foreach($sub_value as $sub_key2 => $sub_value2) {<br /> if(is_array($sub_value2)) {<br /> foreach($sub_value2 as $sub_key3 => $sub_value3) {<br /> if(is_array($sub_value3)) {<br /> foreach($sub_value3 as $sub_key4 => $sub_value4) {<br /> echo "$sub_key4 => $sub_value4";<br /> }<br /> } else {<br /> echo "$sub_key3 => $sub_value3";<br /> }<br /> }<br /> } else {<br /> echo "$sub_key2 => $sub_value2";<br /> }<br /> }<br /> } else {<br /> echo "$sub_key => $sub_value";<br /> }<br /> }<br /> } else {<br /> echo "$array_val";<br /> }<br /> }<br />}<br /></pre>While the above code works exactly as we need it to, it isn't exactly written the most efficient or optimized way. If you look at the code above, you can already start to see the redundancy involved with it. It's the exact same foreach statement whenever our condition of "is_array" rings true, and the exact same statement when it rings false. Plus, since we have to keep track of where we are in each of our loops, we get to the point to where our foreach loop parameters are extremely difficult to keep track of and the code in general is just a mess.<br /><br />So how can we optimize the code above to be less redundant, and in return create a quicker, less line, and optimized solution? We do it by creating a <span style="FONT-WEIGHT: bold">recursive function</span>.<br /><br />A <span style="FONT-WEIGHT: bold">recursive function</span> is just a method that calls itself from within itself. It helps reduce redundancy by applying similar logic to a result set without having to rewrite the exact same methods over and over again (as in the above code).<br /><br /><pre><br />$array = array("info" => array("employees" => array("name" => array(array("first" => "John",<br /> "last" => "Doe",<br /> ),<br /> array("first" => "Bob",<br /> "last" => "Henry",<br /> ),<br /> ),<br /> ),<br /> "departs" => array("building_1" => array("Sales",<br /> "PR",<br /> "HR",<br /> ),<br /> "building_2" => array("Developers",<br /> "Management",<br /> ),<br /> ),<br /> ),<br /> "misc" => "Created in 2009",<br /> );<br /><br />function display_information(array $data_array) {<br /> foreach($data_array as $key => $value) { // info<br /> if(is_array($value)) {<br /> display_information($value);<br /> } else {<br /> echo "$array_val";<br /> }<br /> }<br />}<br /></pre><br /><br />Nice isn't it? We take a 29 line function from our original example and turned it easily into a 9 line optimized function. This not only reduces the lines dedicated our function, but it also makes it easier to read, faster, and above all optimized!<br /><br />Recursive functions can be used in many instances. The key for the developer is to recognize when it's needed by carefully examining the code and determine if it's needed. This example (while a bit exaggerated) will hopefully open your eyes and also teach you just one more simple thing you can do to create more optimized code for PHP!<br /><br />Tune in next time for my next optimizing article on, <a href="http://coderjudychop.blogspot.com/2009/12/simple-optimizing-tips-for-php.html">Commenting</a>.Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-53171206188004032062009-11-12T08:01:00.000-08:002009-11-16T11:53:42.379-08:00Zend Studio 7.0.2 - Lot of new stuff, same old issuesI've been a Zend Studio IDE user for about 5 years now. I've always loved the IDE since it was so well tuned for PHP projects. Last year I made the blind leap of faith into using Zend Studio 6.0 and was extremely disappointed in what it provided to the developer. The release had so many bugs and never really stood up well against their previous 5.x release...<br /><br />When 6.0 was released with all the bugs and issues it contained, I went out of my way to write a 3 page bug list for the team. Why? Because I love Zend and their IDE. It is what makes my life as a developer much easier. I was hoping that pointing out the "features" of 6.0 that was causing so much pain for me to even consider using their product would be enough to send them a message: Change it, or lose yet another developer.<br /><br />Today I installed Zend Studio 7.0.2 Professional, totally expecting to see these issues resolved. While the IDE shows a drastic change in speed, the same errors and exceptions remain, thus making working in Zend Studio a much more complicated headache than it ever should be.<br /><br />Granted I would never be able to create the things Zend has for an IDE, however this is not even the case this time. Zend has decided (as of their 6.0 release) to use the Eclipse engine for their IDE. It was a mistake for their 6.0 version, and it's still a mistake today.<br /><br />The project management piece of Zend Studio (which is the most used functionality for me) is still broken, and management of files is still a clustered mess. <br /><br />Sigh. While there are a small amount of issues with the 5.5.1 build (which is what I STILL use today), these are NOTHING compared to working with 7.0.2. <br /><br />I hate to say it, but Zend Studio has lost another developer to use their IDE. I'm done. Their 5.x release was so GREAT! It made life so nice! But now they have continued to stick with the failed philosophy of using Eclipse as their engine (which is actually a decent enough engine), but they just cannot seem to make it work with Zend Studio.<br /><br />I cannot recommend this IDE to anyone, and I definitely cannot justify spending the amount of cash they (Zend) are calling me asking me to purchase for 7.0.2. There is just no way. <br /><br />I'll continue to use 5.5.1. Unfortunately though, I can only see nothing but doom for Zend's IDE user base, which is really too bad...Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-37348008005740808212009-11-09T07:59:00.000-08:002009-12-02T09:11:42.276-08:00Simple Optimizing Tips for PHP - Part IAs we write PHP code (or any language for that matter) we begin to start thinking about optimizing code. But even though our intentions are for "the greater good", we sometimes miss things that should be obvious. This article is one of many to come that hopes to point these things out to you, and in the process train your mind to think of quicker steps you may otherwise haven't really thought about.<br /><br />Today's article takes a look at:<br /><br /><span style="font-weight:bold;">Loop Arrays</span><br />When we use loops, the goal is simple: iterate through an array set, and do something with the results. Most developers understand this quite well but they build the basic looping structure without considering how poor methods of iteration will affect their code's performance.<br /><br />Example:<br /><pre><br />$sql = "SELECT * FROM `user`";<br />$rst = $dbh->fetch_rows($sql);<br /><br />for($i = 0; $i < count($rst); $i++) {<br /> // do something<br />}<br /></pre><br /><br />For some, the problem is quite clear. For others, the code above seems quite valid and perfectly fine. However, the above can cause serious latency in your application(s) if you follow this type of constructing loops enough times. <br /><br />The issue exists with the loop piece <span style="font-weight:bold;">$i < count($rst);</span><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigv8cEQ2BvK-tDISDRhoXNZSI8zpUzVbT5xRXKvx1dG95zj80oLdMK5DLoaGfYYqP20C0EF1wBgsF8syzzy9K4Ldy35V6xdLXBPlL6acir9prHXAsPRmV3RkT7h-Y2lzsersBq0fG_3EUo/s1600-h/SystemDown1979.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 223px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigv8cEQ2BvK-tDISDRhoXNZSI8zpUzVbT5xRXKvx1dG95zj80oLdMK5DLoaGfYYqP20C0EF1wBgsF8syzzy9K4Ldy35V6xdLXBPlL6acir9prHXAsPRmV3RkT7h-Y2lzsersBq0fG_3EUo/s320/SystemDown1979.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5402885646881687154" /></a>Consider that the query we used returns 2000 records. While the for loop is completely valid, the issue exists in that, for each iteration, you are now counting the number of results ($rst) in <span style="font-weight:bold;">each and every iteration</span>!. This means that if we have 2000 records, it's going to get a count of our $rst array 2000 times!<br /><br />What's worse is that when you issue the count() function on a big array, it must load this array into memory, check it, and then finally clear the tmp data. This in turn puts a small hamper on the server when done once, but when we are doing it 2000 consecutive times just for the sake of iteration, the overhead becomes very evident.<br /><br />The solution for this is quite simple. You should first just get a count of the number of records, assign it to a value <span style="font-style:italic;">before</span> the loop, and then use this for your iteration. For the PHP engine, is much faster to check a flat numeric value 2000 times rather than issue the count() sequence (explained above) 2000 times. <br /><br /><br />The Full Solution<br /><pre><br />$sql = "SELECT * from `user`";<br />$rst = $dbh->fetch_rows($sql);<br /><br />$total_users = count($rst);<br />for($i = 0; $i < $total_users; $i++) {<br /> // do something<br />}<br /></pre><br /><br />Where the above will find some flack from experienced users is the situation where you may really need a count of an array. Such situations include: removing a key from an array, adding a new key to an array, popping values off an array, etc...<br /><br />For these situations, the solution is not to use a for loop, but rather a foreach loop. Since a foreach loop iterates one array key at a time, we can remove/add array keys without the need to keep a count. Plus, if you really want to keep track of your $i variables count you can just assign $i before foreach loop and increment it within the foreach.<br /><br />Example:<br /><pre><br />$sql = "SELECT * FROM `user`";<br />$rst = $dbh->fetch_rows($sql);<br /><br />$i = 0;<br />foreach($rst as $key => $value) {<br /> echo "|| $key => $value => $i || ";<br /> $i++;<br />}<br /></pre><br /><br />While the above can be optimized a hundred different ways, the point is that we should be taking into consideration how a script in PHP operates. Instead of just forcing it to carry out redundant operations and continue to put more overhead/waste of processor cycles on our server, why not try to optimize the code and make a cleaner, faster application?<br /><br />Tune in next week for my next article: <a href="http://coderjudychop.blogspot.com/2009/11/simple-optomizing-tips-for-php-part-ii.html">Recursive Functions</a>.Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-60546444672611800922009-11-04T13:31:00.001-08:002009-11-17T13:52:52.904-08:00PHP Coding StandardsI wrote this a few years ago in order to create a more standard approach to developing PHP code. Enjoy...<br /><pre><br />/**<br /> * @author Jonathon Hibbard<br /> */<br /></pre><br /><span style="font-weight: bold;">PHP Coding Standards</span><br /><br /><span style="font-weight: bold;">Contents</span><br /><a href="#1">1 PHP Coding Standards</a><br /><a href="#2">2 Benefits of Coding Standards</a><br /><a href="#3">3 Coding Standard Used in this Document</a><br /><a href="#4">4 Identifier Naming</a><br /><a href="#5">5 Keep Functions to a Maximum of One Page</a><br /><a href="#6">6 Whitespace and Indentation</a><br /><a href="#7">7 Placement of Parenthesis and Curly Braces</a><br /><a href="#8">8 Line Up Like Values</a><br /><a href="#9">9 Add a Space between Variable Definitions</a><br /><a href="#10">10 File Structure and File Naming (More Work Needed in this section)</a><br /><a href="#11">11 Comments</a><br /><a href="#12">12 A Full Example</a><br /><a href="#13">13 Conclusion</a><br /><a href="#14">14 References</a><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGwwb80-OKmmbtWDVDEUZOOkBWUv5_PusmcSPg4nVlqCXGe7bH368hXnHIz6k7DglVVEGA5SA5zUQ0c9QPpOPfK6uZVlIBpv1ytY2psifzm29AriJ3ZnxlGisFVlTnDnec2YNq-Q-o7COX/s1600-h/team.jpg"><img style="margin: 0pt 10px 0px 0pt; cursor: pointer; width: 320px; height: 121px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGwwb80-OKmmbtWDVDEUZOOkBWUv5_PusmcSPg4nVlqCXGe7bH368hXnHIz6k7DglVVEGA5SA5zUQ0c9QPpOPfK6uZVlIBpv1ytY2psifzm29AriJ3ZnxlGisFVlTnDnec2YNq-Q-o7COX/s320/team.jpg" alt="" id="BLOGGER_PHOTO_ID_5400667766613518930" border="0" /></a><br /><a name="1"></a><br /><span style="font-weight: bold;">PHP Coding Standards</span><br />This document provides a complete coding standard to resolve conflicts that may arise when developers share and/or debug code. It is important for every developer to understand the benefits of such standards, how to use them and how not doing so affects others. Each developer adapts to their own methods and forcing them to change usually results in a negative result.<br /><br />With that being said, it is encouraged rather than required that you follow this standard. Coding standards do not have to be a difficult thing to conform to. They actually do more good than bad, especially in an environment where such standards do not already exist. This document's intension is to put standards to use and make for a more team-friendly development environment.<br /><br /><a name="2"></a><br /><span style="font-weight: bold;">Benefits of Coding Standards</span><br />Standards benefit both developers and businesses alike. It applies conventions that make it significantly easier for both current and subsequent developers to understand how the application they work on operates. It also helps with how to fix or extend existing code for new needs.<br /><br /><span style="font-style: italic;">Example: </span><br />$a = $b * c;<br /><br />The above is 100% valid and works, but it's very unclear to its true meaning. What are the variables true representations? How hard is it going to be when we have more variables like $aa, $az, $z, or others that obfuscate this further?<br /><br /><span style="font-style: italic;">A Standard-Correct Example: </span><br />$weekly_pay = $hours_worked * $pay_rate<br /><br />This describes both the intent and meaning of the variables, the end result and makes it very easy for anyone else to decipher who may stumble upon this line.<br /><br />Coding standards also are beneficial in that when used, they can enable a transparency to the code, eases debugging and can increase code maintainability.<br /><br />Quote from the Java Standards Webpage:<br /><pre><span style="font-style: italic;"> "Why have code conventions?<br />Code conventions are important to programmers for a number of reasons:<br /> * 80% of the lifetime cost of a piece of software goes to maintenance.<br /> * Hardly any software is maintained for its whole life by the original author<br /> * Code conventions improve the readability of the software,<br /> allowing engineers to understand new code more quickly and thoroughly."<br /></span></pre><br /><br /><a name="3"></a><br /><span style="font-weight: bold;">Coding Standard Used in this Document </span><br />The coding standard used in this document is very closely tied to the C++ (and C) language called the Kernighan and Ritchie (K&R) standard.<br /><br />There are other standards (including the ANSI C++ standard, Java standard, Pascal Standard and hundreds others) that developers use, but this standard is much more universal in many ways. The primary way being that it conforms to other adapted models outside of programming (such as the MySQL and SQL database server's standards) and has been widely used for over a decade now.<br /><br /><a name="4"></a><br /><span style="font-weight: bold;">Identifier Naming</span><br />Identifiers are names given to variables, functions, objects, etc.<br /><br />Given this understanding, you should follow these rules when defining an Identifier:<br />1) Do not use a leading underscore. They are usually reserved for compiler or internal variables of a language and can mislead a developer into thinking it's a SYSTEM identifier instead of a custom built one. Example of an incorrect name: $_first_name;<br /><br />2) Do not use names that are like standard system identifiers as these words are reserved words for a reason, and doing so will make the application more difficult to understand. Example of an incorrect name: $for;<br /><br />3) Give descriptive meaning to identifier names. Example of a bad name: $fn Example of a good name: $first_name. However, make sure to keep in mind not to get too descriptive since this will result in a lot of typing for the rest. Try to keep it short, but to the point. This rule can also be relaxed a little more for instances where short variable names such as $i are used in for loops.<br /><br />4) Give descriptive meaning for functions that contain a mix of verbs and nouns separated by underscores.<br /><span style="font-style: italic;"> Bad Example: </span><br />function first_name() {<br /><br /><span style="font-style: italic;"> Good Example: </span><br />function get_first_name() {<br /><br />Once again, this is considered the K&R standard. The other method is the ANSI C++ Standard, which capitalizes the first letter in each word (getFirstName). However, since we are using the K&R Standard in this document, it is required you follow the K&R naming conventions. Function names can easily be dismissed by a developer who is in the heat of the moment in code. It's very easy to call a function "doit" instead of "get_first_name".<br /><br /><a name="5"></a><br /><span style="font-weight: bold;">Keep Functions to a Maximum of One Page </span><br />This is not an absolute rule as much as it is a helpful practice. Functions that exceed 1 page are by default a little harder to decipher both during creation as well as debugging. Scrolling up and down a page can cause confusion as to what function you are in, where the braces line up, and also how something in the beginning of the function worked. This becomes more evident when opening a file in a console editor like VI or EMACs.<br /><br />Plus, if you find yourself writing more than a page for a function, it may be a very good indication that you might need to break the function down to 2 or more separate functions, that the function could instead be used as a recursive function, or simply that the method you are choosing is not the quickest route.<br /><br />This does not mean that you should obfuscate your code in order to meet this requirement. If the function absolutely must extend a page (and usually this is the case when formatting arrays correctly) then go ahead and do it. Just keep it in your head that if you can put a piece of code in its own separate function to be used later, do it.<br /><br /><a name="6"></a><br /><span style="font-weight: bold;">Whitespace and Indentation </span><br />Most modern editors today allow you to define how many spaces a tab can be. They also offer the ability to decide if you would rather use the tab (\t) character when the TAB key is pressed, or if the TAB should be interpreted as X number of spaces.<br /><br />The preferred method is that all TABS be handled as spaces with 2 spaces as the default (4 is usually the system default). If you are used to the standard Window's tab of 4 spaces, this may seem a little awkward at first. Rest assured, it will reduce the number of column space your code is taking up, but also give it a more structured and easier flow.<br /><br />Finally, it should also be common practice to change how new lines are handled with your IDE. The default should be set to treat new lines as the Unix \n (new line) instead of the Microsoft default \r (Return). The reason is that \n is a universal default supported in all Operating Systems, so no matter what OS your code is opened up in, the new lines will be nicely available on each new line instead of one concurrent line.<br /><br /><a name="7"></a><span style="font-weight: bold;">Placement of Parenthesis and Curly Braces </span><br />This is perhaps one of the most difficult subjects, not because of its complexity, but more of an infringement of a developer's habit. The ANSI C++ standard has us put curly braces on their own separate lines after ifs, loops, function declarations, etc. The K&R standard, however, has us put curly braces on the same line.<br /><br /><span style="font-style: italic;">Example ANSI C++ Standard </span><br /><pre>if (this_condition == true)<br />{<br /> //do something<br />}<br />else {<br /> //do something else<br />}<br /></pre><br /><span style="font-style: italic;">K&R 1TBS Standard Example </span><br /><pre><br />if(this_condition == true) {<br /> //do something<br />} else {<br /> //do something else<br />}<br /></pre><br />This document requires you to use the K&R Standard as was first defined in the beginning of this text. It is very important that this method be used in order to reduce the need of other developers to reformat your code in order to bring it up to scope with this standard.<br /><br /><a name="8"></a><br /><span style="font-weight: bold;">Line Up Like Values </span><br />When you have a list of variable declarations, or a large array definition, it's a good idea to line these values up. It helps with readability and is key to making your code clean for other developers.<br /><br /><span style="font-style: italic;">Bad Example </span><br />$first_name = 'John';<br />$last_name = 'Doe';<br />$city = 'Cincinnati';<br /><br /><span style="font-style: italic;">Good Example </span><br /><pre><br />$first_name = 'John';<br />$last_name = 'Doe';<br />$city = 'Cincinnati';<br /></pre><br />As you can see, the second example makes it much more legible. One more exaple would be for an array;<br /><br /><span style="font-style: italic;">Bad Example:</span><br />Array('first_name' => 'John', 'last_name' => 'Doe', 'city' => 'Cincinnati', 'address' => array('street' => 'PO Box 20', 'zip' => '45241'));<br /><br /><span style="font-style: italic;">Good Example: </span><br /><pre><br />Array('first_name' => 'John',<br /> 'last_name' => 'Doe',<br /> 'city' => 'Cincinnati',<br /> 'address' => array('street' => 'PO Box 20',<br /> 'zip' => '45241',<br /> ),<br /> );<br /></pre><br /><br /><a name="9"></a><br /><span style="font-weight: bold;">Add a Space between Variable Definitions </span><br />When defining a variable to be equal to a value, always make sure to put a space between the variable and the equal sign, and also a space between the equal sign and the value.<br /><br /><span style="font-style: italic;">Bad Example: </span><br />$i=0;<br />function foo($bar=1){<br />}<br /><br /><span style="font-style: italic;">Good Example:</span><br />$i = 0;<br />function foo($bar = 1) {<br />}<br /><br /><a name="10"></a><br /><span style="font-weight: bold;">Filesystem Naming Conventions (Files/Directories)</span><br />Both files and directories should be named by default by all lower-case. They should be descriptive in their meaning, but also limited in length. This is not only because both Linux and Unix servers are case-sensitive file systems, but also because even web addresses typed in capitalized lettering will, by default, be translated as lower-case values (IE: WWW.GOOGLE.COM will be switched to www.google.com on Enter).<br /><br />A typical file structure should have the following structure:<br /><pre><br />/admin/<br />/apps/<br /> |- classes<br /> |- includes<br />/css/<br />/js/<br />/utils/<br />/xml/<br /></pre><br /><br />The admin directory is where backend application files that would require a login and admins a page should go. The apps directory has 2 sub directories: includes and classes. Includes are files that are included simply to reduce repetition (such as header or footer files), whereas classes is where files containing class definitions are stored. The css directory, as the name implies, is where style sheet (css) files will go. The js directory is where JavaScript files would go. The utils directory is where either 3rd party applications or reusable applications (such as thumbnail generators) would go. The xml directory is where xml files will go.<br /><br /><span style="font-style: italic;">Example of a bad filename</span><br />1.php<br /><br /><span style="font-style: italic;">Example of a GOOD filename</span><br />list_users.php<br /><br /><a name="11"></a><br /><span style="font-weight: bold;">Comments</span><br />Comments play a major role in any development environment. It not only helps out an individual better debug their own code, but it is basically a manual to how your code works. Commenting should follow the DOC standard for commenting.<br /><br />The following is an example of this:<br /><pre><br />/**<br /> * A brief description of what you are commenting goes here.<br /> */<br /></pre><br /><br />Commenting is vital with any team. Over commenting can cause your code to be very confusing, under commenting could leave many questions regarding what your code actually does.<br /><br />You should always comment in these circumstances:<br /><pre><br />* Whenever you define a function or class<br />* Whenever you define a variable that does not describe itself properly.<br />* Whenever you write a "hack".<br />* Whenever a block of code is foreign to you.<br />* Every new page you create should have a description at the top indicating its purpose.<br />* If something you do is not 100% and needs to be rewritten in the future.<br />* If something you do is not 100% obvious.<br /></pre><br /><br />The PHPdoc comment is very intuitive and supported by most popular IDE's.<br /><br />Some of the most popular keys used with this commenting style are:<br /><pre><br />@author // Indicates the author's name<br />@param // Describes a parameter for a function<br />@copyright // The copyright information (if applicable).<br />@return // The return value of a function<br />@todo // Gives you the ability to write-up a "todo" list.<br /></pre><br /><br /><a name="12"></a><br /><span style="font-weight: bold;">A Full Example</span><br /><pre><br />/**<br /> * @author John Doe<br /> * This class' purpose is to provide a control area for handling database connections,<br /> * errors and results.<br /> *<br /> * @copyright ACME<br /> * @todo This class requires a new method of error control.<br /> */<br />class db_handle {<br /> /**<br /> * This is the database handler variable.<br /> */<br /> public $dbh;<br /><br /> /**<br /> * This is the constructor of the class.<br /> * @param string $strDSN // String containg connection information<br /> * @return object // Returns the db_handle object.<br /> */<br /> public function __construct($strDSN) {<br /> // Do Something.<br /> }<br />}<br /></pre><br /><br /><a name="13"></a><br /><span style="font-weight: bold;">Conclusion </span><br />This is the end of the current Coding Standards document. There are a few other concepts such as private/public variables, unit naming, and other high-end programming techniques that can be applied, but are not due to this not being about "how to program", but instead is about coding standards.<br /><br /><a name="14"></a><br /><span style="font-weight: bold;">References </span><br /><a href="http://en.wikipedia.org/wiki/Coding_standard">http://en.wikipedia.org/wiki/Coding_standard</a> - Wikipedia Definition of a Coding Standard<br /><a href="http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code_Style">http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code_Style</a> - Code Standards<br /><a href="http://en.wikipedia.org/wiki/Indent_style">http://en.wikipedia.org/wiki/Indent_style</a> - K&R Coding Style Definition<br /><a href="http://dn.codegear.com/article/10280/Code">http://dn.codegear.com/article/10280/Code</a> - Great Article relating to the K&R Coding StyleJonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-82135933002220786882009-01-09T20:58:00.000-08:002009-11-17T13:22:57.087-08:00When and How to Use Cookies(Disclaimer: The methods described below should be viewed as education purposes only! These methods are not certified by me to stop or prevent attacks to your site. Instead, this blog tries to explain some ideas for properly using cookies. In other words, use these methods at your own risk, but don't come looking to sue me if you or your site are compromised).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFOp7lUYPQyo-0NcpBAstsHssDOAgwZDpYQ6_ZvW76yWles9Klve7tkkuiGDX7fuRsw6FydSVGmUV8D3365-fKWNb5khHG_dvCypDvpRL7RxMiHT4YLW8LKrYiyEh-CSoXBNqZgy7dZOqE/s1600-h/cookie_theif.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 300px; height: 301px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFOp7lUYPQyo-0NcpBAstsHssDOAgwZDpYQ6_ZvW76yWles9Klve7tkkuiGDX7fuRsw6FydSVGmUV8D3365-fKWNb5khHG_dvCypDvpRL7RxMiHT4YLW8LKrYiyEh-CSoXBNqZgy7dZOqE/s320/cookie_theif.jpg" alt="" id="BLOGGER_PHOTO_ID_5289580419679517234" border="0" /></a>Cookies, by some, are one of God's greatest inventions for the Internet. To others, cookies represent all that is bad and evil in the world today.<br /><br />In reality, they are both.<br /><br />These little files are only as good or bad as you, the developer, use them. With the growing popularity in <a href="http://en.wikipedia.org/wiki/HTTP_cookie">XSS Attacks</a> and <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF Attacks</a>, there is no wonder developers are having trouble relating anything good with using cookies, and also why even more users are refusing to accept them.<br /><br /><br /><br />In this blog entry, I'll explain to you how to make using cookies on your site safer by explaining the following:<br />When to use cookies, and when not to use cookies<br />How to properly validate users with cookies<br />Alternatives to using client-side cookies<br />References/Further Reading<br /><br /><br /><br /><span style="font-weight: bold;">When to use cookies</span><br />Cookies, by many sites in the past and, unfortunately, the present, are mainly used to identify a user who has access to a website. They are intended to be a beneficial file(s) that grants users a more pleasant experience while they are browsing, shopping, or later return to a site, without the need to retype their credentials. However, the same helpful intentions of cookies such as these are continually being turned into unpleasant security vulnerabilities for users and websites alike.<br /><br />We first start with when <span style="font-weight: bold;">not</span> to use cookies.<br /><br />Cookies <span style="font-weight: bold;">should not</span> be used to store sensitive information. To be more blunt, you shouldn't store unencrypted (or plain-text) values for usernames, credit card information, first/last names, addresses, phone/fax/mobile numbers, passwords, email addresses, websites, social security numbers...you get the drift. Nothing personally related to your user nor anything that will be used to automatically authenticate/login a user should be available in a cookie.<br /><br />While select few will scream “blasphemy” at such an idea, I assure you it is not I who is blaspheming. It is a common misconception for developers to think cookies are a safe warehouse for information. Such carelessness is leading the current craze of XSS and CSRF attacks among <a href="http://kb.iu.edu/data/agwt.html">crackers</a> (poorly and misleadingly labeled <a href="http://kb.iu.edu/data/agwt.html">hackers</a>) to be legit methods to obtain or attack a user/website.<br /><br />So what should cookies be used for then?<br /><br />Cookies <span style="font-weight: bold;">should</span> be used for simple and harmless storage, and/or by validating that an actual user is submitting a form from within your website (for examples using the form method, please see Preventing CSRF andXSRF Attack link below).<br /><br />Some Ideas of simple storage:<br />Keeping track of a shopping cart of an unregistered user (registered users have the luxury of that information being stored in a database).<br /><br />Remembering which test/quiz/questionnaire/poll a user has already completed.. Of course, I do not mean for use with prize-based poll/questionnaire/etc. These should be limited to registered users and, like before, stored in a database.<br /><br />Tracking when a user is logged into your site to assist and report “Number of active/Logged In Users” status.<br /><br />All of these methods are simple, and harmless uses to store cookie data. But like any other data coming from a user to your site, the above must <span style="font-weight: bold;">always</span> be validated. You must be as paranoid as possible when dealing with data coming from your client, and validate everything, always. Assuming that no one cares about your website, or that it's unlikely a cracker would ever want to take over your website is exactly why a cracker would choose to take over your site. The majority of crackers do this in order to obtain popularity within their group (or bragging rights if you will), and when one finds out it's possible, the majority of the others will follow in order to gain the same bragging rights. All courtesy of your website's vulnerabilities.<br /><br />In general remember to just keep it simple, keep it light, and make values you store in a cookie obfuscated as well. If you want to store the ID of an item, name the cookie “session_id_for_user” and the ID the item_id multiplied by some integer and combination of letters/numbers.<br /><br />Example:<br />Assume you sale Bourbon, and the George T. Stagg has an item_id of 15. The value you should store in the cookie should be b375gts. In other words, b(for bourbon), 375 (which is 15 x 25), and gts (the initials for George T Stagg).<br /><br />Don't go using my example though. Be creative! Be obtrusive! The harder it is for a cracker to understand just exactly what your cookie values do, the harder it's going to be for them to realize that it's a worthless cookie to begin with.<br /><br /><span style="font-weight: bold;">How to properly validate users with cookies</span><br />One of the most popular things a developer wants to do anymore with cookies is allow for a returning user to have a more pleasant experience on their site by not needing to enter as much data to gain access. But since we've already stated that storing information used to authenticate a user is not only dangerous, but shouldn't be used, how should we go about granting users some sort of relief?<br /><br />The answer, just like above, is an obfuscated encryption key that is used to lookup a user_id in a database, but requires the user to type in their password. Once the encryption key is used and the correct password entered, the current encrypted key is discarded, and a new one is generated.<br /><br />While this may sound like it contradicts my statements earlier, it is in fact a legitimate method! How can this be? Well, first of all an encrypted hash generated from a combination of the user's browser agent (ie: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.04 (hardy) Firefox/3.0.5), a current timestamp (12388445), parts of the person's username and email address (smashed123 becomes maed23 and bob@gmail.com becomes omilom), all encrypted with <a href="http://www.php.net/sha1">SHA</a> or <a href="http://www.php.net/md5">MD5</a> (although there are numerous rumors about MD5 quickly becoming an insecure encryption). Now you have a nice, simple, and (for now) safe encryption. One that, even if decrypted, would be meaningless/useless to the cracker who attempts to hijack it.<br /><br />And since we are still requiring the user to type in their password to the site in order to accurately authenticate them further, off-site attacks are even more less likely.<br /><br />Even after all of this, I still do not use cookies for validating a user's login credentials. Unfortunately, I would rather suffer from losing a lazy user to giving an attacker even 1 iota of an advantage, no matter how good the methods appears.<br /><br /><span style="font-weight: bold;">Alternatives to using client-side cookies</span><br />There are of course alternatives to using cookies. Since I am more of a PHP fan, I will use PHP's server-side sessions as an example.<br /><br />PHP stores sessions 3 ways: via cookies on the client site (which, if used, should be used in conjunction with the session.cookie_httponly setting to help reduce XSS vulnerability), on the filesystem of the server (usually located in /tmp with a hash value), or in the server's memory (not covered or recommended).<br /><br />Since we're only looking at server-side methods, obviously that leaves server-side-based cookies. While this method is much more secure and reliable, it is still <span style="font-weight: bold;">strongly recommended</span> to follow the above guidelines when determining what sort of data to store inside of a session-based cookie.<br /><br /><span style="font-weight: bold;">Resources/Further Reading</span><br /><a href="http://www.codinghorror.com/blog/archives/001175.html">Preventing CSRF and XSRF Attacks</a><br /><a href="http://freedom-to-tinker.com/sites/default/files/csrf.pdf">The Felten and Zeller Paper (PDF)</a><br /><a href="http://www.cgisecurity.com/xss-faq.html">Cross-site Scripting Prevention/Awareness</a><br /><br /><br />In conclusion, I hope this has been helpful in some way to anyone interested in security. While some of the above almost certainly can be improved on (and I truly hope the development community tries to assist in doing just that), I welcome any and all comments.Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com1tag:blogger.com,1999:blog-6793774533095766486.post-69622671150870075092009-01-07T22:33:00.000-08:002009-01-10T10:25:00.552-08:00Facebook - You're killing me smalls!About 4 months ago, I began making my transition from MySpace over to the Facebook realm. Until recently, I had the utmost respect for Facebook, it's interface, how it works, and all that jazz.<br /><br />As I said, that is until recently.<br /><br />That is until I started getting all sorts of emails out of the blue. "What the hell??", I asked myself. Was Facebook selling my account information to a 3rd party? Were they spamming me to make an extra buck?<br /><br />The answer to all of these questions is "No" - at least not on purpose.<br /><br />For any tech nerd out there who knows anything at all about Cookies, Sessions, and Security from building a website, you know some pretty common rules when it comes to user information.<br /><br />1) Don't put any sensitive information in the cookie that you yourself wouldn't want the whole ever-loving world to know about.<br /><br />2) Don't trust that cookie data. It should be there as a means of "Quick Lookup" ONLY!<br /><br />3) DON'T PUT ANY SENSITIVE INFORMATION IN THE COOKIE!!<br /><br />Facebook, being the big powerhouse social networking site that they are, should of all people be more than aware of this. They should know that setting a cookie called "login_x" with my username (which is my email address too by the way) in there is a HUGE no-no! Worse yet, it's in plain text to boot!!<br /><br />Well, maybe I'm over-reacting a little bit. I mean, it <span style="font-weight: bold;"><span style="font-style: italic;">is</span></span> quote/unquote encrypted with url encode!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6Shc3FVsEYGkdinHj28kEpsx6vVDP8tF64n-BOjGSiY-79e5IBx0VxBlayHwHgEgM_NBQTKFcYMSg8tNYmARe2O1PfL1hI_KXMmZN20giv6XJfPdlN3NwCJ8zn9WR4Ga8XzkWGmDX2M2t/s1600-h/Noooo.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 311px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6Shc3FVsEYGkdinHj28kEpsx6vVDP8tF64n-BOjGSiY-79e5IBx0VxBlayHwHgEgM_NBQTKFcYMSg8tNYmARe2O1PfL1hI_KXMmZN20giv6XJfPdlN3NwCJ8zn9WR4Ga8XzkWGmDX2M2t/s320/Noooo.jpg" alt="" id="BLOGGER_PHOTO_ID_5288815413684583858" border="0" /></a><br /><br />COME ON GUYS! What the heck gives with this crap?<br /><br />Given the fact that a LOT more Cookie Sniffing sites are coming out, wouldn't it be pretty obvious that this is yet another great way to have the security on your site compromised, or even worse, a great way for my personal information to get out?! A simple lookup of the email from google, and more than likely you're also going to know that Person's First and Last Name. With that, if the user, say, owns a few domain names? A quick whois on those domains and you now have their address and phone number too! All this information in a matter of seconds if you have written a script to just do the leg work for you, or a couple minutes if you're a teenager with a desire to be a haxx0r.<br /><br />Now, in case there are any nay sayers out there who think that cookies are part of Satan's toolkit and that only a moron would store them, just hold on a second. Cookies can be good for a number of reasons, like storing a counter, the number of the last post you read, or something else insignificant that would just make your user's experience a tad bit better. Hell, maybe I'll even write a blog on the goods and bads of cookies. Either way, there are ways to use a cookie and there are ways NOT to use a cookie. For a good show in how not to, just use Facebook as an example.<br /><br />Don't get me wrong, I still love Facebook as an application, and I'll still use it since I've put way too much time into it as it is. However, I for one am going to try and block any and all cookies from this moment on from Facebook.<br /><br />I mean, MySpace isn't exactly the greatest site on the planet, but hey, at least they aren't storing sensitive information like this in plain text for the world to see...Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0tag:blogger.com,1999:blog-6793774533095766486.post-47873256722218202582008-12-18T22:47:00.000-08:002009-12-02T09:11:12.728-08:00Future of the Web<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFZ-v7eF0EQNAn5T9Nz0Z3pEtVtrQZgzMhtL3Eml-FgNEAUbj8dl2faLYfahtf6dmkEjifGOKUPUeeTe2BgeWif0rHx3ryVpXCosScrpg5ryX8qUf7z17p9RQjjvh9FrDZsSOqZ1aUavmF/s1600-h/big_phone.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 218px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFZ-v7eF0EQNAn5T9Nz0Z3pEtVtrQZgzMhtL3Eml-FgNEAUbj8dl2faLYfahtf6dmkEjifGOKUPUeeTe2BgeWif0rHx3ryVpXCosScrpg5ryX8qUf7z17p9RQjjvh9FrDZsSOqZ1aUavmF/s320/big_phone.jpg" alt="" id="BLOGGER_PHOTO_ID_5281389635462587842" border="0" /></a><br /><div class="note_content clearfix"> <div>So what's keeping me awake the past few nights is thinking about what is going to come next. The world was taken by storm from the whole "Web 2.0" craze (or Y2k part 2 if you ask me), but what's key here is that there really *is* a next step in technology.<br /><br />That next step is Mobile...<br /><br />I've been a mobile advocate since I learned how to send and receive to my Sony Ericson Z500a about 3-4 years ago. Since then, I started following trends with the new Mobile Web Standards that came out in 2005/06. When the world started seeing that it was possible to design sites around phones, the cell companies started to see a drastic increase in sales. The problem though, was phones just didn't have the resolution, the processor power, nor any other great qualities that made home computers the best user experience for surfing the web. This caused many to think it was just another fad and that mobile web would eventually just go away.<br /><br />But the happy fact is that it didn't go away, and it has actually started growing faster every single quarter. I think I predicted 2 years ago that 2008/09 would be the year for mobile, and I quite honestly like to think that my prediction is slowly becoming true. Google has released Android (a software development language for building mobile applications FREE) into the T-Mobile network that is being used by the G1 phones. Unfortunately for Google, it *is* with T-Mobile... kind of like the "SAMS cola" of phone services. But still, it was a MAJOR win for mobile devs everywhere.<br /><br />Then, once the rumors of Android in the wild were out, you started to see a huge hike in production of more finger-friendly keyboards for mobile phones, such as the new Blackberry Storm and the iPhone. Suddenly, mobile was coming back in a REALLY big way.<br /><br />Now, I honestly think there are companies out there struggling to figure out what to do next. Personally, I think that answer is quite obvious: start building mobile applications. Blackberry is based on Java, so is Android. Android right now is not nearly as big as Blackberry, but I bet you will see it catching up to speed IF (and this is truly an IF) Google sticks with it's guns for continuing development.<br /><br />What does this have to do with the future of Internet/Web? Everything. Once people start seeing that the market is out there for mobile, they will start wanting more applications like Facebook's awesome mobile app that helps connect them to not only their personal computing internet surfing, but also with their mobile surfing. You're going to see new Advertisement business plans aimed primarily at the mobile community, you're going to see huge leaps in interacting with our documents we normally would be able to maintain on our personal computers. You're also going to see OpenID finally start reaching the masses as mobile will be how they will try to finally sell it to the public. OpenID (a one-login for everything idea) has been sponsored and worked with by the biggest names (IBM, Microsoft, Google, etc), but the online community (for security reasons of course) just don't want one login to tie them to everything. But, if they can say "hey, this way you don't have to have 15 logins for your computer and 15 others for your mobile, just use one with OpenID", they'll have a big selling point...<br /><br />More than anything else, you're going to see innovation!! Innovation that I've been DYING to see come back to the digital nerds of our planet! I mean, it excites me even RIGHT NOW at how much we can truly do if we just stop being lazy and get out there and do it! The technology is here, and it's just a matter of kicking ourselves in the ass and saying LET'S GO DO IT!<br /></div></div>Jonathon Hibbardhttp://www.blogger.com/profile/18207064833581397383noreply@blogger.com0