<?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>Home of Peter Haza &#187; PHP</title>
	<atom:link href="http://blog.peterhaza.no/category/programming/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.peterhaza.no</link>
	<description>Opinions on most things</description>
	<lastBuildDate>Sat, 28 Nov 2009 12:36:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Using lists instead of tables with sfGuardAuth</title>
		<link>http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/</link>
		<comments>http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/#comments</comments>
		<pubDate>Tue, 13 May 2008 12:25:41 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/?p=43</guid>
		<description><![CDATA[For some reason, symfony 1.1&#8242;s new sfForm class is using sfWidgetFormSchemaFormatterTable by default, instead of sfWidgetFormSchemaFormatterList. This means that you get a form based on tables, while I prefer to think of my form as a list to fill in. To change this you can use this chain: $form-&#62;getWidgetSchema()-&#62;setFormFormatterName('list'); The question is, &#8220;where do you [...]]]></description>
			<content:encoded><![CDATA[<p>For some reason, <a href="http://www.symfony-project.org/" onclick="pageTracker._trackPageview('/outgoing/www.symfony-project.org/?referer=');">symfony</a> 1.1&#8242;s new sfForm class is using sfWidgetFormSchemaFormatterTable by default, instead of sfWidgetFormSchemaFormatterList. This means that you get a form based on 
tables, while I prefer to think of my form as a list to fill in. To change this you can use this chain:</p>

<pre><code>$form-&gt;getWidgetSchema()-&gt;setFormFormatterName('list');
</code></pre>

<p>The question is, &#8220;where do you put this to alter sfGuard&#8217;s login form?&#8221;</p>

<p><span id="more-43"></span></p>

<p>In the case of sfGuard you just need to create a new folder under apps/<em>frontend</em>/modules/ (replace frontend with your app name) called sfGuardAuth, in this you create a folder called actions, and within this again a file called actions.class.php.</p>

<pre><code>apps/
-frontend/
--modules/
---sfGuardAuth/
----actions/
-----actions.class.php
</code></pre>

<p>Inside the actions.class.php file you put this:</p>

<pre><code>&lt;?php
    require_once sfConfig::get('sf_plugins_dir').
    '/sfGuardDoctrinePlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php';

/**
* Extend to use list schema formatter
*/
class sfGuardAuthActions extends BasesfGuardAuthActions
{
    public function executeSignin($request)
    {
        parent::executeSignin($request);
        $this-&gt;form-&gt;getWidgetSchema()-&gt;setFormFormatterName('List');
    }
}
?&gt;
</code></pre>

<p>We manually include BasesfGuardAuthActions.class.php because symfony&#8217;s black magic autoloader doesn&#8217;t pick this up. Voila. Nice and easy!</p>

<p>If you wanna make your completely own sfWidgetFormSchemaFormatter you can read about it over at <a href="http://notjosh.com/blog/archives/53-Symfony-1.1-Form-Templating.html" onclick="pageTracker._trackPageview('/outgoing/notjosh.com/blog/archives/53-Symfony-1.1-Form-Templating.html?referer=');">notjosh&#8217;s blog</a>.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;title=Using+lists+instead+of+tables+with+sfGuardAuth" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_title=Using+lists+instead+of+tables+with+sfGuardAuth&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;t=Using+lists+instead+of+tables+with+sfGuardAuth" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_t=Using+lists+instead+of+tables+with+sfGuardAuth&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;title=Using+lists+instead+of+tables+with+sfGuardAuth" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_title=Using+lists+instead+of+tables+with+sfGuardAuth&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;title=Using+lists+instead+of+tables+with+sfGuardAuth" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_title=Using+lists+instead+of+tables+with+sfGuardAuth&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Using+lists+instead+of+tables+with+sfGuardAuth+-+http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Using+lists+instead+of+tables+with+sfGuardAuth+-+http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/&amp;title=Using+lists+instead+of+tables+with+sfGuardAuth" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/_amp_title=Using+lists+instead+of+tables+with+sfGuardAuth&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Using%20lists%20instead%20of%20tables%20with%20sfGuardAuth%22&amp;body=Link: http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A For%20some%20reason%2C%20%5Bsymfony%5D%5B%5D%201.1%27s%20new%20sfForm%20class%20is%20using%20sfWidgetFormSchemaFormatterTable%20by%20default%2C%20instead%20of%20sfWidgetFormSchemaFormatterList.%20This%20means%20that%20you%20get%20a%20form%20based%20on%20%0Atables%2C%20while%20I%20prefer%20to%20think%20of%20my%20form%20as%20a%20list%20to%20fill%20in.%20To%20change%20this%20you%20can%20use%20this%20chain%3A%0A%0A%20%20%20%20" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/using-lists-instead-of-tables-with-sfguardauth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony, a PHP web application framework</title>
		<link>http://blog.peterhaza.no/symfony-a-php-web-application-framework/</link>
		<comments>http://blog.peterhaza.no/symfony-a-php-web-application-framework/#comments</comments>
		<pubDate>Mon, 12 May 2008 09:43:33 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/?p=42</guid>
		<description><![CDATA[Recently I made a library for a client which needed database access, cache and configuration. For this I decided to try Zend Framework for the first time. ZF was excellent for this, because you can cherry-pick what components you want, without having to include everything. For my next project however I&#8217;m going to build a [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I made a library for a client which needed database access, cache and configuration. For this I decided to try <a href="http://framework.zend.com/" onclick="pageTracker._trackPageview('/outgoing/framework.zend.com/?referer=');">Zend Framework</a> for the first time. ZF was excellent for this, because you can cherry-pick what components you want, without having to include everything. For my next project however I&#8217;m going to build a full-scale application, and for this I prefer something more tightly coupled. <a href="http://www.symfony-project.com" onclick="pageTracker._trackPageview('/outgoing/www.symfony-project.com?referer=');">Symfony</a> to the rescue.</p>

<p><span id="more-42"></span></p>

<p>For anyone who has played with <a href="http://rubyonrails.com/" onclick="pageTracker._trackPageview('/outgoing/rubyonrails.com/?referer=');">Ruby on Rails</a>, symfony will be very familiar. You got a nice command line interface to do your scaffolding, migrations and application building, and of course the well-known and diffuse <a href="http://en.wikipedia.org/wiki/Model-view-controller" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Model-view-controller?referer=');">MVC</a> coding paradigm to seperate business logic from presentation.</p>

<p>Symfony is very <a href="http://www.symfony-project.org/doc/1_0/" onclick="pageTracker._trackPageview('/outgoing/www.symfony-project.org/doc/1_0/?referer=');">well documented</a> in english, something I didn&#8217;t expect as the author company, <a href="http://www.sensiolabs.com/en" onclick="pageTracker._trackPageview('/outgoing/www.sensiolabs.com/en?referer=');">Sensio labs</a> is a french web development company. It totally blew me away.</p>

<p>You do your configuration in <a href="http://en.wikipedia.org/wiki/XML" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/XML?referer=');">XML</a> or <a href="http://en.wikipedia.org/wiki/YAML" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/YAML?referer=');">YAML</a> whereas the latter is recommended because it&#8217;s alot easier on the eye.</p>

<p>So far I&#8217;ve only scratched the surface of symfony, but as I&#8217;m doing a full-scale application in symfony these days, I expect to get more familiar and have more to present later.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/symfony-a-php-web-application-framework/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;title=Symfony%2C+a+PHP+web+application+framework" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_title=Symfony_2C+a+PHP+web+application+framework&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;t=Symfony%2C+a+PHP+web+application+framework" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_t=Symfony_2C+a+PHP+web+application+framework&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;title=Symfony%2C+a+PHP+web+application+framework" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_title=Symfony_2C+a+PHP+web+application+framework&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;title=Symfony%2C+a+PHP+web+application+framework" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_title=Symfony_2C+a+PHP+web+application+framework&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Symfony%2C+a+PHP+web+application+framework+-+http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Symfony_2C+a+PHP+web+application+framework+-+http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/symfony-a-php-web-application-framework/&amp;title=Symfony%2C+a+PHP+web+application+framework" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/symfony-a-php-web-application-framework/_amp_title=Symfony_2C+a+PHP+web+application+framework&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Symfony%2C%20a%20PHP%20web%20application%20framework%22&amp;body=Link: http://blog.peterhaza.no/symfony-a-php-web-application-framework/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Recently%20I%20made%20a%20library%20for%20a%20client%20which%20needed%20database%20access%2C%20cache%20and%20configuration.%20For%20this%20I%20decided%20to%20try%20%5BZend%20Framework%5D%5B%5D%20for%20the%20first%20time.%20ZF%20was%20excellent%20for%20this%2C%20because%20you%20can%20cherry-pick%20what%20components%20you%20want%2C%20without%20having%20to%20include%20everything.%20For%20my%20next%20project%20ho" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/symfony-a-php-web-application-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image + Geotag + automation = Map Gallery</title>
		<link>http://blog.peterhaza.no/image-geotag-automation-map-gallery/</link>
		<comments>http://blog.peterhaza.no/image-geotag-automation-map-gallery/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 19:33:29 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/image-geotag-automation-map-gallery/</guid>
		<description><![CDATA[My latest personal project is a wordpress plugin that automatically reads geotags from images and adds the image as a point on a google map. You insert the map using a shortcode (&#41; and there you go. Shortcodes were introduced with WordPress 2.5, and I rely on some PHP5 functions, so those are the requirements. [...]]]></description>
			<content:encoded><![CDATA[<p>My latest personal project is a wordpress plugin that automatically reads <a href="http://en.wikipedia.org/wiki/Geotagging" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Geotagging?referer=');">geotags</a> from images and adds the image as a point on a google map. You insert the map using a shortcode (&#91;map_gallery&#93;) and there you go. Shortcodes were introduced with <a href="http://wordpress.org/development/2008/03/wordpress-25-brecker/" onclick="pageTracker._trackPageview('/outgoing/wordpress.org/development/2008/03/wordpress-25-brecker/?referer=');">WordPress 2.5</a>, and I rely on some PHP5 functions, so those are the requirements. You can see a live example on my <a href="http://blog.peterhaza.no/map-gallery/">Map Gallery page</a>.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/image-geotag-automation-map-gallery/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;title=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_title=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;t=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_t=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;title=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_title=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;title=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_title=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery+-+http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery+-+http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/image-geotag-automation-map-gallery/&amp;title=Image+%2B+Geotag+%2B+automation+%3D+Map+Gallery" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/image-geotag-automation-map-gallery/_amp_title=Image+_2B+Geotag+_2B+automation+_3D+Map+Gallery&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Image%20%2B%20Geotag%20%2B%20automation%20%3D%20Map%20Gallery%22&amp;body=Link: http://blog.peterhaza.no/image-geotag-automation-map-gallery/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A My%20latest%20personal%20project%20is%20a%20wordpress%20plugin%20that%20automatically%20reads%20%5Bgeotags%5D%5B%5D%20from%20images%20and%20adds%20the%20image%20as%20a%20point%20on%20a%20google%20map.%20You%20insert%20the%20map%20using%20a%20shortcode%20%28%5C%29%20and%20there%20you%20go.%20Shortcodes%20were%20introduced%20with%20%5BWordpress%202.5%5D%5B%5D%2C%20and%20I%20rely%20on%20some%20PHP5%20functions%2C%20so%20those%20a" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/image-geotag-automation-map-gallery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Working with image meta data in Exif and IPTC headers from PHP</title>
		<link>http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/</link>
		<comments>http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/#comments</comments>
		<pubDate>Thu, 24 Apr 2008 19:47:06 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/?p=11</guid>
		<description><![CDATA[Most people know that when you take a picture a digital camera it writes the image to a file, but quite a few people do not know that there&#8217;s usually a lot more data being written to this image file. The extra data being written is meta data (data about data), and it may contain [...]]]></description>
			<content:encoded><![CDATA[<p>Most people know that when you take a picture a digital camera it writes the image to a file, but quite a few people do not know that there&#8217;s usually a lot more data being written to this image file.
The extra data being written is <a href="http://en.wikipedia.org/wiki/Metadata" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Metadata?referer=');">meta data</a> (data about data), and it may contain lots of data about the camera and surroundings when the picture was taken. This data is usually written in <a href="http://en.wikipedia.org/wiki/Exif" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Exif?referer=');">Exif</a> headers. Addtionally you can add your own data in <a href="http://www.iptc.org/IIM/" onclick="pageTracker._trackPageview('/outgoing/www.iptc.org/IIM/?referer=');">IPTC</a> headers. Here&#8217;s how to work with the two formats in <a href="http://www.php.net" onclick="pageTracker._trackPageview('/outgoing/www.php.net?referer=');">PHP</a>.</p>

<p><span id="more-11"></span></p>

<h3>Why two formats?</h3>

<p>At first glance, the two formats look very similar in their purpose and capabilities, and they are. The main difference is that Exif is a write-once-read-only-format, IPTC is a read-and-write-format. By this it&#8217;s meant that Exif is only supposed to be written once, and that&#8217;s when the camera takes the picture. After that you&#8217;re only supposed to read the data and never modify it.</p>

<p>IPTC on the other hand is an exchange format that removes the need for sending an additional file with meta data. If you look at the <a href="http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf" onclick="pageTracker._trackPageview('/outgoing/www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf?referer=');">IPTC IIM specification</a> you&#8217;ll see that you can embed almost any imaginable meta data. In this post I&#8217;ll only focus on chapter 6, section 1.4 of the IPTC headers: &#8220;Application record No. 2&#8243;, which is where you specify most of the &#8220;personal stuff&#8221;.</p>

<p>This also somewhat implies that Exif headers contain more technical details, while IPTC headers contain more personal/human details.</p>

<h3>Exif</h3>

<p><a href="http://en.wikipedia.org/wiki/Exif" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Exif?referer=');">Exif</a> is pretty straight forward to work with in <a href="http://www.php.net" onclick="pageTracker._trackPageview('/outgoing/www.php.net?referer=');">PHP</a>. As of PHP >= 4.2.0 you are presented with <a href="http://php.net/exif_read_data" onclick="pageTracker._trackPageview('/outgoing/php.net/exif_read_data?referer=');"><code>exif_read_data()</code></a>, where you specify the path to the file you want to read the meta data from.</p>

<pre><code>print_r(exif_read_data('05042008042.jpg'));
Array
(
    [FileName] =&gt; 05042008042.jpg
    [FileDateTime] =&gt; 1207409868
    [FileSize] =&gt; 791791
    [FileType] =&gt; 2
    [MimeType] =&gt; image/jpeg
    [SectionsFound] =&gt; ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS
    [COMPUTED] =&gt; Array
        (
            [html] =&gt; width="2592" height="1944"
            [Height] =&gt; 1944
            [Width] =&gt; 2592
            [IsColor] =&gt; 1
            [ByteOrderMotorola] =&gt; 0
            [ApertureFNumber] =&gt; f/2.8
            [Thumbnail.FileType] =&gt; 2
            [Thumbnail.MimeType] =&gt; image/jpeg
        )

    [Make] =&gt; Nokia
    [Model] =&gt; N95
    [Orientation] =&gt; 1
    [XResolution] =&gt; 300/1
    [YResolution] =&gt; 300/1
    [ResolutionUnit] =&gt; 2
    [YCbCrPositioning] =&gt; 1
    [Exif_IFD_Pointer] =&gt; 144
    [GPS_IFD_Pointer] =&gt; 2994
    [THUMBNAIL] =&gt; Array
        (
            [Compression] =&gt; 6
            [XResolution] =&gt; 72/1
            [YResolution] =&gt; 72/1
            [ResolutionUnit] =&gt; 2
            [JPEGInterchangeFormat] =&gt; 3294
            [JPEGInterchangeFormatLength] =&gt; 18626
        )

    [ExposureTime] =&gt; 29000/1000000
    [FNumber] =&gt; 28/10
    [ISOSpeedRatings] =&gt; 400
    [ExifVersion] =&gt; 0220
    [DateTimeOriginal] =&gt; 2008:04:05 17:36:05
    [DateTimeDigitized] =&gt; 2008:04:05 17:36:05
    [ComponentsConfiguration] =&gt; 
    [ShutterSpeedValue] =&gt; 5107/1000
    [ApertureValue] =&gt; 297/100
    [LightSource] =&gt; 4
    [Flash] =&gt; 25
    [FocalLength] =&gt; 56/10
    [FlashPixVersion] =&gt; 0100
    [ColorSpace] =&gt; 1
    [ExifImageWidth] =&gt; 2592
    [ExifImageLength] =&gt; 1944
    [CustomRendered] =&gt; 0
    [ExposureMode] =&gt; 0
    [WhiteBalance] =&gt; 0
    [DigitalZoomRatio] =&gt; 100/100
    [SceneCaptureType] =&gt; 0
    [GainControl] =&gt; 2
    [GPSVersion] =&gt; 
    [GPSLatitudeRef] =&gt; N
    [GPSLatitude] =&gt; Array
        (
            [0] =&gt; 59/1
            [1] =&gt; 55/1
            [2] =&gt; 2883/100
        )

    [GPSLongitudeRef] =&gt; E
    [GPSLongitude] =&gt; Array
        (
            [0] =&gt; 10/1
            [1] =&gt; 29/1
            [2] =&gt; 3939/100
        )

    [GPSAltitudeRef] =&gt; 
    [GPSAltitude] =&gt; 14750/100
    [GPSTimeStamp] =&gt; Array
        (
            [0] =&gt; 0/1
            [1] =&gt; 0/1
            [2] =&gt; 0/1
        )
    [GPSDateStamp] =&gt; 0000:01:01
)
</code></pre>

<p>That&#8217;s a lot of data, and unless you&#8217;re a photographer probably only understand parts of it. Anyway. This was shot with my Nokia N95 with <a href="http://www.nokia.com/betalabs/locationtagger" onclick="pageTracker._trackPageview('/outgoing/www.nokia.com/betalabs/locationtagger?referer=');">LocationTagger</a> enabled, so I get the extra GPS data embedded as well.
Now, to pick any of this data you just go to the index in your associative array.
For instance if I want read the date and time my picture was shot, I get it like this:</p>

<pre><code>$info = exif_read_data('05042008042.jpg');
echo 'Image was taken at: '.$info['DateTimeOriginal'];
</code></pre>

<p>Straight forward and easy, time to have a look at IPTC headers on the next page.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;t=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_t=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP+-+http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP+-+http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/&amp;title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/_amp_title=Working+with+image+meta+data+in+Exif+and+IPTC+headers+from+PHP&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Working%20with%20image%20meta%20data%20in%20Exif%20and%20IPTC%20headers%20from%20PHP%22&amp;body=Link: http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Most%20people%20know%20that%20when%20you%20take%20a%20picture%20a%20digital%20camera%20it%20writes%20the%20image%20to%20a%20file%2C%20but%20quite%20a%20few%20people%20do%20not%20know%20that%20there%27s%20usually%20a%20lot%20more%20data%20being%20written%20to%20this%20image%20file.%0AThe%20extra%20data%20being%20written%20is%20%5Bmeta%20data%5D%5B%5D%20%28data%20about%20data%29%2C%20and%20it%20may%20contain%20lots%20of%20data%20abo" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>New google charts wrapper in PHP</title>
		<link>http://blog.peterhaza.no/new-google-charts-wrapper-in-php/</link>
		<comments>http://blog.peterhaza.no/new-google-charts-wrapper-in-php/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 10:52:00 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/?p=4</guid>
		<description><![CDATA[I&#8217;ve been doing a freelance project for a while for one of the biggest media corporations in Norway. Without going into details it involves tying together a lot of data and make it available on a map. I&#8217;m building the back-end for this thing, and it needs to support charts and diagrams. In the old [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing a freelance project for a while for one of the biggest media corporations in Norway. Without going into details it involves tying together a lot of data and make it available on a map. I&#8217;m building the back-end for this thing, and it needs to support charts and diagrams.</p>

<p><span id="more-4"></span></p>

<p>In the old days I would implements the &#8220;plotter&#8221; in <a href="http://www.libgd.org/Main_Page/" onclick="pageTracker._trackPageview('/outgoing/www.libgd.org/Main_Page/?referer=');">GD2</a>, using <a href="http://www.php.net/" onclick="pageTracker._trackPageview('/outgoing/www.php.net/?referer=');">PHP</a>s <a href="http://no.php.net/manual/en/ref.image.php" onclick="pageTracker._trackPageview('/outgoing/no.php.net/manual/en/ref.image.php?referer=');">excellent api</a>, but since then <a href="http://www.google.com/" onclick="pageTracker._trackPageview('/outgoing/www.google.com/?referer=');">Google</a> have released their <a href="http://code.google.com/apis/chart/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/apis/chart/?referer=');">charts api</a> which basically means you send a GET request to Google&#8217;s servers, and get an image/plot back.</p>

<p>This is all fine and dandy, but it gets tedious to build the GET parameters every time. So then I decided to go look for a nice PHP wrapper for this api. While I did find some <a href="http://luddep.se/notebook/2008/04/charts_with_php_and_google_charts_api" onclick="pageTracker._trackPageview('/outgoing/luddep.se/notebook/2008/04/charts_with_php_and_google_charts_api?referer=');">interesting</a> <a href="http://code.google.com/p/gchartphp/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/gchartphp/?referer=');">ones</a>, I decided to start <a href="http://github.com/phaza/googlecharts/tree/master" onclick="pageTracker._trackPageview('/outgoing/github.com/phaza/googlecharts/tree/master?referer=');">my own</a>. This because I found the other frameworks lacking, either because they serve a different purpose(like being very easy to use(1file)), or because they used an approach I didn&#8217;t feel comfortable with.</p>

<p>Anyway. Feel free to contribute with code or comment comments. I do plan on eventually to support the whole api, but it will come in bits and pieces as I need them. First out is barchart which is <em>nearly</em> done already!</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/new-google-charts-wrapper-in-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;title=New+google+charts+wrapper+in+PHP" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_title=New+google+charts+wrapper+in+PHP&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;t=New+google+charts+wrapper+in+PHP" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_t=New+google+charts+wrapper+in+PHP&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;title=New+google+charts+wrapper+in+PHP" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_title=New+google+charts+wrapper+in+PHP&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;title=New+google+charts+wrapper+in+PHP" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_title=New+google+charts+wrapper+in+PHP&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=New+google+charts+wrapper+in+PHP+-+http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=New+google+charts+wrapper+in+PHP+-+http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/new-google-charts-wrapper-in-php/&amp;title=New+google+charts+wrapper+in+PHP" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/new-google-charts-wrapper-in-php/_amp_title=New+google+charts+wrapper+in+PHP&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22New%20google%20charts%20wrapper%20in%20PHP%22&amp;body=Link: http://blog.peterhaza.no/new-google-charts-wrapper-in-php/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A I%27ve%20been%20doing%20a%20freelance%20project%20for%20a%20while%20for%20one%20of%20the%20biggest%20media%20corporations%20in%20Norway.%20Without%20going%20into%20details%20it%20involves%20tying%20together%20a%20lot%20of%20data%20and%20make%20it%20available%20on%20a%20map.%20I%27m%20building%20the%20back-end%20for%20this%20thing%2C%20and%20it%20needs%20to%20support%20charts%20and%20diagrams.%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AIn%20" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/new-google-charts-wrapper-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Callback-functions explained</title>
		<link>http://blog.peterhaza.no/callback-functions-explained/</link>
		<comments>http://blog.peterhaza.no/callback-functions-explained/#comments</comments>
		<pubDate>Fri, 23 Mar 2007 19:34:05 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/?p=6</guid>
		<description><![CDATA[Very many programming and scripting languages today allows you to use callback functions, both built-in functions and user defined functions. This is all good and dandy, but unfortunately very many programmers don&#8217;t know what a callback function is or does, and definately not how to use one. In this article I will try to explain [...]]]></description>
			<content:encoded><![CDATA[<p>Very many programming and scripting languages today allows you to use callback functions, both built-in functions and user defined functions. This is all good and dandy, but unfortunately very many programmers don&#8217;t know what a callback function is or does, and definately not how to use one. In this article I will try to explain and show how to use callbacks. The language used in this article is PHP because it&#8217;s easy to understand and work with, but the theory can be applied to any language supporting callback functions.</p>

<p><span id="more-6"></span></p>

<h3>So what exactly is a callback function?</h3>

<p>A callback-function has the exact same signature as any other function; because it is a normal function. It may take some parameters to work with, and it may return a value, but neither are required. This implies that &#8220;normal&#8221; functions may also be used as callback functions. In reality though, most callback functions will take one or more parameters, work with this and return a value.</p>

<p>The biggest difference between a normal function and a callback function is that the calling/parent function may not know the name or signature of the callback function at compile time, but rather at run time. In PHP, these times are normally the same, as most people run PHP as an interpreted language.</p>

<p>Now this can be a tough concept to grasp, hence we proceed with an example.</p>

<pre><code>// In order to keep the code small and clean, there is no input checking being done.
// SETUP
// This is our function that will be used as a callback function
function sqr( $var )
{
  return $var*$var;
}

$int_arr = array( 1, 2, 3 );
// END SETUP

// Call like normal function
echo 'Normal call: '.sqr( 5 );

// call within another function
function var_sqr( $i )
{
  echo 'Within another function: '.sqr( $i );
}

var_sqr(5);

// Call as a callback function

function sqr_arr( $arr, $callback )
{
  foreach( $arr as $i )
  {
    echo 'Callback-call: '.call_user_func( $callback, $i );
  }
}

sqr_arr( $int_arr, 'sqr' );
</code></pre>

<p>The result should print something like this (with newlines added)</p>

<pre><code>Normal call: 25
Within another function: 25
Callback-call: 1
Callback-call: 4
Callback-call: 9
</code></pre>

<p>The two first you should be able to predict on your own. The third one on the other hand, is what this article is really about.
As you can see we call the <code>arr_sqr</code> function like this</p>

<pre><code>arr_sqr( $int_arr, 'sqr' );
</code></pre>

<p>The first parameter is just a normal array with three integers. No magic going on there. The second parameter on the other hand, is somewhat fishy. Here we provide the name of the function. We don&#8217;t provide any parameters or any magic to this second function, just the name.</p>

<p>The foreach loop in the <code>var_sqr</code> function shouldn&#8217;t be unfamiliar either. It just iterates over the array, and for each value in the array runs the loop body.</p>

<p>The <code>call_user_func()</code> call on the other hand, is somewhat frightning and scary.</p>

<p><code>call_user_func()</code> is what we may call the &#8220;function executer&#8221;, it takes care of calling our callback function and providing it with parameters. <code>call_user_func()</code> takes an infinite number of parameters, but the first one has to be the name of function. The trailing parameters to <code>call_user_func()</code> are the same parameters that will be sent to the callback function, in the same order they are listed in <code>call_user_func()</code>.</p>

<p>Example:</p>

<pre><code>call_user_func( 'myfunc', $1, $2, $3 );
</code></pre>

<p>Here we are calling a function called myfunc() which takes at least three parameters. It will be called as follow:</p>

<pre><code>myfunc( $1, $2, $3 )
</code></pre>

<h3>So why use callback functions?</h3>

<p>Callback functions are excellent for writing modular code. For instance we have this code:</p>

<pre><code>/*
List the directory $dir, and apply the $filter_func function to all the elements to filter out the unwanted elements.
return the array of wanted elements from $dir
$filter_func should take one parameter (a name of a file or directory) and return true or false
*/

function listDir($dir, $filter_func) {

$ret = array();

if(function_exists($filter_func) &amp;&amp; is_callable($filter_func)) {
 if(is_dir($dir)) {
  if(is_readable($dir)) {
   $curr_dir = getcwd();
   // undocumented notice on error?
   if(@chdir($dir)) {
    if($fp = opendir('.')) {
     while(false !== ($file = readdir($fp))) {
      if($file != '.' &amp;&amp; $file != '..') {
       if(call_user_func($filter_func, $file))
        $ret[] = $file;
      }
     }
     closedir($fp);
    }
    chdir($curr_dir);
   }
  }
 }
}
return $ret;
}
</code></pre>

<p>This function takes two parameters, a directory/path and a callback function. As the name implies, this function will list the files in the path given by the $dir parameter. What might not be so obvious is the second parameter, $filter_func. As mentioned this argument is the name of the callback function, and it should take exactly one parameter and return true or false.</p>

<p>The listDir() function will then use the callback function to determine whether or not to add the file in question to the list(returned array) or not.</p>

<p>For instance: Say we have a function <code>is_image()</code> which takes one parameter, and determines if the file or directory given in the parameter is an image or not. Then we could list all images in a directory like this.</p>

<pre><code>$images = listDir( 'somedir/', 'is_image' );
print_r( $images );
</code></pre>

<p>Or say we only wanted to list subdirectories of $dir, we could do this (note that we are using the in-built function <code>is_dir()</code>)</p>

<pre><code>$dirs = listDir( 'somedir/', 'is_dir' );
print_r( $dirs );
</code></pre>

<p>One could even make an advanced version of <code>is_dir()</code> which prints the name of the &#8220;file&#8221; if it is a directory, and called listDir() on this before it returned true and that way print all directories recursively. Note that I write &#8220;print all directories&#8221;. This is because listDir() wouldn&#8217;t save the value from <code>is_dir()</code> if it returned an array of directories anyway, as it expects <code>is_dir()</code> to return true or false. But if <code>is_dir()</code> PRINTS the directory it will make a recursive list. (This is left as an excercise to the reader <em>phew</em>)</p>

<p>I hope this can work as a primer for using callback functions to modularize your code. By doing this will avoid having to re-invent the wheel only to change the rims.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/callback-functions-explained/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/callback-functions-explained/&amp;title=Callback-functions+explained" rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/callback-functions-explained/_amp_title=Callback-functions+explained&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/callback-functions-explained/&amp;t=Callback-functions+explained" rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/callback-functions-explained/_amp_t=Callback-functions+explained&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/callback-functions-explained/&amp;title=Callback-functions+explained" rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/callback-functions-explained/_amp_title=Callback-functions+explained&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/callback-functions-explained/&amp;title=Callback-functions+explained" rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/callback-functions-explained/_amp_title=Callback-functions+explained&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Callback-functions+explained+-+http://blog.peterhaza.no/callback-functions-explained/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Callback-functions+explained+-+http_//blog.peterhaza.no/callback-functions-explained/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/callback-functions-explained/&amp;title=Callback-functions+explained" rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/callback-functions-explained/_amp_title=Callback-functions+explained&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Callback-functions%20explained%22&amp;body=Link: http://blog.peterhaza.no/callback-functions-explained/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Very%20many%20programming%20and%20scripting%20languages%20today%20allows%20you%20to%20use%20callback%20functions%2C%20both%20built-in%20functions%20and%20user%20defined%20functions.%20This%20is%20all%20good%20and%20dandy%2C%20but%20unfortunately%20very%20many%20programmers%20don%27t%20know%20what%20a%20callback%20function%20is%20or%20does%2C%20and%20definately%20not%20how%20to%20use%20one.%20In%20this" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/callback-functions-explained/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Session security in PHP, and how to improve it.</title>
		<link>http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/</link>
		<comments>http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/#comments</comments>
		<pubDate>Mon, 06 Nov 2006 18:02:12 +0000</pubDate>
		<dc:creator>Peter Haza</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.peterhaza.no/2008/04/21/session-security-in-php-and-how-to-improve-it/</guid>
		<description><![CDATA[When you first start out with PHP, you soon realize that you need a way to save small chunks of data like client input across pages. There are two fairly simple ways of doing this in PHP. Sessions are useful for storing this data for shorter periods of time i.e per browser session while cookies [...]]]></description>
			<content:encoded><![CDATA[<p>When you first start out with PHP, you soon realize that you need a way to save small chunks of data like client input across pages. There are two fairly simple ways of doing this in PHP. Sessions are useful for storing this data for shorter periods of time i.e per browser session while cookies are used to store the data more permanently. While cookies are saved on the client&#8217;s computer, sessions are stored on the server, giving the client a unique string which identifies their session. Hence sessions are arguably better for storing sensitive data, as there&#8217;s no way for anyone to tamper with it, unlike cookies which are just text files stored on the client computer. This is at least what many programmers tend to think today. Unfortunately, things are rarely this easy. This post is not going explain the vulnerabilities of sessions in great detail, but this great blog post explains the most common exploitations.</p>

<p><span id="more-7"></span></p>

<p>In this post I aim to nail the first problem mentioned by Harry Fuecks in his blog, shared web server. One of his suggested solutions is to use a database to store the sessions instead of normal files, and that&#8217;s exactly what we&#8217;re going to do.</p>

<p>First of all, you have to create the database table for our code to use.
This is done by executing the following code either directly in PHP with mysql_query, or by using phpmyadmin or a similar tool:</p>

<pre><code>CREATE TABLE IF NOT EXISTS sessions
(
    session_id VARCHAR(255) NOT NULL,
    session_expires CHAR(10) NOT NULL,
    session_data TEXT,
    PRIMARY KEY (session_id)
) ENGINE=INNODB;
</code></pre>

<p>This should create a table called &#8220;sessions&#8221;. The storage engine used here is InnoDb, but you can change this to HEAP to use an in-memory engine, or MyISAM which is the default MySQL table type or any other type supported by MySQL.</p>

<p>Now it&#8217;s time to configure a few settings to allow our script to access the database, these settings are located at the top of our script and should be self-explanatory:</p>

<pre><code>// Mysql user
define( 'DB_USERNAME', '' );

// Mysql password
define( 'DB_PASSWORD', '' );

// Mysql database name
define( 'DB_NAME', '' );

// Mysql host
define( 'DB_HOST', null );

// Mysql host port
define( 'DB_PORT', null );

// Name of the session table
define( 'DB_SESSION_TABLE', 'sessions' );
</code></pre>

<p>That&#8217;s it! You&#8217;re done! You don&#8217;t have to call any special methods or functions to use this script.
While the example below looks like its using sessions in the normal way the actual data is being stored in the database table. This is far more secure than using sessions in a shared web server environment. Don&#8217;t forget to call <code>session_start()</code>:</p>

<pre><code>require_once( 'mysql_session_manager.php' );
session_start();

// add a session
$_SESSION['this_is_a_session'] = 'omg, this is easy!';

// use it
if( isset( $_SESSION['this_is_a_session'] ) )
{
    // This will output "omg, this is easy!"
    echo $_SESSION['this_is_a_sesion'];
}

// delete session
unset( $_SESSION['this_is_a_session'] );
</code></pre>

<p>The script is written in OOP and PHP5.
It requires a mysql database, version 4.1 or newer.</p>

<p>The code is released under the Creative Commons Attribution 2.5 License</p>

<p>Use 7-zip or similar to un-pack on a windows machine, or the unzip command or similar on linux.</p>

<p>Download: <a href='http://blog.peterhaza.no/wp-content/uploads/2008/04/mysql_session_manager.zip'>MySQL session manager</a></p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
		<li class="shr-comfeed">
			<a href="http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;title=Session+security+in+PHP%2C+and+how+to+improve+it." rel="nofollow" class="external" title="Share this on del.icio.us" onclick="pageTracker._trackPageview('/outgoing/delicious.com/post?url=http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_title=Session+security+in+PHP_2C+and+how+to+improve+it.&amp;referer=');">Share this on del.icio.us</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;t=Session+security+in+PHP%2C+and+how+to+improve+it." rel="nofollow" class="external" title="Share this on Facebook" onclick="pageTracker._trackPageview('/outgoing/www.facebook.com/share.php?v=4_amp_src=bm_amp_u=http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_t=Session+security+in+PHP_2C+and+how+to+improve+it.&amp;referer=');">Share this on Facebook</a>
		</li>
		<li class="shr-reddit">
			<a href="http://reddit.com/submit?url=http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;title=Session+security+in+PHP%2C+and+how+to+improve+it." rel="nofollow" class="external" title="Share this on Reddit" onclick="pageTracker._trackPageview('/outgoing/reddit.com/submit?url=http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_title=Session+security+in+PHP_2C+and+how+to+improve+it.&amp;referer=');">Share this on Reddit</a>
		</li>
		<li class="shr-stumbleupon">
			<a href="http://www.stumbleupon.com/submit?url=http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;title=Session+security+in+PHP%2C+and+how+to+improve+it." rel="nofollow" class="external" title="Stumble upon something good? Share it on StumbleUpon" onclick="pageTracker._trackPageview('/outgoing/www.stumbleupon.com/submit?url=http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_title=Session+security+in+PHP_2C+and+how+to+improve+it.&amp;referer=');">Stumble upon something good? Share it on StumbleUpon</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Session+security+in+PHP%2C+and+how+to+improve+it.+-+http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!" onclick="pageTracker._trackPageview('/outgoing/twitter.com/home?status=Session+security+in+PHP_2C+and+how+to+improve+it.+-+http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_source=shareaholic&amp;referer=');">Tweet This!</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/&amp;title=Session+security+in+PHP%2C+and+how+to+improve+it." rel="nofollow" class="external" title="Digg this!" onclick="pageTracker._trackPageview('/outgoing/digg.com/submit?phase=2_amp_url=http_//blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/_amp_title=Session+security+in+PHP_2C+and+how+to+improve+it.&amp;referer=');">Digg this!</a>
		</li>
		<li class="shr-mail">
			<a href="mailto:?subject=%22Session%20security%20in%20PHP%2C%20and%20how%20to%20improve%20it.%22&amp;body=Link: http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A When%20you%20first%20start%20out%20with%20PHP%2C%20you%20soon%20realize%20that%20you%20need%20a%20way%20to%20save%20small%20chunks%20of%20data%20like%20client%20input%20across%20pages.%20There%20are%20two%20fairly%20simple%20ways%20of%20doing%20this%20in%20PHP.%20Sessions%20are%20useful%20for%20storing%20this%20data%20for%20shorter%20periods%20of%20time%20i.e%20per%20browser%20session%20while%20cookies%20are%20" rel="nofollow" class="external" title="Email this to a friend?">Email this to a friend?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://blog.peterhaza.no/session-security-in-php-and-how-to-improve-it/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
