<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dragffy.com &#187; PHP</title>
	<atom:link href="http://dragffy.com/blog/posts/category/programming/php-programming/feed" rel="self" type="application/rss+xml" />
	<link>http://dragffy.com/blog</link>
	<description>The development, documentation, and blogging domain of Gabriel Dragffy.</description>
	<lastBuildDate>Wed, 27 Jan 2010 14:23:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Creating a PHP array of ISO 3166-1 Country Codes</title>
		<link>http://dragffy.com/blog/posts/creating-a-php-array-of-iso-3166-1-country-codes</link>
		<comments>http://dragffy.com/blog/posts/creating-a-php-array-of-iso-3166-1-country-codes#comments</comments>
		<pubDate>Thu, 07 Jan 2010 09:42:04 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=142</guid>
		<description><![CDATA[I recently came across http://opencountrycodes.appspot.com/ which has an ISO 3166-1 list of country codes for various programming languages. I wanted to generate an HTML drop down list for customer to choose from based on these codes. However, there is no PHP version provoided. So taking the XML version found at http://opencountrycodes.appspot.com/xml/ I made a trivial [...]]]></description>
			<content:encoded><![CDATA[<p>I recently came across http://opencountrycodes.appspot.com/ which has an ISO 3166-1 list of country codes for various programming languages. I wanted to generate an HTML drop down list for customer to choose from based on these codes. However, there is no PHP version provoided. So taking the XML version found at http://opencountrycodes.appspot.com/xml/ I made a trivial script that would take the codes found in the XML document and organise them in to a PHP array called $XML2PHPCountryCodes and save that array in a file called country_names.php. The output file can then be included in any PHP script making the contained array available.</p>
<pre>
< ?php
$str = file_get_contents('http://opencountrycodes.appspot.com/xml/');
$xml = new SimpleXMLElement($str);
$out = '$countries'." = array(\n";
foreach ($xml->country as $country)
{
	$out .= "'{$country['code']}' => \"{$country['name']}\",\n";
}
$out .= ");";

file_put_contents('country_names.php', $out);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/creating-a-php-array-of-iso-3166-1-country-codes/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Xdebug.ini</title>
		<link>http://dragffy.com/blog/posts/xdebug-ini</link>
		<comments>http://dragffy.com/blog/posts/xdebug-ini#comments</comments>
		<pubDate>Wed, 09 Sep 2009 10:58:15 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=136</guid>
		<description><![CDATA[Shamelessly ripped from: http://gggeek.altervista.org/2007/11/26/the-completely-unofficial-xdebugini/
There are just a couple of minor annoyances with the Xdebug PHP debugger really, the first one being the absence of a proper documentation package to be downloaded and read offline.
I find well-commented ini files, in the Apache httpd.conf style, the best complement to user manuals and technical references: when you are [...]]]></description>
			<content:encoded><![CDATA[<p>Shamelessly ripped from: http://gggeek.altervista.org/2007/11/26/the-completely-unofficial-xdebugini/</p>
<p>There are just a couple of minor annoyances with the Xdebug PHP debugger really, the first one being the absence of a proper documentation package to be downloaded and read offline.</p>
<p>I find well-commented ini files, in the Apache httpd.conf style, the best complement to user manuals and technical references: when you are editing the forgotten config of that vetust server that has no web access or even ssh whatsoever, awkwardly sitting on an unstable pile of extinguished hardware in the darkest corner of the server room, they will save you dozens of round trips to go googling for information.</p>
<p>Unfortunately the Xdebug distribution contains no such thing: no comments, no list of ini directives, no ini file at all. But since I am a nice chap, after having carved out such precious jewel, I thought it might be of interest to the community, and without further ado here it is:</p>
<p>[xdebug]</p>
<p>;;;;;;;;;;;;;;;;;;;<br />
; About this file ;<br />
;;;;;;;;;;;;;;;;;;;<br />
;<br />
; built by G. Giunta as a verbatim copy of info from xedbug website on 2007/11/08</p>
<p>; You must uncomment one (and only one) line from the following to load<br />
; the xdebug extension.<br />
zend_extension=&#8221;/usr/lib/php4/xdebug.so&#8221;<br />
;zend_extension_ts=&#8221;/usr/lib/php4/xdebug.so&#8221;<br />
;zend_extension_ts=&#8221;c:\php4\xdebug.dll&#8221;<br />
;zend_extension=&#8221;c:\php4\xdebug.dll&#8221;</p>
<p>; When this setting is set to on, the tracing of function calls will be enabled<br />
; just before the script is run. This makes it possible to trace code in the<br />
; auto_prepend_file.<br />
xdebug.auto_trace=Off</p>
<p>; This setting, defaulting to On, controls whether Xdebug should write the<br />
; filename used in include(), include_once(), require() or require_once() to<br />
; the trace files.<br />
xdebug.collect_includes=On</p>
<p>; This setting, defaulting to 0, controls whether Xdebug should collect the<br />
; parameters passed to functions when a function call is recorded in either the<br />
; function trace or the stack trace.<br />
; The setting defaults to Off because for very large scripts it may use huge<br />
; amounts of memory and therefore make it impossible for the huge script to run.<br />
; You can most safely turn this setting on, but you can expect some problems in<br />
; scripts with a lot of function calls and/or huge data structures as parameters.<br />
; Xdebug 2 will not have this problem with increased memory usage, as it will<br />
; never store this information in memory. Instead it will only be written to disk.<br />
; This means that you need to have a look at the disk usage though.<br />
; This setting can have four different values. For each of the values a different<br />
; amount of information is shown. Below you will see what information each of the<br />
; values provides. See also the introduction of the feature Stack Traces for a<br />
; few screenshots.<br />
; Value Argument Information Shown<br />
; 0 None.<br />
; 1 Type and number of elements (f.e. string(6), array(8)).<br />
; 2 Type and number of elements, with a tool tip for the full information.<br />
; 3 Full variable contents (with the limits respected as set by<br />
; xdebug.var_display_max_children, xdebug.var_display_max_data and<br />
; xdebug.var_display_max_depth.<br />
; 4 Full variable contents and variable name.<br />
xdebug.collect_params=0</p>
<p>; This setting, defaulting to Off, controls whether Xdebug should write the<br />
; return value of function calls to the trace files.<br />
xdebug.collect_return=On</p>
<p>; This setting tells Xdebug to gather information about which variables are<br />
; used in a certain scope. This analysis can be quite slow as Xdebug has to<br />
; reverse engineer PHP&#8217;s opcode arrays. This setting will not record which<br />
; values the different variables have, for that use xdebug.collect_params.<br />
; This setting needs to be enabled only if you wish to use<br />
; xdebug_get_declared_vars().<br />
xdebug.collect_vars=Off</p>
<p>; If this setting is On then stacktraces will be shown by default on an error<br />
; event. You can disable showing stacktraces from your code with xdebug_disable().<br />
; As this is one of the basic functions of Xdebug, it is advisable to leave this<br />
; setting set to &#8216;On&#8217;.<br />
xdebug.default_enable=On</p>
<p>; These seven settings control which data from the superglobals is shown when an<br />
; error situation occurs. Each php.ini setting can consist of a comma seperated<br />
; list of variables from this superglobal to dump, but make sure you do not add<br />
; spaces in this setting. In order to dump the REMOTE_ADDR and the REQUEST_METHOD<br />
; when an error occurs, add this setting: xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD<br />
xdebug.dump.COOKIE=<br />
xdebug.dump.FILES=<br />
xdebug.dump.GET=<br />
xdebug.dump.POST=<br />
xdebug.dump.REQUEST=<br />
xdebug.dump.SERVER=<br />
xdebug.dump.SESSION=</p>
<p>; Controls whether the values of the superglobals as defined by the xdebug.dump.*<br />
; settings whould be shown or not.<br />
xdebug.dump_globals=On</p>
<p>; Controls whether the values of the superglobals should be dumped on all error<br />
; situations (set to Off) or only on the first (set to On).<br />
xdebug.dump_once=On</p>
<p>; If you want to dump undefined values from the superglobals you should set this<br />
; setting to On, otherwise leave it set to Off.<br />
xdebug.dump_undefined=Off</p>
<p>; Controls whether Xdebug should enforce &#8216;extended_info&#8217; mode for the PHP parser;<br />
; this allows Xdebug to do file/line breakpoints with the remote debugger. When<br />
; tracing or profiling scripts you generally want to turn off this option as PHP&#8217;s<br />
; generated oparrays will increase with about a third of the size slowing down<br />
; your scripts. This setting can not be set in your scripts with ini_set(), but<br />
; only in php.ini.<br />
xdebug.extended_info=1</p>
<p>; Introduced in Xdebug 2.1<br />
; This setting determines the format of the links that are made in the display<br />
; of stack traces where file names are used. This allows IDEs to set up a<br />
; link-protocol that makes it possible to go directly to a line and file by<br />
; clicking on the filenames that Xdebug shows in stack traces. An example format<br />
; might look like: myide://%f@%l<br />
; The possible format specifiers are:<br />
; %f the filename<br />
; %l the line number<br />
xdebug.file_link_format=</p>
<p>; Controls which IDE Key Xdebug should pass on to the DBGp debugger handler.<br />
; The default is based on environment settings. First the environment setting<br />
; DBGP_IDEKEY is consulted, then USER and as last USERNAME. The default is set<br />
; to the first environment variable that is found. If none could be found the<br />
; setting has as default &#8221;.<br />
xdebug.idekey=</p>
<p>; This is the base url for the links from the function traces and error message<br />
; to the manual pages of the function from the message. It is advisable to set<br />
; this setting to use the closest mirror.<br />
xdebug.manual_url=http://www.php.net</p>
<p>; Controls the protection mechanism for infinite recursion protection. The value<br />
; of this setting is the maximum level of nested functions that are allowed before<br />
; the script will be aborted.<br />
xdebug.max_nesting_level=100</p>
<p>; Introduced in Xdebug 2.1<br />
; By default Xdebug overloads var_dump() with its own improved version for displaying<br />
; variables when the html_errors php.ini setting is set to 1. In case you do not<br />
; want that, you can set this setting to 0, but check first if it&#8217;s not smarter<br />
; to turn off html_errors.<br />
xdebug.overload_var_dump=On</p>
<p>; When this setting is set to 1, profiler files will not be overwritten when a<br />
; new request would map to the same file (depnding on the xdebug.profiler_output_name setting.<br />
; Instead the file will be appended to with the new profile.<br />
xdebug.profiler_append=0</p>
<p>; Enables Xdebug&#8217;s profiler which creates files in the profile output directory.<br />
; Those files can be read by KCacheGrind to visualize your data. This setting<br />
; can not be set in your script with ini_set().<br />
xdebug.profiler_enable=0</p>
<p>; When this setting is set to 1, you can trigger the generation of profiler<br />
; files by using the XDEBUG_PROFILE GET/POST parameter. This will then write<br />
; the profiler data to defined directory.<br />
xdebug.profiler_enable_trigger=0</p>
<p>; The directory where the profiler output will be written to, make sure that the<br />
; user who the PHP will be running as has write permissions to that directory.<br />
; This setting can not be set in your script with ini_set().<br />
xdebug.profiler_output_dir=/tmp</p>
<p>; This setting determines the name of the file that is used to dump traces into.<br />
; The setting specifies the format with format specifiers, very similar to sprintf()<br />
; and strftime(). There are several format specifiers that can be used to format<br />
; the file name.<br />
; See the xdebug.trace_output_name documentation for the supported specifiers.<br />
xdebug.profiler_output_name=cachegrind.out.%p</p>
<p>; Normally you need to use a specific HTTP GET/POST variable to start remote debugging.<br />
; When this setting is set to &#8216;On&#8217; Xdebug will always attempt to start a remote<br />
; debugging session and try to connect to a client, even if the GET/POST/COOKIE<br />
; variable was not present.<br />
xdebug.remote_autostart=Off</p>
<p>; This switch controls whether Xdebug should try to contact a debug client which<br />
; is listening on the host and port as set with the settings xdebug.remote_host<br />
; and xdebug.remote_port. If a connection can not be established the script will<br />
; just continue as if this setting was Off.<br />
xdebug.remote_enable=Off</p>
<p>; Can be either &#8216;php3&#8242; which selects the old PHP 3 style debugger output, &#8216;gdb&#8217;<br />
; which enables the GDB like debugger interface or &#8216;dbgp&#8217; &#8211; the brand new debugger<br />
; protocol. The DBGp protocol is more widely supported by clients. See more<br />
; information in the introduction for Remote Debugging.<br />
xdebug.remote_handler=dbgp</p>
<p>; Selects the host where the debug client is running, you can either use a host<br />
; name or an IP address.<br />
xdebug.remote_host=localhost</p>
<p>; If set to a value, it is used as filename to a file to which all remote debugger<br />
; communications are logged. The file is always opened in append-mode, and will<br />
; therefore not be overwritten by default. There is no concurrency protection<br />
; available.<br />
xdebug.remote_log=</p>
<p>; Selects when a debug connection is initiated. This setting can have two different values:<br />
; req Xdebug will try to connect to the debug client as soon as the script starts.<br />
; hit Xdebug will only try to connect to the debug client as soon as an error condition occurs.<br />
xdebug.remote_mode=req</p>
<p>; The port to which Xdebug tries to connect on the remote host. Port 9000 is the<br />
; default for both the client and the bundled debugclient. As many clients use<br />
; this port number, it is best to leave this setting unchanged.<br />
xdebug.remote_port=9000</p>
<p>; When this setting is set to 1, Xdebug will show a stack trace whenever an<br />
; exception is raised &#8211; even if this exception is actually caught.<br />
xdebug.show_exception_trace=0</p>
<p>; When this setting is set to something != 0 Xdebug&#8217;s generated stack dumps in<br />
; error situations will also show all variables in the top-most scope. Beware<br />
; that this might generate a lot of information, and is therefore turned off by default.<br />
xdebug.show_local_vars=0</p>
<p>; When this setting is set to something != 0 Xdebug&#8217;s human-readable generated<br />
; trace files will show the difference in memory usage between function calls.<br />
; If Xdebug is configured to generate computer-readable trace files then they<br />
; will always show this information.<br />
xdebug.show_mem_delta=0</p>
<p>; The format of the trace file.<br />
; 0 shows a human readable indented trace file with: time index, memory usage,<br />
; memory delta (if the setting xdebug.show_mem_delta is enabled), level,<br />
; function name, function parameters (if the setting xdebug.collect_params<br />
; is enabled, filename and line number.<br />
; 1 writes a computer readable format which has two different records. There<br />
; are different records for entering a stack frame, and leaving a stack frame<br />
xdebug.trace_format=0</p>
<p>; When set to &#8216;1&#8242; the trace files will be appended to, instead of being overwritten<br />
; in subsequent requests.<br />
xdebug.trace_options=0</p>
<p>; The directory where the tracing files will be written to, make sure that the<br />
; user who the PHP will be running as has write permissions to that directory.<br />
xdebug.trace_output_dir=/tmp</p>
<p>; This setting determines the name of the file that is used to dump traces into.<br />
; The setting specifies the format with format specifiers, very similar to<br />
; sprintf() and strftime(). There are several format specifiers that can be used<br />
; to format the file name. The &#8216;.xt&#8217; extension is always added automatically.<br />
;The possible format specifiers are:<br />
; %c crc32 of the current working directory trace.%c trace.1258863198.xt<br />
; %p pid trace.%p trace.5174.xt<br />
; %r random number trace.%r trace.072db0.xt<br />
; %s script name cachegrind.out.%s cachegrind.out._home_httpd_html_test_xdebug_test_php<br />
; %t timestamp (seconds) trace.%t trace.1179434742.xt<br />
; %u timestamp (microseconds) trace.%u trace.1179434749_642382.xt<br />
; %H $_SERVER['HTTP_HOST'] trace.%H trace.kossu.xt<br />
; %R $_SERVER['REQUEST_URI'] trace.%R trace._test_xdebug_test_php_var=1_var2=2.xt<br />
; %S session_id (from $_COOKIE if set) trace.%S trace.c70c1ec2375af58f74b390bbdd2a679d.xt<br />
; %% literal % trace.%% trace.%%.xt<br />
xdebug.trace_output_name=trace.%c</p>
<p>; Controls the amount of array children and object&#8217;s properties are shown when<br />
; variables are displayed with either xdebug_var_dump(), xdebug.show_local_vars<br />
; or through Function Traces. This setting does not have any influence on the<br />
; number of children that is send to the client through the Remote Debugging feature.<br />
xdebug.var_display_max_children=128</p>
<p>; Controls the maximum string length that is shown when variables are displayed<br />
; with either xdebug_var_dump(), xdebug.show_local_vars or through Function Traces.<br />
; This setting does not have any influence on the amount of data that is send to<br />
; the client through the Remote Debugging feature.<br />
xdebug.var_display_max_data=512</p>
<p>; Controls how many nested levels of array elements and object properties are<br />
; when variables are displayed with either xdebug_var_dump(),<br />
; xdebug.show_local_vars or through Function Traces. This setting does not have<br />
; any influence on the depth of children that is send to the client through the<br />
; Remote Debugging feature.<br />
xdebug.var_display_max_depth=3</p>
<p>For installation, just copy and paste it at the end of your php.ini file (or, if you’re on Debian or similarly configured distros, you can save it as separate file in the php ini directory).</p>
<p>Note1: the zend_extension lines at the top of the file are tailored for a php4 install. Make sure to change them to fit your environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/xdebug-ini/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apache Virtual Hosts on OS X Leopard</title>
		<link>http://dragffy.com/blog/posts/apache-virtual-hosts-on-os-x-leopard</link>
		<comments>http://dragffy.com/blog/posts/apache-virtual-hosts-on-os-x-leopard#comments</comments>
		<pubDate>Sun, 31 May 2009 13:42:49 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[Leopard]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Operating System]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=124</guid>
		<description><![CDATA[If you develop multiple sites and you need virtual hosting functionality, scroll down to the end of the /private/etc/apache2/httpd.conf file and uncomment the following:
# Include /private/etc/apache2/extra/httpd-vhosts.conf
Next, you’ll need to setup whatever virtual hosts you have in the virtual hosts file /private/etc/apache2/extra/httpd-vhosts.conf
You need to make an entry in the httpd-vhosts.conf file like so:

&#60;virtualhost *:80&#62;
   [...]]]></description>
			<content:encoded><![CDATA[<p>If you develop multiple sites and you need virtual hosting functionality, scroll down to the end of the <code>/private/etc/apache2/httpd.conf</code> file and uncomment the following:</p>
<p><code># Include /private/etc/apache2/extra/httpd-vhosts.conf</code></p>
<p>Next, you’ll need to setup whatever virtual hosts you have in the virtual hosts file <code>/private/etc/apache2/extra/httpd-vhosts.conf</code></p>
<p>You need to make an entry in the httpd-vhosts.conf file like so:</p>
<pre>
&lt;virtualhost *:80&gt;
   ServerName beta-site-1.com
   ServerAlias www.beta-site-1.com
   ServerAdmin webmaster@beta-site-1.com
   ErrorLog "/private/var/log/apache2/dummy-host2.example.com-error_log"
   CustomLog "/private/var/log/apache2/dummy-host2.example.com-access_log" common

   DocumentRoot "/Library/WebServer/beta-site-1"
   ScriptAlias /cgi-bin/ "/Library/WebServer/beta-site-1/cgi-bin"
   <directory "/Library/WebServer/beta-site-1">
     Options FollowSymLinks MultiViews Includes
     AllowOverride All
     Order allow,deny
     Allow from all
   </directory>
&lt;/virtualhost&gt;
</pre>
<p>The examples provided by Apple  in the vhosts file are slightly incorrect and if you use the CustomLog lines as is you will get errors the following errors if you run: <code>apachectl -t -D DUMP_VHOSTS</code>:<br />
<code>Syntax error on line 40 of /private/etc/apache2/extra/httpd-vhosts.conf:<br />
CustomLog takes two or three arguments, a file name, a custom log format string or format name, and an optional "env=" clause (see docs)</code></p>
<p>This is because<br />
<code>CustomLog "/private/var/log/apache2/dummy-host.example.com-access_log common</code></p>
<p>Should actually read:<br />
<code>CustomLog "/private/var/log/apache2/dummy-host.example.com-access_log" common</code></p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/apache-virtual-hosts-on-os-x-leopard/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making CodeIgniter&#8217;s Profiler AJAX compatible</title>
		<link>http://dragffy.com/blog/posts/making-codeigniters-profiler-ajax-compatible</link>
		<comments>http://dragffy.com/blog/posts/making-codeigniters-profiler-ajax-compatible#comments</comments>
		<pubDate>Tue, 13 Jan 2009 09:21:08 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Operating System]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=80</guid>
		<description><![CDATA[Modern web applications almost all make use of AJAX to enhance their user appeal. However, AJAX can be hard to debug, especially when all the traditional tools do little to help. When doing standard PHP coding CodeIgniter (CI) offers a profiler which will be appended to the bottom of generated pages. This gives you information [...]]]></description>
			<content:encoded><![CDATA[<p>Modern web applications almost all make use of AJAX to enhance their user appeal. However, AJAX can be hard to debug, especially when all the traditional tools do little to help. When doing standard PHP coding CodeIgniter (CI) offers a profiler which will be appended to the bottom of generated pages. This gives you information on the request that was recently processed, including any POST or GET values passed to the script, how long execution took and how long any SQL queries took as well as what those queries actually were. During development I find this information indispensable to make sure my SQL queries are correct and things are working as I want.</p>
<p>However, when coding up AJAX aspects of the application this doesn&#8217;t work very well, any page fragments fed back to the JavaScript will have the profiler stuck at the bottom, and since these fragments are usually inserted inside DIVs the profiler cannot be read in it&#8217;s entirety, or it breaks the layout, or more likely, both of the above. Therefore I set out to find a way of making it AJAX compatible, so that it would always end up at the bottom of the page, even when it was originally returned appended to a page fragment. In the end this turned out easier than anticipated.</p>
<p>One small change needs to be  made to your footer, you need to create an empty div with an ID of &#8220;debug&#8221;, this div will hold the profiler, so place the div where you want the profiler. The advantage with this is that you cannot see it when it is empty so it could even be left in for production code. The div looks like this:<br />
<code>&lt;div id="debug"&gt;&lt;/div&gt;</code></p>
<p>Now we need to extend, or rather override the CI profiler so create the file <code>system/application/libraries/MY_Profiler.php</code></p>
<p>Replace MY_ with the value of <code>$config['subclass_prefix']</code> found in your config file, by default it is MY_.</p>
<p>Next paste the following code in to it. Remember to change the name of the class as dictated by the filename you use, also change the name of the constructor function too. You can also change the script line to load the jQuery library from one of your servers, or even rewrite the entire script section to use any JavaScript you like.</p>
<pre>
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Profiler extends CI_Profiler
{
    function MY_profiler()
    {
        parent::CI_Profiler();
    }

    function run()
    {
            $output = &lt;&lt;&lt;ENDJS
&lt;script src=&quot;http://code.jquery.com/jquery-latest.js&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; charset=&quot;utf-8&quot;&gt;
// &lt; ![CDATA[
    $(document).ready(function() {
        var html = $('#codeigniter_profiler').clone();
        $('#codeigniter_profiler').remove();
        $('#debug').hide().empty().append(html).fadeIn('slow');
    });
// ]]&gt;
&lt;/script&gt;
ENDJS;
            $output .= &quot;&lt;div id='codeigniter_profiler' style='font-size: 0.7em; clear:both;background-color:#fff;padding:10px;'&gt;&quot;;
            $output .= $this-&gt;_compile_uri_string();
            $output .= $this-&gt;_compile_controller_info();
            $output .= $this-&gt;_compile_memory_usage();
            $output .= $this-&gt;_compile_benchmarks();
            $output .= $this-&gt;_compile_get();
            $output .= $this-&gt;_compile_post();
            $output .= $this-&gt;_compile_queries();
            $output .= '&lt;/div&gt;';
            return $output;
    }
}</pre>
<p>If you have already loaded a jQuery library in your header somewhere then make sure this ajax fragment doesn&#8217;t load jQuery again &#8211; otherwise all your event bindings and everything else will fail. If this is the case simply remove the line:</p>
<pre>&lt;script src=&quot;http://code.jquery.com/jquery-latest.js&quot; /&gt;</pre>
<p>From the above code.</p>
<p>That should be it, hit me back if you have any feedback, questions, or need some help.</p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/making-codeigniters-profiler-ajax-compatible/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Inserting large blobs in MySQL</title>
		<link>http://dragffy.com/blog/posts/inserting-large-blobs-in-mysql</link>
		<comments>http://dragffy.com/blog/posts/inserting-large-blobs-in-mysql#comments</comments>
		<pubDate>Mon, 12 Jan 2009 14:05:00 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=77</guid>
		<description><![CDATA[Last week I setup MySQL replication for a database with two slaves. I wanted to see how resilient it was, and one of the tests I wanted to perform was to create a record on the master and then interrupt the replication of the same record on the slave. This would allow me to see [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I setup MySQL replication for a database with two slaves. I wanted to see how resilient it was, and one of the tests I wanted to perform was to create a record on the master and then interrupt the replication of the same record on the slave. This would allow me to see whether MySQL could recover from such an error.</p>
<p>So I thought the easiest way of doing this would be to to insert a large 700mb<br />
file in to MySQL &#8211; to give me enough time to interrupt a slave before<br />
replication had completed. Thus being able to test MySQL&#8217;s resilience to<br />
loss of connectivity during UPDATE/INSERT queries.</p>
<p>I have never used BLOB columns before so my quest took my on a journey during which I learned a lot about these blobs. Now, even though a MySQL long blob can hold 4GB of data I have encountered<br />
problem after problem dealing with it:</p>
<p>PHP scripts are limited to 32MB memory maximum, this can be upped, but<br />
is not scalable and not a good solution. It means that you cannot simply<br />
read the data of file and perform an INSERT since the file data is<br />
stored in PHP&#8217;s memory first. This meant the development of a PHP script<br />
that could read chunks (just a meg or so) from a file and perform UPDATE<br />
queries along with MySQL CONCAT function to effectively append each<br />
chunk.</p>
<p>CONCAT, as I eventually found out, returns NULL if any of it&#8217;s arguments<br />
are NULL. In my case when attempting to UPDATE a row with additional<br />
chunks the resulting blob size was always zero. This was because the<br />
very first time CONCAT is used the blob field is empty (NULL), therefore<br />
CONCAT always returned NULL &#8211; and so, the data in the blob column never<br />
grew. The query looked like this:<br />
<code>UPDATE `$table` SET `data` = CONCAT(data, '{mysqli_real_escape_string($buffer)}') WHERE `id`=$id";</code></p>
<p>I then combined CONCAT with COALESCE which will return an alternative<br />
value that you specify in the eventuality the first argument is NULL. By<br />
combining these two I could overcome the above problem.<br />
Resulting query structure:<br />
<code>UPDATE `$table` SET `data` = COALESCE(CONCAT(data, '{mysqli_real_escape_string($buffer)}'), '') WHERE `id`=$id";</code></p>
<p>Great, now we&#8217;re finally adding our chunks on. Then my computer ran out<br />
of disc space &#8211; the reason: 7 gigs of MySQL replication logs. Took a<br />
while to find that out. Fixed.</p>
<p>Next problem, although I was certain (via in-depth PHP debugging) that<br />
PHP was correctly reading chunks from the file in a consecutive order,<br />
of the correct size, and the SQL query was being properly executed<br />
without any sly errors the blob column would never end up growing above<br />
12MB (according the PHP MyAdmin). Through even more intensive debugging<br />
I found that after concatenating each chunk the blob would grow by the<br />
correct amount up to 16MB, then it would zero and start again. The<br />
result of pushing a 700MB ISO in to it would always be less 16MB.</p>
<p>Working from a hunch I upped the max_packet_size in my.conf from 16MB to<br />
36MB, the result was as above but this time the blob would grow to 32MB<br />
before zeroing itself.</p>
<p>I then found this MySQL bug report:<br />
<a href="http://bugs.mysql.com/bug.php?id=22853">http://bugs.mysql.com/bug.php?id=22853</a></p>
<p>It is considered a bug simply because by upping max_packet_size to<br />
something like 4GB or anything substantial leaves the MySQL server open<br />
to network DoS attacks. There is no work around. A fix is scheduled for<br />
version 6.</p>
<p>Anyway, since we don&#8217;t care about security I maxed out the packet_size,<br />
and my chunking script worked, but very quickly I noticed a huge amount of<br />
slowdown once the blob had grown to just a few tens of megs. In fact it<br />
took about 20 minutes to get to 200MB. Without supporting my theory with<br />
any evidence I reckon the CONCAT function reads all the data out of the<br />
database in to memory, does it&#8217;s stuff and then stuffs it back in to the<br />
database. The result is an increasingly slow query.</p>
<p>It would seem that although MySQL supports blobs of about 4GB that you<br />
can never get that size unless you:</p>
<p>1. Change the max_packet_size to a stupidly high number, leaving your<br />
server open to DoS attacks so then you can just do a single INSERT. Using CONCAT<br />
is out since it would take forever.</p>
<p>2. Change the memory limit of PHP scripts to be greater than 4GB.</p>
<p>3. Have absolutely bags of RAM since three copies of the file are stored<br />
in RAM (certainly two copies). Since you cannot chunk the file and<br />
perform CONCATS PHP will read the entire file in to it&#8217;s memory. This<br />
will all then be buffered by the MySQL driver. Then this is passed to<br />
the database. Therefore if you wish to insert a 4 GB file you will<br />
require >12GB of RAM.</p>
<p>One work around is to chunk the file as before but each chunk is<br />
represented by a single row. These can then be linked together by giving<br />
each row a master file ID, so that all necessary rows can be retrieved. </p>
<p>For my purposes this doesn&#8217;t help, I needed queries that took a while,<br />
inserting rows like this will take but a fraction of a second each.</p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/inserting-large-blobs-in-mysql/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Beware of the Trailing Comma in JavaScript Prototypes</title>
		<link>http://dragffy.com/blog/posts/beware-of-the-trailing-comma-in-javascript-prototypes</link>
		<comments>http://dragffy.com/blog/posts/beware-of-the-trailing-comma-in-javascript-prototypes#comments</comments>
		<pubDate>Wed, 03 Dec 2008 11:29:12 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating System]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=66</guid>
		<description><![CDATA[Came accross the following post at:
http://www.pluralsight.com/community/blogs/fritz/archive/2007/06/19/47771.aspx
&#8220;I spent more time than I care to admit tracking down this one, perhaps this post will save someone else the trouble&#8230;
When defining a number of functions in a prototype in JavaScript, do not include a trailing comma after the last function:

MyType.prototype = {
    foo : function() [...]]]></description>
			<content:encoded><![CDATA[<p>Came accross the following post at:<br />
<a href="http://www.pluralsight.com/community/blogs/fritz/archive/2007/06/19/47771.aspx">http://www.pluralsight.com/community/blogs/fritz/archive/2007/06/19/47771.aspx</a></p>
<p>&#8220;I spent more time than I care to admit tracking down this one, perhaps this post will save someone else the trouble&#8230;</p>
<p>When defining a number of functions in a prototype in JavaScript, do not include a trailing comma after the last function:</p>
<pre>
MyType.prototype = {
    foo : function() {
          // ...
    },

    bar : function() {
        //...
    }, //< - fails in IE!
 }
</pre>
<p>What was especially tricky about tracking this problem down was that FireFox works with or without the trailing comma, so it only fails in IE!"</pre>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/beware-of-the-trailing-comma-in-javascript-prototypes/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML Helper for generating a country drop-down list in CodeIgniter</title>
		<link>http://dragffy.com/blog/posts/html-helper-for-generating-a-country-drop-down-list-in-codeigniter</link>
		<comments>http://dragffy.com/blog/posts/html-helper-for-generating-a-country-drop-down-list-in-codeigniter#comments</comments>
		<pubDate>Fri, 09 May 2008 12:04:50 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=44</guid>
		<description><![CDATA[Frustrated at having to create my own drop-down country lists in CI I created a helper for it. It can even work with the CI Validation class, so if the form is submitted and fails validation when it is redisplayed the same country is selected as the form was submitted with.
Download the file MY_form_helper.php and [...]]]></description>
			<content:encoded><![CDATA[<p>Frustrated at having to create my own drop-down country lists in CI I created a helper for it. It can even work with the CI Validation class, so if the form is submitted and fails validation when it is redisplayed the same country is selected as the form was submitted with.</p>
<p>Download the file <a href='http://dragffy.com/blog/wp-content/uploads/2008/06/my_form_helperphp.zip'>MY_form_helper.php</a> and put it in the folder: <code>/system/application/helpers/</code>.</p>
<p>Download the file <a href='http://dragffy.com/blog/wp-content/uploads/2008/06/countriesphp.zip'>countries.php</a> and place that in <code>/system/application/config/</code>.</p>
<p>You will now be able to create drop-down lists of countries in your views like this:<br />
<code>< ?=form_countries( 'country', $this->validation->country, array( 'style' => 'width: 250px' ) )?></code></p>
<p>Ensure that you create a validation rule called &#8220;country&#8221; in your controller and that you are loading the form helper.</p>
<p><code>form_countries()</code> takes three arguments. The first is the name you would like to give the select box, this is required. The second is the country to select by default &#8211; this could be something like &#8216;GB&#8217;, or <code>$this->validation->country</code>, otherwise you can leave it blank. The third argument is any additional properties to give the select box, you can leave this blank, or pass an array. In the example above we also set the width to 250x. The country chosen by the user will be returned to the script as a two-letter ISO country code, if you are validating this then you can set the min and max length values as 2, and accept alphabetical characters only. If using MySQL as your database you will get best performance by creating a column of the type char with a length of 2.</p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/html-helper-for-generating-a-country-drop-down-list-in-codeigniter/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Profiling in CodeIgniter</title>
		<link>http://dragffy.com/blog/posts/profiling-in-codeigniter</link>
		<comments>http://dragffy.com/blog/posts/profiling-in-codeigniter#comments</comments>
		<pubDate>Tue, 06 May 2008 14:56:16 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/?p=40</guid>
		<description><![CDATA[Profiling an application is a great way to see how it is performing. CodeIgniter comes with a profiling class, which you can make calls to from your controllers. However, during development I find profiling so helpful that I want it on all my pages, without having to specifically call it each time. I also want [...]]]></description>
			<content:encoded><![CDATA[<p>Profiling an application is a great way to see how it is performing. CodeIgniter comes with a profiling class, which you can make calls to from your controllers. However, during development I find profiling so helpful that I want it on all my pages, without having to specifically call it each time. I also want to be able to deploy my development site to a production server &#8211; making calls to the profiler throughout the controllers means I would need to edit each and every controller to make sure the profiler wasn&#8217;t active on the live server.</p>
<p>After much searching I discovered a better solution. This allows you to add profiling to the bottom of every page (along with its debug info and SQL query info). When you copy the dev site live you just exclude 1 file, and profiling will be removed totally. All you need to do is create a file called <code>MY_Output.php</code> in <code>system/application/libraries</code> that extends the Output core class, with the following contents:<br />
<code><br />
< ?php<br />
# /system/application/libraries/MY_Output.php<br />
if (!defined('BASEPATH')) exit('No direct script access allowed');<br />
class MY_Output extends CI_Output {<br />
    function __construct() {<br />
        parent::__construct();<br />
        $this->enable_profiler( TRUE );<br />
    }<br />
}<br />
?><br />
</code></p>
<p>This will enable profiling output on all your pages for development and debug purposes. When you copy your site to a production server just make sure you don&#8217;t copy MY_Output.php file. I normally use rsync for copying live and just add: <code>--exclude="MY_Output.php"</code> to the rsync command.</p>
<p>The condition to using the name <code>MY_Output.php</code> is that you left the variable <code>$config['subclass_prefix']</code> in config.php as default. This defaults to <code>$config['subclass_prefix'] = 'MY_';</code>, so if you change it you will need to alter the filename of your new class.</p>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/profiling-in-codeigniter/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Protected: Learning PHP 5 &#8211; O&#8217;Reilly</title>
		<link>http://dragffy.com/blog/posts/learning-php-5-oreilly</link>
		<comments>http://dragffy.com/blog/posts/learning-php-5-oreilly#comments</comments>
		<pubDate>Mon, 10 Mar 2008 10:49:30 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/posts/learning-php-5-oreilly</guid>
		<description><![CDATA[There is no excerpt because this is a protected post.]]></description>
			<content:encoded><![CDATA[<form action="http://dragffy.com/blog/wp-pass.php" method="post">
<p>This post is password protected. To view it please enter your password below:</p>
<p><label for="pwbox-27">Password:<br />
<input name="post_password" id="pwbox-27" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="Submit" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/learning-php-5-oreilly/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Protected: Pro PHP Security</title>
		<link>http://dragffy.com/blog/posts/pro-php-security</link>
		<comments>http://dragffy.com/blog/posts/pro-php-security#comments</comments>
		<pubDate>Thu, 06 Mar 2008 15:48:50 +0000</pubDate>
		<dc:creator>Gabe</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://dragffy.com/blog/posts/pro-php-security</guid>
		<description><![CDATA[There is no excerpt because this is a protected post.]]></description>
			<content:encoded><![CDATA[<form action="http://dragffy.com/blog/wp-pass.php" method="post">
<p>This post is password protected. To view it please enter your password below:</p>
<p><label for="pwbox-21">Password:<br />
<input name="post_password" id="pwbox-21" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="Submit" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://dragffy.com/blog/posts/pro-php-security/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
