<?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>Tiffany B. Brown &#187; PHP</title>
	<atom:link href="http://tiffanybbrown.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://tiffanybbrown.com</link>
	<description>A web log about web development and internet culture with frequent detours into other stuff.</description>
	<lastBuildDate>Fri, 10 Feb 2012 23:35:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>setInterval in PHP</title>
		<link>http://tiffanybbrown.com/2011/10/25/setinterval-in-php/</link>
		<comments>http://tiffanybbrown.com/2011/10/25/setinterval-in-php/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 09:00:09 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[setinterval]]></category>
		<category><![CDATA[sleep]]></category>
		<category><![CDATA[time_nanosleep]]></category>
		<category><![CDATA[usleep]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=6418</guid>
		<description><![CDATA[JavaScript has a native method for executing a function periodically: setInterval. But in PHP, it&#8217;s a little bit harder. PHP lacks a setInterval equivalent. The closest we can get are the sleep(), usleep(), and time_nanosleep() functions. These functions delay script execution by a certain period of time (either seconds, microseconds, or a combination or seconds [...]]]></description>
			<content:encoded><![CDATA[<p>JavaScript has a native method for executing a function periodically: <a href="https://developer.mozilla.org/en/window.setInterval">setInterval</a>. But in PHP, it&#8217;s a little bit harder. PHP lacks a <code>setInterval</code> equivalent. The closest we can get are the <a href="http://php.net/sleep"><code>sleep()</code></a>, <a href="http://php.net/usleep"><code style="white-space:nowrap;text-wrap:none">usleep()</code></a>, and <a href="http://php.net/time_nanosleep"><code>time_nanosleep()</code></a> functions. These functions delay script execution by a certain period of time (either seconds, microseconds, or a combination or seconds and nanoseconds).</p>
<p>PHP does, however, have a means of executing code as long as a condition is true: the <a href="http://php.net/while"><code>while</code> loop</a>. What we can do, then is combine a <code>while</code> loop with one of the sleep functions &#8212; in this case <code>usleep()</code> &#8212; to create a <code>setInterval</code> equivalent. Check out the code below.</p>
<pre>function setInterval($func = null, $interval = 0, $times = 0){
  if( ($func == null) || (!function_exists($func)) ){
    throw new Exception('We need a valid function.');
  }

  /*
  usleep delays execution by the given number of microseconds.
  JavaScript setInterval uses milliseconds. microsecond = one
  millionth of a second. millisecond = 1/1000 of a second.
  Multiplying $interval by 1000 to mimic JS.
  */

  $seconds = $interval * 1000;

  /*
  If $times > 0, we will execute the number of times specified.
  Otherwise, we will execute until the client aborts the script.
  */

  if($times > 0){

    $i = 0;

    while($i < $times){
        call_user_func($func);
        $i++;
        usleep( $seconds );
    }
  } else {

    while(true){
        call_user_func($func); // Call the function you've defined.
        usleep( $seconds );
    }
  }
}

function doit(){
  print 'done!&lt;br&gt;';
}
</pre>
<p>To invoke, do something similar to the following.</p>
</pre>
<pre>
setInterval('doit', 5000); // Invoke every five seconds, until user aborts script.
</pre>
<pre>
setInterval('doit', 1000, 100); // Invoke every second, up to 100 times.
</pre>
<p>Here&#8217;s the catch: no data will be sent to the browser until the script has completely executed. </p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2011/10/25/setinterval-in-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Quick PHP Tip: Uploading multiple files in HTML5</title>
		<link>http://tiffanybbrown.com/2011/03/29/quick-php-tip-uploading-multiple-files-in-html5/</link>
		<comments>http://tiffanybbrown.com/2011/03/29/quick-php-tip-uploading-multiple-files-in-html5/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 08:00:51 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[(x)HTML]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[html5 forms]]></category>
		<category><![CDATA[multiple file uploads]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=5827</guid>
		<description><![CDATA[One of the neat things about HTML5 is that it allows for multiple file uploads in one file upload field. Of course, you have to have a browser that supports such a feature. Currently Opera 11.10 does. So do Firefox 4, the latest version of Chrome, and Safari 5.0.4. (Internet Explorer 9 does not.) Now [...]]]></description>
			<content:encoded><![CDATA[<p>One of the neat things about HTML5 is that it allows for multiple file uploads in one file upload field. Of course, you have to have a browser that supports such a feature. Currently Opera 11.10 does. So do Firefox 4, the latest version of Chrome, and Safari 5.0.4. (Internet Explorer 9 does not.)</p>
<p>Now what&#8217;s less clear is how to send data from multiple files to a server-side PHP script. Turns out, it&#8217;s quite easy. Treat it in the same way you&#8217;d treat any other array of options (radio buttons, for example) and include square ([]) brackets in the field name. See the code below for an example:</p>
<pre>
&lt;!DOCTYPE html&gt;
&lt;html lang="en-us"&gt;
&lt;head&gt;
	&lt;meta charset="UTF-8"&gt;
	&lt;title&gt;HTML5 Multiple File Upload&lt;/title&gt;
	&lt;link rel="stylesheet" href="s.css" media="screen"&gt;
	&lt;style media="screen"&gt;&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;form action="processor.php" method="post" enctype="multipart/form-data"&gt;
		&lt;input type="file" value="" name="upload[]" multiple&gt;
		&lt;button type="submit"&gt;Upload!&lt;/button&gt;
	&lt;/form&gt;
&lt;script&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In processor.php, all we&#8217;re going to do is print the <code>$_FILES</code> array so you can see what&#8217;s happening.</p>
<pre>
&lt;pre&gt;
&lt;?php
     print_r( $_FILES );
?&gt;
&lt;/pre&gt;
</pre>
<p>Copy and paste this code and save it to your own server to see everything in action.</p>
<h3>Related:</h3>
<ul>
<li><a href="http://dev.w3.org/html5/spec/Overview.html">HTML5 Specification</a></li>
<li><a href="http://tiffanybbrown.com/html5forms/">Slides from my recent HTML5 Forms talk</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2011/03/29/quick-php-tip-uploading-multiple-files-in-html5/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>CodeIgniter&#8217;s &#8220;Disallowed Key Characters&#8221; error revisited</title>
		<link>http://tiffanybbrown.com/2010/07/21/codeigniters-disallowed-key-characters-error-revisited/</link>
		<comments>http://tiffanybbrown.com/2010/07/21/codeigniters-disallowed-key-characters-error-revisited/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 16:19:53 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[codeigniter]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=4402</guid>
		<description><![CDATA[Two years ago, I posted about CodeIgniter&#8216;s &#8220;Disallowed Key Characters&#8221; error message, and one possible cause. Recently, I stumbled across another cause: disallowed characters in a POST array. In my case, I had single-quotes as part of the variable name. My fingers mixed up PHP array syntax and HTML form syntax. &#60;!-- will cause the [...]]]></description>
			<content:encoded><![CDATA[<p>Two years ago, I posted about <a href="http://codeigniter.com/">CodeIgniter</a>&#8216;s &#8220;Disallowed Key Characters&#8221; error message, and one <a href="http://tiffanybbrown.com/2008/05/06/debugging-tip-disallowed-key-character-error-in-codeigniter/">possible cause</a>.</p>
<p>Recently, I stumbled across another cause: <strong>disallowed characters in a POST array</strong>. In my case, I had single-quotes as part of the variable name. My fingers mixed up PHP array syntax and HTML form syntax. </p>
<pre>
&lt;!-- will cause the error --&gt;
&lt;input type="text" name="fieldname['foo']" value=""&gt; 

&lt;!-- won't cause the error. besides, this is the proper syntax. --&gt;
&lt;input type="text" name="fieldname[foo]" value=""&gt;
</pre>
<p><a href="http://tiffanybbrown.com/2008/05/06/debugging-tip-disallowed-key-character-error-in-codeigniter/#comment-61676457">kalodont</a> points out this can also happen when using accented characters, such as &oacute; or &ntilde; as keys in your array.            </p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2010/07/21/codeigniters-disallowed-key-characters-error-revisited/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Quick tips for working with Amazon S3 and PHP</title>
		<link>http://tiffanybbrown.com/2010/04/12/quick-tips-for-working-with-amazon-s3-and-php/</link>
		<comments>http://tiffanybbrown.com/2010/04/12/quick-tips-for-working-with-amazon-s3-and-php/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 20:46:55 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Donovan Schonknecht]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[uploading]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=3710</guid>
		<description><![CDATA[Try Donovan Schonknecht&#8217;s Amazon S3 PHP Class because it supports large uploads and doesn&#8217;t require PEAR. Set your Content-Disposition request header to &#8216;inline&#8217; if you want files to display in your browser rather than forcing a download Use S3::inputFile() when copying data from a source file &#8212; when uploading, for example. You don&#8217;t need to [...]]]></description>
			<content:encoded><![CDATA[<ol>
<li>Try Donovan Schonknecht&#8217;s <a href="http://undesigned.org.za/2007/10/22/amazon-s3-php-class">Amazon S3 PHP Class</a> because it supports large uploads and doesn&#8217;t require PEAR.</li>
<li>Set your <code>Content-Disposition</code> request header to &#8216;inline&#8217; if you want files to display in your browser rather than forcing a download</li>
<li>Use <code>S3::inputFile()</code> when copying data from a source file &#8212; when uploading, for example. You don&#8217;t need to use it when creating files on the fly.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2010/04/12/quick-tips-for-working-with-amazon-s3-and-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP in Arabic: An interview with Khaled Al-Shamaa</title>
		<link>http://tiffanybbrown.com/2009/11/18/php-in-arabic-an-interview-with-khaled-al-shamaa/</link>
		<comments>http://tiffanybbrown.com/2009/11/18/php-in-arabic-an-interview-with-khaled-al-shamaa/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 16:24:22 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[arabic]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[internationalization]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[localization]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=2610</guid>
		<description><![CDATA[PHP Classes interviews Khaled Al-Shamaa about his AR-PHP project, a series of PHP classes designed to handle Arabic-language web applications. Because Arabic uses a non-Latin character set, it presents a new set of challenges. PC: Developing Web applications in Arabic requires special care. What are the most important concerns and what components do you provide [...]]]></description>
			<content:encoded><![CDATA[<p>PHP Classes <a href="http://www.phpclasses.org/blog/post/107-PHP-in-Arabic.html" class="ext">interviews Khaled Al-Shamaa</a> about his <a href="http://www.ar-php.org/" class="ext">AR-PHP</a> project, a series of PHP classes designed to handle Arabic-language web applications. Because Arabic uses a non-Latin character set, it presents a new set of challenges. </p>
<blockquote><p>
<b>PC: </b> Developing Web applications in Arabic requires special care. What are the most important concerns and what components do you provide to address those concerns?</p>
<p><b>KA:</b>  Besides the search issue presented above, some of Arab countries use Hijri calendar instead of Gregorian calendar. So I developed classes to convert dates between those two calendars, as well as an Arabic version from date and strtotime PHP functions. &#8230; Another issue that is handled in this project is related to rendering Arabic text correctly in some libraries like GD, PDF, SWF and even VRML.</p></blockquote>
<p>This interested me simply because it raises awarness of cultural, linguistic, and character set challenges that monolingual developers, or Western character set developers don&#8217;t often think about. [Via <a href="http://www.phpdeveloper.org/news/13547">PHP Developer</a>]</p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2009/11/18/php-in-arabic-an-interview-with-khaled-al-shamaa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PHP quickie] Select a certain number of words from a string</title>
		<link>http://tiffanybbrown.com/2009/03/26/php-quickie-select-a-certain-number-of-words-from-a-string/</link>
		<comments>http://tiffanybbrown.com/2009/03/26/php-quickie-select-a-certain-number-of-words-from-a-string/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 13:38:28 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[string manipulation]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=1893</guid>
		<description><![CDATA[An alternative to subst() that selects entire words rather than a specified number of characters. I used this on a recent project where I needed to create a meta tag description from text and HTML stored in a database. Uses PHP&#8217;s native str_word_count() function. function select_number_of_words($input,$number_of_words){ $output = ''; $input = strip_tags($input); $input = str_word_count($input,1); [...]]]></description>
			<content:encoded><![CDATA[<p>An alternative to <a href="http://us2.php.net/manual/en/function.substr.php"><code>subst()</code></a> that selects entire words rather than a specified number of characters. I used this on a recent project where I needed to create a meta tag description from text and HTML stored in a database.</p>
<p>Uses PHP&#8217;s native <a href="http://us2.php.net/manual/en/function.str-word-count.php"><code>str_word_count()</code> function</a>.</p>
<pre>
function select_number_of_words($input,$number_of_words){
	$output = '';
	$input = strip_tags($input);
	$input = str_word_count($input,1);  // second parameter returns the string as an array.
	for($i=0; $i< $number_of_words; $i++){
		$output .=$input[$i].' ';
	}
	return trim($output); // cut off the last space.
}
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2009/03/26/php-quickie-select-a-certain-number-of-words-from-a-string/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP: Sorting arrays randomly with array_randsort()</title>
		<link>http://tiffanybbrown.com/2009/03/11/php-sorting-arrays-randomly-with-array_randsort/</link>
		<comments>http://tiffanybbrown.com/2009/03/11/php-sorting-arrays-randomly-with-array_randsort/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 16:18:31 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=1881</guid>
		<description><![CDATA[Or, you know, just use the shuffle() function. Kim points out the drawbacks of shuffle in the comments below. A custom PHP function. This function will return an array that&#8217;s been resorted in a random order. Supports both numerically-indexed and associative arrays. Uses PHP&#8217;s native array_rand() function. function array_randsort($array,$preserve_keys=false){ /*-------------------------------------/ Preserving the keys works best [...]]]></description>
			<content:encoded><![CDATA[<p class="editors-note">Or, you know, just use the <a href="http://us3.php.net/shuffle"><code>shuffle()</code> function</a>. Kim points out the drawbacks of shuffle in the comments below.</p>
<p>A custom PHP function. This function will return an array that&#8217;s been resorted in a random order. Supports both numerically-indexed and associative arrays. Uses PHP&#8217;s native <a href="http://us.php.net/manual/en/function.array-rand.php"><code>array_rand()</code></a> function.</p>
<pre>
function array_randsort($array,$preserve_keys=false){
	/*-------------------------------------/
	Preserving the keys works best with associative arrays.
	If you choose to preserve keys on a numerically-indexed or
    mixed-indexed array, use a foreach loop rather than a for loop
    to preserve the sorted order.
	/-------------------------------------*/

	if(!is_array($array)):
		exit('Supplied argument is not a valid array.');
	else:
		$i = NULL;

		// how long is the array?
		$array_length = count($array); 

		// Sorts the array keys in a random order.
		$randomize_array_keys = array_rand($array,$array_length);

		// if we are preserving the keys ...
		if($preserve_keys===true) {
			// reorganize the original array in a new array
			foreach($randomize_array_keys as $k=>$v){
				$randsort[$randomize_array_keys[$k]] = $array[$randomize_array_keys[$k]];
			}
		} else {
			// reorganize the original array in a new array
			for($i=0; $i < $array_length; $i++){
				$randsort[$i] = $array[$randomize_array_keys[$i]];
			}
		}
		return $randsort;
	endif;
}
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2009/03/11/php-sorting-arrays-randomly-with-array_randsort/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Collecting e-commerce conversion data with Zen Cart and Google Analytics</title>
		<link>http://tiffanybbrown.com/2009/02/19/zen-cart-and-google-analytics/</link>
		<comments>http://tiffanybbrown.com/2009/02/19/zen-cart-and-google-analytics/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 09:00:44 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[MySQL / Databases]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[analytics]]></category>
		<category><![CDATA[ecommerce]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[online shopping]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[zen cart]]></category>
		<category><![CDATA[zencart]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=1785</guid>
		<description><![CDATA[Google Analytics allows you to collect pretty robust data about how users move through your e-commerce site. Here&#8217;s how to make it work with Zen Cart, an open source shopping cart. For this tutorial, you will need: A Zen Cart-based shopping cart A Google Analytics account and the tracking code for both conversions and page [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://google.com/analytics">Google Analytics</a> allows you to collect pretty robust data about how users move through your e-commerce site. Here&#8217;s how to make it work with <a href="http://www.zen-cart.com/">Zen Cart</a>, an open source shopping cart.</p>
<p>For this tutorial, you will need:</p>
<ul>
<li>A Zen Cart-based shopping cart</li>
<li>A Google Analytics account and the tracking code for both conversions and page views.</li>
<li>Experience with <a href="http://www.php.net/">PHP</a> and <a href="http://dev.mysql.com/">MySQL</a> programming</li>
</ul>
<p>Also check out Google&#8217;s support article <a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&#038;answer=55528">How do I track e-commerce transactions?</a> and become <abbr title="best friends forever">BFF</abbr>s with the <a href="http://www.zen-cart.com/wiki/" class="ext">Zen Cart wiki</a>. </p>
<h2>Creating a custom functions file</h2>
<p>Create a file to <a href="http://www.zen-cart.com/wiki/index.php/Customisation_-_Templates#Automatically_included_files">house your custom functions</a>. Name it whatever you&#8217;d like (with a PHP extension, of course). Put it in your includes/functions/extra_functions/ directory. </p>
<p class="editors-note">A word of caution: I created these functions with my own SQL, outside of the Zen Cart framework. There may be a better way to do it.</p>
<p>In the file you created above, add the following code:</p>
<pre>
# get the product ID out of session key
function custom_get_prodId($productkey){
	$pid = explode(':',$productkey);
	return $pid[0];
}

#get the product data
function custom_get_product($prodID,$return='all'){
	global $db;
	reset($data);
	$q = sprintf("SELECT
			pd.products_name,
			pd.products_description,
			cd.categories_name, p.products_price
			FROM categories_description AS cd, products AS p, products_description AS pd
	 		WHERE  p.products_id = 183
   				AND p.master_categories_id = cd.categories_id
   				AND p.products_id = pd.products_id",$prodID);
	$res = $db->Execute($q);
	return $res->fields;
}
# get the current user's data
function custom_get_userinfo($custID){
	global $db;
	reset($data);
	$q = sprintf("SELECT
			ab.entry_street_address,
			ab.entry_postcode,
			ab.entry_city,
			ab.entry_state,
			c.countries_name,
			c.countries_iso_code_2
			FROM address_book AS ab, countries AS c
			WHERE customers_id=%d
			   AND ab.entry_country_id = c.countries_id
				  ",(int)$custID);
	$res = $db->Execute($q);
	return $res->fields;
}
</pre>
<p>Adjust the names of the tables if you have added a custom table prefix during your Zen Cart configuration. We&#8217;ll use these functions to get us the user data and product data we need. </p>
<h2>Edit the checkout success and global footer files</h2>
<p>Add the conversion tracking code &#8212; provided by Google Analytics &#8212; to the checkout success page template. It&#8217;s located in your templates directory, includes/templates/YOUR_TEMPLATE_DIR/templates/tpl_checkout_success_default.php.</p>
<p>Also add the regular Google Analytics tracking code to your footer file (found in includes/templates/YOUR_TEMPLATE_DIR/common/tpl_footer.php).</p>
<p><em>Below your Google Analytics code</em>, but also in your footer file, add the code below.</p>
<pre>
&lt;?php
# do this on the checkout success page only.
if($_GET['main_page'] == 'checkout_success'): 

$userdata = $_SESSION['cart'];
$moreud = custom_get_userinfo($_SESSION['customer_id']);
?&gt;
&lt;script type="text/javascript"&gt;
pageTracker._addTrans(
    "&lt;?=$userdata-&gt;cartID; ?&gt;",
    "www.YOURDOMAINNAME.com",
    "&lt;?=$userdata-&gt;total; ?&gt;",
    "",
    "&lt;?=$_SESSION['shipping']['cost']; ?&gt;",
    "&lt;?=$moreud['entry_city'];?&gt;",
    "&lt;?=$moreud['entry_state'];?&gt;",
    "&lt;?=$moreud['countries_name'];?&gt;"
  );
&lt;?
# for each product ID key in the userdata session
foreach($userdata-&gt;contents as $k=&gt;$v):
	/*
	the product id gets stored as an array key as xxx:funkymd5key
	ex: 183:fw920e8ktw327uio67xew9mn. custom_get_prodId extracts
	the product id part of that key.
	*/
	$pid = custom_get_prodId($k);
	$data = custom_get_product($pid,'all');
?&gt;

 pageTracker._addItem(
    "&lt;?=$userdata-&gt;cartID; ?&gt;",
    "&lt;?=getProdId($k); ?&gt;",
    "&lt;?=strip_tags($data['products_name']);?&gt;",
    "&lt;?=$data['categories_name'];?&gt;",
    "&lt;?=number_format($data['products_price'],2);?&gt;",
    "&lt;?=$v['qty']; ?&gt;"
  );
&lt;? endforeach; ?&gt;
pageTracker._trackTrans();
&lt;/script&gt;

&lt;?php endif;
} // flag_disable_footer
?&gt;
</pre>
<div class="editors-note">Providing this code with the following disclaimers: </p>
<ol>
<li>It may not work for you. </li>
<li>I&#8217;m not responsible if it does.</li>
<li>I can&#8217;t offer personalized support.</li>
</ol>
<p>In short: you&#8217;re on your own.
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2009/02/19/zen-cart-and-google-analytics/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Simple pagination for arrays with PHP 5</title>
		<link>http://tiffanybbrown.com/2008/12/14/simple-pagination-for-arrays-with-php-5/</link>
		<comments>http://tiffanybbrown.com/2008/12/14/simple-pagination-for-arrays-with-php-5/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 04:16:58 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=1646</guid>
		<description><![CDATA[While working on a recent project, I had to build a feature that displayed a list of files available in a directory. A simple way is just to use scandir() and a foreach loop to spit out a pretty list. There&#8217;s a small problem though: long lists aren&#8217;t all that user friendly. I decided instead [...]]]></description>
			<content:encoded><![CDATA[<p>While working on a recent project, I had to build a feature that displayed a list of files available in a directory. A simple way is just to use <code>scandir()</code> and a <code>foreach</code> loop to spit out a pretty list. </p>
<p>There&#8217;s a small problem though: long lists aren&#8217;t all that user friendly. I decided instead to paginate the results. Here&#8217;s one way to do it using PHP 5:<br />
<span id="more-1646"></span></p>
<h2>Step 1: Read the directory</h2>
<pre>
/*
 * scandir is only available in PHP 5 or higher.
 * It returns an array of ALL available files in the
 * specified directory
*/

$allfiles = scandir('/directory/to/scan/');
</pre>
<p>Now we don&#8217;t want to display <em>every</em> file. Some files are system files. Some files may not be the right format. Here, we&#8217;re going to eliminate any file name that starts with a period.</p>
<pre>
# intialize a new array of files that we want to show
$goodfiles = array();

# add a file to the $goodfiles array if its name doesn't begin with a period
foreach($allfiles as $f){
	if(strpos($f,'.')!==0){
		array_push($goodfiles,$f);
	}
}
</pre>
<h3>Step 2: Split it! Split it good!</h3>
<p>Now we get to the heart of things: determining how many pages there will be and how many items we&#8217;ll show per page. It&#8217;s remarkably simple thanks to PHP&#8217;s <code>array_chunk()</code> function. The <code>array_chunk </code> function takes two parameters: the array that you want to split, and the number of units that should be in each set.</p>
<pre>$pages = array_chunk($goodfiles, 5);</pre>
<p>This produces a multidimensional array which, if we <code>print_r</code> it, looks a bit like this (let&#8217;s assume we have 13 files in the directory).</p>
<pre>
Array
(
    [0] => Array
        (
            [0] => About_RFSB06WEB.flv
            [1] => Kids_Excited.flv
            [2] => Kids_Start_Run.flv
            [3] => Kids_start.jpg
            [4] => Kids_start_sm.jpg
        )

    [1] => Array
        (
            [0] => image01.jpg
            [1] => image02.jpg
            [2] => image03.jpg
            [3] => image04.jpg
            [4] => image05.jpg
        )

    [2] => Array
        (
            [0] => image06.jpg
            [1] => image07.jpg
            [2] => image08.jpg
        )
)
</pre>
<p>Each parent array is a page. Each child array is the content for that page. Now we just have to specify which page we want to view. In this example, we&#8217;re going to pass the desired page to the script as part of a query string &#8212; <code class="nowrap">showfiles.php?showpage=1</code>. </p>
<h3>Step 3: Linking up</h3>
<p>So now that our array is all split and chunked, we can build our page links. As I explained earlier, using <code>array_chunk()</code> creates our &#8216;pages.&#8217; To build our pagination navigation, then, we just need to create as many links as there are pages. Let&#8217;s do this with a for loop.</p>
<pre>
&lt;? for($i=1; $i< count($pages)+1; $i++): ?&gt;
     &lt;a href="showfiles.php?showpage=&lt;? echo $i;?&gt;"&lt;&lt;? echo $i; ?&gt;&lt;/a&gt;
&lt;? endfor; ?&gt;
</pre>
<p>Remember that we're doing a page count, so we want to start at one (not zero). Now it's just a matter of grabbing the variable's value to specify which array to show. We're grabbing that value from the query string in the URL.</p>
</pre>
<pre>
$pgkey = (int)$_GET['showpage']; // forces $_GET['showpage'] to be an integer
$pages[$pgkey];
</pre>
<p>If you want to highlight which page the user is on, add if / else logic to check whether the value of <code>$i</code> is the same as the value of <code>$_GET['showpage']</code> and apply a style or CSS class name. </p>
<h3>Step 4: Showing the files</h3>
<p>The final step is to show the files on each page. Simply use a foreach loop.</p>
<pre>foreach($pages[$pgkey] as $file){ echo $file.'&lt;br /&gt;'; }</pre>
<p>This is a technique that you could conceivably use to display <em>any</em> array data across pages. </p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2008/12/14/simple-pagination-for-arrays-with-php-5/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>Atlanta, GA: php&#124;works and PyWorks</title>
		<link>http://tiffanybbrown.com/2008/07/18/atlanta-ga-phpworks-and-pyworks/</link>
		<comments>http://tiffanybbrown.com/2008/07/18/atlanta-ga-phpworks-and-pyworks/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 15:49:48 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech Events]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/2008/07/18/atlanta-ga-phpworks-and-pyworks/</guid>
		<description><![CDATA[Marco Tabini &#38; Associates, publishers of PHP Architect and Python Magazine are bringing their php&#124;works conference back to Atlanta this fall, November 12th through 14th, 2008. This year, though, the conference has an added bonus: PyWorks, a conference devoted to Python. Registering for one conference allows you to attend both. Both conferences have an open [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://tiffanybbrown.com/images/uploads/2008/phpandpy.png" alt="" class="rightimg"/><br />
Marco Tabini &amp; Associates, publishers of <a href="http://www.phparch.com/">PHP Architect</a> and <a href="http://pymag.phparch.com/">Python Magazine</a> are bringing their <a href="http://phpworks.mtacon.com/" class="b">php|works</a> conference back to Atlanta this fall, <b class="event-date">November 12th through 14th, 2008</b>. </p>
<p>This year, though, the conference has an added bonus: <a href="http://pyworks.mtacon.com/" class="b">PyWorks</a>, a conference devoted to Python. Registering for one conference allows you to attend both. </p>
<p>Both conferences have an open call for papers, which ends July 25, 2008. Registration costs $599 (discounts are available).</p>
<p><a href="http://tiffanybbrown.com/tag/tech+events/feed/"><b>RSS:</b> Tech Events</a></p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2008/07/18/atlanta-ga-phpworks-and-pyworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debugging tip: &#8220;Disallowed Key Character&#8221; error in CodeIgniter</title>
		<link>http://tiffanybbrown.com/2008/05/06/debugging-tip-disallowed-key-character-error-in-codeigniter/</link>
		<comments>http://tiffanybbrown.com/2008/05/06/debugging-tip-disallowed-key-character-error-in-codeigniter/#comments</comments>
		<pubDate>Tue, 06 May 2008 21:24:17 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development & Programming]]></category>
		<category><![CDATA[carriage return]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[line breaks]]></category>
		<category><![CDATA[line feed]]></category>
		<category><![CDATA[whitespace]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/?p=1285</guid>
		<description><![CDATA[After 6 hours of massive anxiety, stress, near tears, one pound on my desk, and some hair pulling, I tracked down the source of a nagging Disallowed Key Character error that I received while using CodeIgniter: an extra line break. The line feed (LF) and carriage return (CR) characters (and their hex code equivalents (%0D [...]]]></description>
			<content:encoded><![CDATA[<p>After 6 hours of massive anxiety, stress, near tears, one pound on my desk, and some hair pulling, I tracked down the source of a nagging <strong>Disallowed Key Character</strong> error that I received while using <a href="http://www.codeigniter.com/">CodeIgniter</a>: <strong>an extra line break</strong>.</p>
<p>The line feed (LF) and carriage return (CR) characters (and their hex code equivalents (%0D and %0A) are forbidden in CodeIgniter&#8217;s framework. The hard part is tracking down exactly <em>where</em> that extra line break character lives.</p>
<p>In my case, there was an extra line of blank, barren, not-all-that-obvious white space at the very, very end of one of my controller files, just <em>after</em> the closing <code>?&gt;</code>. </p>
<h3>Related:</h3>
<ul>
<li><a href="http://tiffanybbrown.com/2005/02/15/php_header_error_messages/">PHP header error messages</a></li>
<li><a href="http://tiffanybbrown.com/2006/03/21/four_common_p_h_p_errors_and_what_they_mean/">Four common P H P errors and what they mean</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2008/05/06/debugging-tip-disallowed-key-character-error-in-codeigniter/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Turn text files into pull down menus</title>
		<link>http://tiffanybbrown.com/2008/02/26/turn-text-files-into-pull-down-menus/</link>
		<comments>http://tiffanybbrown.com/2008/02/26/turn-text-files-into-pull-down-menus/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 02:16:43 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[drop down menu]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[pull down menu]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/2008/02/26/turn-text-files-into-pull-down-menus/</guid>
		<description><![CDATA[UPDATE: This could also be done with the foreach() construct, but here &#8212; on my set-up at least &#8212; the for loop is a teensy bit faster. I developed this PHP function for a project I&#8217;m working on. I&#8217;m posting it here in case I need it again, or in case you find it handy. [...]]]></description>
			<content:encoded><![CDATA[<p class="editors-note"><b>UPDATE:</b> This could also be done with the <code>foreach()</code> construct, but here &#8212; on my set-up at least &#8212; the <code>for</code> loop is a teensy bit faster.</p>
<p>I developed this PHP function for a project I&#8217;m working on. I&#8217;m posting it here in case I need it again, or in case you find it handy.</p>
<pre>
#Input text files must contain one item per line
function print_menu($txtfile_or_files){
	$args = func_get_args();
	$num_args = func_num_args();
	$input = array();

	for($i = 0; $i &lt; $num_args; $i++){
		// get contents of each text file specified
		$lines = file($args[$i]); 

		// get each line from each file an add to array
		for($j = 0; $j &lt; count($lines); $j++){
			array_push($input,$lines[$j]);
		}
	}
	// sort alphabetically
	sort($input,SORT_STRING);		

	for($i = 0; $i &lt; count($input); $i++){
		$value = str_replace(' ','_',strtolower(trim($input[$i])));
		echo '&lt;option value="'.$value.'"&gt;'.trim($input[$i])."&lt;/option&gt;\n";
	}
}
</pre>
<h3>Configuration and use</h3>
<p>The variable <code>$txtfile_or_files</code> should be a comma-separated list of paths to plain text files. This function accepts multiple arguments, in case you want to string multiple files into one menu.</p>
<p>Each text file should contain one item per line. For example:</p>
<pre>
Red
Blue
Orange
Green
</pre>
<p>Add another line or two of code if you need to indicate whether the form field value has already been selected.</p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2008/02/26/turn-text-files-into-pull-down-menus/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Review: Learning PHP Data Objects by Dennis Popel</title>
		<link>http://tiffanybbrown.com/2007/10/23/review-learning-php-data-objects-by-dennis-popel/</link>
		<comments>http://tiffanybbrown.com/2007/10/23/review-learning-php-data-objects-by-dennis-popel/#comments</comments>
		<pubDate>Tue, 23 Oct 2007 05:01:56 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[MySQL / Databases]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[pdo]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/2007/10/23/review-learning-php-data-objects-by-dennis-popel/</guid>
		<description><![CDATA[Packt Publishing graciously provided me with a copy of this book to review. PHP supports more than a dozen database setups, including the SQLite library bundled with PHP 5. That&#8217;s a lot of databases, and each one has its own connection syntax and server-specific functions. So what happens when you want to be able to [...]]]></description>
			<content:encoded><![CDATA[<p span class="editors-note">Packt Publishing graciously provided me with a copy of this book to review.</p>
<p><img src='http://tiffanybbrown.com/images/uploads/2007/10/learningpdo.jpg' alt='Learning P H P Data Objects' class="rightimg" /> PHP supports more than a dozen database setups, including the <a href="http://sqlite.org/">SQLite</a> library bundled with PHP 5. That&#8217;s a lot of databases, and each one has its own connection syntax and server-specific functions. </p>
<p>So what happens when you want to be able to swap one database for another? You turn to an abstraction library, such as <a href="http://php.net/pdo"><abbr title="PHP Data Objects">PDO</abbr></a>.
</p>
<p>In <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.com%2FLearning-Data-Objects-Dennis-Poppel%2Fdp%2F1847192661%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1193074907%26sr%3D8-1&#038;tag=webinista-20&#038;linkCode=ur2&#038;camp=1789&#038;creative=9325" class="book title">Learning PHP Data Objects</a><img src="http://www.assoc-amazon.com/e/ir?t=webinista-20&amp;l=ur2&amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Dennis Popel takes you through the process of building an application using <abbr class="say">PDO</abbr> with My<abbr class="say">SQL</abbr> and SQLite.</p>
<p>Aimed squarely at PHP developers who are new to <abbr class="say">PDO</abbr>, Popel covers how to make connections, handle errors, and use prepared statements with <abbr class="say">PDO</abbr>. He also discusses transactions, <a href="http://en.wikipedia.org/wiki/Model-view-controller"><abbr title="Model-View-Controller">MVC</abbr> development</a>, and the appropriateness of using PDO versus other abstraction libraries.</p>
<p>Where <span class="book title">Learning PHP Data Objects</span> shines,  however is in its code examples. They are easy to follow, and Popel smartly alerts readers to potential gotchas in developing the sample application.</p>
<p>The book assumes an understanding of <abbr title="Object-oriented P H P">OOPHP</abbr> &#8212; necessary because PDO is entirely object-oriented. To get the most out of it, you should be familiar with object-oriented principles and syntax. While Appendix A does give readers a quick overview of <abbr class="say">OOPHP</abbr>, for a more thorough treatment, you&#8217;ll need to look elsewhere.</p>
<p>It&#8217;s a solid, though not quite perfect book. For example, Popel only sort-of mentions a potentially huge gotcha: when you may need to specify a <a href="http://tiffanybbrown.com/2007/10/22/solution-for-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-error-when-using-pdo/">unix_socket parameter</a> in the connection string. It&#8217;s a problem I think would be common enough and confusing enough to discuss and demonstrate. I also think Popel could have been a bit clearer about when and why to use <code>PDOStatement->closeCursor()</code>.</p>
<p>Those are minor quibbles however, easily solved by consulting the documentation or doing a Google search. Overall, this book is nice introduction to the whys and hows of using PDO to develop database driven applications.</p>
<div class="quickfacts">
<h3>Quick facts</h3>
<ul>
<li class="book title">Learning PHP Data Objects</li>
<li class="book author">By Dennis Popel</li>
<li class="book publisher"><a href="http://www.packtpub.com/">Packt Publishing</a></li>
<li class="book release">September 2007</li>
<li class="book price">$39.99</li>
<li>ISBN number: <span class="ISBN">978-1-847192-66-0</span></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2007/10/23/review-learning-php-data-objects-by-dennis-popel/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Solution for &#8220;Can&#8217;t connect to local MySQL server through socket &#8216;/tmp/mysql.sock&#8217;&#8221; error when using PDO</title>
		<link>http://tiffanybbrown.com/2007/10/22/solution-for-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-error-when-using-pdo/</link>
		<comments>http://tiffanybbrown.com/2007/10/22/solution-for-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-error-when-using-pdo/#comments</comments>
		<pubDate>Mon, 22 Oct 2007 14:54:34 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[MySQL / Databases]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pdo]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/2007/10/22/solution-for-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-error-when-using-pdo/</guid>
		<description><![CDATA[If you&#8217;re trying to get up-and-running with PDO, you may experience a &#8220;Can&#8217;t connect to local MySQL server through socket &#8216;/tmp/mysql.sock&#8217;&#8221; error when trying to connect to your database, even if your php.ini and my.cnf files contain a different default socket path for MySQL. It&#8217;s counterintuitive to a degree, but it&#8217;s actually expected behavior. The [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re trying to get up-and-running with <abbr title="P H P Data Objects">PDO</abbr>, you may experience a &#8220;Can&#8217;t connect to local MySQL server through socket &#8216;/tmp/mysql.sock&#8217;&#8221; error when trying to connect to your database, even if your php.ini and my.cnf files contain a different default socket path for MySQL.</p>
<p>It&#8217;s counterintuitive to a degree, but it&#8217;s actually expected behavior. The good news is that <a href="http://osdir.com/ml/php.pecl.devel/2006-11/msg00019.html">the fix</a> is easy. Simply include the unix socket path in your connection string. </p>
<pre>
$connection = new PDO("mysql:host=localhost;dbname=test;unix_socket=/path/to/socket/found_in_php.ini_or_my.cnf",'username','password');
</pre>
<p><b>Related:</b> Notes from &#8220;<a href="http://tiffanybbrown.com/2006/06/16/nyphp-con-introduction-to-pdo/">Introduction to PDO</a>,&#8221; a talk by Ilia Alshanetsky at NYPHPCon 2006.</p>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2007/10/22/solution-for-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-error-when-using-pdo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Atlanta, Ga: php&#124;works 2007</title>
		<link>http://tiffanybbrown.com/2007/08/15/atlanta-ga-phpworks-2007/</link>
		<comments>http://tiffanybbrown.com/2007/08/15/atlanta-ga-phpworks-2007/#comments</comments>
		<pubDate>Wed, 15 Aug 2007 17:39:13 +0000</pubDate>
		<dc:creator>tiffany</dc:creator>
				<category><![CDATA[Atlanta]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech Events]]></category>
		<category><![CDATA[Web Development & Programming]]></category>

		<guid isPermaLink="false">http://tiffanybbrown.com/2007/08/15/atlanta-ga-phpworks-2007/</guid>
		<description><![CDATA[Local PHP geeks rejoice! php&#124;works 2007 is happening in our neck of the woods in about a month. Speakers include Atlanta PHP founder Ben Ramsey, PHP guru Sara Goleman and security expert Chris Shiflett. Event details When: Sept 13 &#8211; 14, 2007 Where: Sheraton Gateway Hotel How much: US$650 and $200 for the tutorial add-on. [...]]]></description>
			<content:encoded><![CDATA[<p>Local PHP geeks rejoice! php|works 2007 is happening in our neck of the woods in about a month. Speakers include <a href="http://www.atlantaphp.org/">Atlanta PHP</a> founder <a href="http://benramsey.com/">Ben Ramsey</a>, PHP guru <a href="http://blog.libssh2.org/">Sara Goleman</a> and security expert <a href="http://shiflett.org/">Chris Shiflett</a>.</p>
<div class="event-details">
<h3>Event details</h3>
<ul>
<li>When: Sept 13 &#8211; 14, 2007</li>
<li>Where: <a href="http://www.starwoodhotels.com/sheraton/property/overview/index.html?propertyID=48&#038;requestedChainCode=SI&#038;requestedAffiliationCode=SI&#038;localeCode=en_US&#038;language=en_US&#038;">Sheraton Gateway Hotel</a></li>
<li>How much: US$650 and $200 for the tutorial add-on. Discounts available for students, non-profits, educators and groups</li>
<li><a href="http://works.phparch.com/c/p/index">More info</a></li>
</ul>
</div>
<h3>Related entries</h3>
<ul>
<li><a href="http://tiffanybbrown.com/2007/03/29/atlanta-ga-apachecon-us-2007/">Atlanta, GA: ApacheCon US 2007</a></li>
<li><a href="http://tiffanybbrown.com/2007/08/07/dallas-tx-webmaster-jam-session/">Dallas, TX: Webmaster Jam Session</a></li>
<li><a href="http://tiffanybbrown.com/2007/04/02/santa-clara-ca-ajaxworld-conference-expo/">Santa Clara, CA: AJAXWorld Conference &#038; Expo</a></li>
<li><a href="http://tiffanybbrown.com/2007/06/28/future-of-web-design-new-york/">New York City: Future of Web Design</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tiffanybbrown.com/2007/08/15/atlanta-ga-phpworks-2007/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

