<?xml version="1.0" encoding="iso-8859-1"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">

 <link rel="alternate" type="text/html" href="http://www.dotvoid.com"/>
 <tagline>Experimenting with PHP, Javascript and XML</tagline>
 <id>http://www.dotvoid.com</id>
 <generator url="http://www.dotvoid.com">dotvoid.com</generator>
 <title>dotvoid.com - php and javascript</title>
 <modified>2008-01-28T10:58:00+01:00</modified>

 <entry>
  <title type="text/plain" mode="escaped">Setting up a development environment with apache-2.2.6</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=80" title="Setting up a development environment with apache-2.2.6"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=80</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-11-20T00:16:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>I recently bought a new laptop as my new development box. A nice 17" screen with 1920*1200. So now I was to setup a PHP development environment for all the projects I'm working on. I downloaded Apache 2.2.6, PHP 5.2.4 and MySQL 5.0.45. I compiled and installed them and finally added a few virtual hosts. None of the vhosts worked. They all gave me</p><pre>"client denied by server configuration: ..."</pre><p>I had missed that apache now ships with a slightly different configuration for the / directory to</p><pre>&lt;Directory /&gt;<br>&nbsp;&nbsp;&nbsp; Options FollowSymLinks<br>&nbsp;&nbsp;&nbsp; AllowOverride None<br>&nbsp;&nbsp;&nbsp; Order deny,allow<br>&nbsp;&nbsp;&nbsp; Deny from all<br>&lt;/Directory&gt;</pre><p>The <span style="font-style: italic;">Order deny,allow</span> and <span style="font-style: italic;">Deny from all</span> makes the virtual hosts inaccessible by default. When I googled it I saw many forum and blog posts asking about this issue.</p><p>To fix it you can either remove/change the lines. But that is probably not a good idea. Better is to explicitly specify which directories that apache are allowed to serve. So for me and my project setup it was as simple as adding a new directory directive opening up my www directories for all the projects. <br></p><pre>&lt;Directory /&gt;<br>&nbsp;&nbsp;&nbsp; Options FollowSymLinks<br>&nbsp;&nbsp;&nbsp; AllowOverride None<br>&nbsp;&nbsp;&nbsp; Order deny,allow<br>&nbsp;&nbsp;&nbsp; Deny from all<br>&lt;/Directory&gt;<br><br>&lt;Directory "/home/myusername/Projects/*/www"&gt;<br>&nbsp;&nbsp;&nbsp; Order deny,allow<br>&nbsp;&nbsp;&nbsp; Allow from all<br>&lt;/Directory&gt;<br></pre><p>I hope this short explanation helps a few people looking for a solution to the problem.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">International PHP conference in Frankfurt 2007</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=79" title="International PHP conference in Frankfurt 2007"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=79</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-11-05T12:27:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>Yesterday was the first day of the International PHP Conference. I
listened to Lars Jankowfsky in his session "Practising Agile
Development". Altough different methodoligies were mentioned it was
mainly a one day session on how Extreme programming works. The session
had a good mix of fun och seriousness. One of the reasons I wanted to
go to Frankfurt this year was the mix between technical and non
technical sessions. I have to say that Lars one day session on XP was a
very good start. As always me and others that do not use xdebug and unit tests frequently got a lot of well deserved bashing...</p><p>"<span style="font-style: italic;">Using your brain while developing is really helpful</span>" - Lars Jankowfsky. Maybe I should stop the bad habit of lazy coding while watching TV...<br></p>
<p>One thing that makes me happy is that they have added a session on
Zend Framework. I look forward to that as I have begun to rely on Zend
Framework quite a lot.</p><br><p style="text-align: center;"><img style="border-style: none; width: 526px; height: 394px;" title="" alt="IPC 2007 Frankfurt" src="/fs2/fs__media_mod_action.php?action=v&amp;criteria=49" fsid="49" align=""></p><p style="text-align: center;">IPC 2007 and Ajax In Action</p><br><p style="text-align: center;"><img style="border-style: none; width: 527px; height: 396px;" title="" alt="Lars Jankowfsky" src="/fs2/fs__media_mod_action.php?action=v&amp;criteria=50" fsid="50" align=""></p><p style="text-align: center;">Lars Jankowfsky during his session<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">Reordering nested sets using PHP and Javascript</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=78" title="Reordering nested sets using PHP and Javascript"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=78</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-09-14T12:29:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<h2>The adjancency method<br></h2><p>Representing a tree of nodes, for example product categories, in a relational database is not hard. The most common way of doing it is to store a parentid with each node. This is also known as the adjacency list model. It is sometimes also referred to as the recursive model. Whatever the name it is easy to grasp. It is very simple to insert and move nodes around but it is not an optimal solution if you often select the whole tree from the database for displaying on a web page as you need to recursively select all children of nodes.</p><h2>The nested set model</h2><p>A much better solution is the nested set model. In this model trees are represented as nested sets. Instead of using a parentid you have a left and right value for each node expressing the relationship to other nodes. A tree of nodes can look like this.</p><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 34<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--36<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; | <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +--46<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +--47<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--38<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--39</pre><p>The same data can be viewed more graphically as nested sets. This is also the way they are stored in the database. Notice how the left and right values are numbered in order from the outermost left to the outermost right.</p><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id:34<br>&nbsp;&nbsp; +----------------------------------------------------+<br>&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id:36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id:38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp; |&nbsp;&nbsp; +------------------------+&nbsp;&nbsp;&nbsp; +--------------+&nbsp;&nbsp; |<br>&nbsp;&nbsp; |&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; id:46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id:47&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; id:39&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |<br>&nbsp;&nbsp; |&nbsp;&nbsp; |&nbsp;&nbsp; +-----+&nbsp;&nbsp;&nbsp; +-----+&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +------+&nbsp;&nbsp; |&nbsp;&nbsp; |<br>&nbsp; 1|&nbsp; 2|&nbsp; 3|&nbsp;&nbsp;&nbsp;&nbsp; |4&nbsp; 5|&nbsp;&nbsp;&nbsp;&nbsp; |6&nbsp; |7&nbsp; 8|&nbsp; 9|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |10 |11 |12<br>&nbsp;&nbsp; |&nbsp;&nbsp; |&nbsp;&nbsp; +-----+&nbsp;&nbsp;&nbsp; +-----+&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +------+&nbsp;&nbsp; |&nbsp;&nbsp; |<br>&nbsp;&nbsp; |&nbsp;&nbsp; +------------------------+&nbsp;&nbsp;&nbsp; +--------------+&nbsp;&nbsp; |<br>&nbsp;&nbsp; +----------------------------------------------------+</pre><p></p><p>In the database this is stored as in the following table.</p><pre>&nbsp;+----+-----+-----+<br> | id | lft | rgt |<br> +----+-----+-----+<br> | 34 | 1&nbsp;&nbsp; | 12&nbsp; |<br> | 36 | 2&nbsp;&nbsp; |&nbsp; 7&nbsp; |<br> | 46 | 3&nbsp;&nbsp; |&nbsp; 4&nbsp; |<br> | 47 | 5&nbsp;&nbsp; |&nbsp; 6&nbsp; |<br> | 38 | 8&nbsp;&nbsp; | 11&nbsp; |<br> | 39 | 9&nbsp;&nbsp; | 10&nbsp; |<br> +----+-----+-----+</pre><p>This allow you to select the full tree with only one select statement. Normally you select the full list of nodes including the depth of each node as shown below in the small table containing id and depth. It is then easy to loop over the data in PHP to produce a nice tree in HTML/CSS.</p><p>The data below can be displayed as the the tree on right. The depth is in parenthesis.</p><pre> +----+-------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 34 (0)<br> | id | depth |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br> +----+-------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--36 (1)<br> | 34 | 0&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |&nbsp; <br> | 36 | 1&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +--46 (2)<br> | 46 | 2&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |<br> | 47 | 2&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; +--47 (2)<br> | 38 | 1&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br> | 39 | 2&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--38 (1)<br> +----+-------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--39 (2)</pre><p>Here is a more thorough article on <a target="" title="" href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">how you use MySQL with nested sets</a>.<br></p><h2>On to the problem</h2><p>Last night I was working on an application that display a full tree where the user must be able to to drag and drop nodes to reorder the tree. The problem is that it is much more difficult to insert or reorder the tree using the nested set model.</p><p>For the actual html I produced nested ordered lists using the OL and LI html element so that it was easy to use with the excellent <a target="" title="" href="http://youmuppet.com/?page_id=9">MooTree script</a> based on <a target="" title="" href="http://www.mootools.net/">MooTools</a>. (It does seem to have trouble with the latest version of MooTools though.) After reordering the structure it was easy to extract the tree list including the depth of each node. I sent this to the PHP backend to be handled there. The text data I sent to the PHP backend then look like below.</p><pre>&nbsp;34,0<br>&nbsp;36,1<br>&nbsp;46,2<br>&nbsp;47,2<br>&nbsp;38,1<br>&nbsp;39,2</pre><p>As you can see it looks exactly like the data I selected from the database previously. So I had to create a function in PHP that took this indata and produced a list of nodes with the correct left and right values. This list is then looped over to update all the nodes in the database.</p><pre>function depth2nestedset($data)<br>{<br>&nbsp; $lines = explode("\n", $data);<br>&nbsp; $rows = array();<br>&nbsp; $stack = array();<br><br>&nbsp; $lft = 0;&nbsp;&nbsp; // Left value<br>&nbsp; $rgt = 0;&nbsp;&nbsp; // Right value<br>&nbsp; $plvl = -1; // Previous node level<br><br>&nbsp; foreach($lines as $line) {<br>&nbsp;&nbsp;&nbsp; list($id, $lvl) = explode(',', $line);<br><br>&nbsp;&nbsp;&nbsp; // Skip empty/faulty lines<br>&nbsp;&nbsp;&nbsp; if (trim($id) == '') {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue();<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; if ($lvl &gt; $plvl) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lft++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rgt = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array_push($stack, $id);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else if ($lvl == $plvl) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $pid = array_pop($stack);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rows[$pid][2] = $rows[$pid][1] + 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lft = $lft + 2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rgt = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array_push($stack, $id);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lft = $lft + ($plvl - $lvl) + 2;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $diff = $plvl - $lvl + 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for($n = 0; $n &lt; $diff; $n++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $pid = array_pop($stack);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rows[$pid][2] = $lft - $diff + $n;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array_push($stack, $id);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; $rows[$id] = array($id, $lft, $rgt);<br>&nbsp;&nbsp;&nbsp; $plvl = $lvl;<br>&nbsp; }<br><br>&nbsp; $plvl++;<br>&nbsp; $cnt = count($rows) * 2;<br>&nbsp; $leftovers = count($stack);<br><br>&nbsp; for($n = 0; $n &lt; $leftovers; $n++) {<br>&nbsp;&nbsp;&nbsp; $pid = array_pop($stack);<br>&nbsp;&nbsp;&nbsp; $rows[$pid][2] = $cnt - $plvl-- + $n;<br>&nbsp; }<br><br>&nbsp; return $rows;<br>}<br></pre><p>The resulting associated array that is returned looks like below.</p><pre>Array<br>(<br>&nbsp;&nbsp;&nbsp; [34] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 34<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 12<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; [36] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 36<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 7<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; [46] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 46<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; [47] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 47<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 5<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 6<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; [38] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 38<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 8<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 11<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; [39] =&gt; Array<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; 39<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; 9<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [2] =&gt; 10<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br>)<br></pre><p>That makes the circle complete. From left/right values in the database to a node tree based on depths that is easy to manipulate in html and then back to left/right values. Hopefully this makes sense. Do you have a better solution or more examples on applications that do this I would love to hear about it.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">PHP Conference</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=77" title="PHP Conference"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=77</id>
  <modified>2008-05-27T13:50:00+01:00</modified>
  <issued>2007-09-05T16:28:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>I have been to the <a target="" title="" href="http://phpconference.com/">International PHP Conference</a> in Frankfurt a couple of times. Last year I didn't go as the quality of the conference 2005 wasn't what I think one should expect.<br></p><p>This year seems to be different though. A whole slew of interesting sessions on PHP mixed with a few sessions on agile development. Sounds just about perfect to me. I am especially interested in the one PHP 6 session as I have not had the time to follow what is happening in regards to next major version of PHP. I'm definitely going to Frankfurt this November. There are still too many sessions in German if you ask me - but I guess there are quite a few Germans going to the conference.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">Generating Excel files with PHP</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=76" title="Generating Excel files with PHP"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=76</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-07-10T11:10:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>I'm on this project at work where we need to create an excel file and send it via email or ftp to a recipient. The normal answer to this is to create a comma separated file and name it .xls and excel will work it out. However, that only works if you open it directly through an http request and are able to set the http headers correctly. I'm not going to elaborate on the requirements but they want an excel file generated and sent to them. They don't want to and can't download the file themselves.<br></p><p>Naturally I went to the almighty Google for the answer. There are a few excel writers written out there. I found a tutorial on <a target="" title="" href="http://www.phphacks.com/content/view/26/33/">using PEAR Spreadsheet_Excel_Writer</a> and an <a target="" title="" href="http://www.phpclasses.org/browse/package/1919.html">MS-Excel Stream Handler class</a> to mention two solutions.</p><p>I found one piece of code floating around numerous places that I fell for. I am not sure about the original source for this code though. Extremely simple.</p><pre>function xlsBOF() {<br>    return pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);  <br>}<br><br>function xlsEOF() {<br>    return pack("ss", 0x0A, 0x00);<br>}<br><br>function xlsWriteNumber($Row, $Col, $Value) {<br>    return pack("sssss", 0x203, 14, $Row, $Col, 0x0)<br>      .pack("d", $Value);<br>}<br><br>function xlsWriteLabel($Row, $Col, $Value ) {<br>    $L = strlen($Value);<br>    return pack("ssssss", 0x204, 8 + $L, $Row, $Col, 0x0, $L)<br>      .$Value;<br>}<br></pre><p>I liked it because it did what I wanted with a minimum of fuss. I was happy until I realized I don't understand it enough to be able to set the character set. Right now question marks appear in the texts instead of national Swedish characters as å, ä and ö.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">SVN hosting options</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=75" title="SVN hosting options"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=75</id>
  <modified>2008-03-14T09:48:00+01:00</modified>
  <issued>2007-05-10T09:48:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>At work we still use CVS. We even have PVCS sitting on an old Tru64 machine actively used in one last project that hasn't converted to CVS. I have looked at subversion/SVN and I use it for a few smaller projects. I host the repositories myself which is not the right option in every situation. And for some projects it would sometimes be better to host them somewhere else. This is especially true for many open source projects. Yesterday I found a good <a target="" title="" href="http://www.snook.ca/archives/servers/hosted_subversion/">subversion hosting overview</a> over at <a target="" title="" href="http://www.snook.ca/">Snook.ca</a>.</p><p>However, before I decided to host a software project somewhere else I would thoroughly investigate how easy it is to export the whole repository with version history intact.</p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">PostNuke and PHP 5</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=74" title="PostNuke and PHP 5"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=74</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-05-09T01:46:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>In an earlier blog post I wrote about how I think companies, and open
source projects, will <a target="" title="" href="http://www.dotvoid.com/view.php?id=69">loose business</a> if they don't start the
upgrade path to PHP 5. With PHP 6 in the works it is only a matter of
time before most people will consider PHP 4 applications legacy. Now
that there is a clear message that <a title="" href="http://derickrethans.nl/php_quebec_conference_rip_php_4.php" target="_blank">no new versions of PHP 4 will be
released after December 31st, 2007</a> this will go much faster.<br> <br>
In the long run I think that it is not enough to just be PHP 5 friendly while staying backwards compatible.<br> <br>
There is so much added benefit in using PHP 5 and probably PHP 6 later
on that projects not taking advantage of new features will eventually
be left behind. New developers will more often than not start with PHP
5 when learning the language. I think many open source projects will
have difficulties in attracting new developers if they don't actively
promote using new features in the language. Some projects will most likely fork. A fork is not always a good solution with all the problems and politics that usually comes with it. It would be stupid not to
prepare for new PHP versions in advance and avoid all the problems.<br> <br>
The other day I had a conversation with an industry collegue from back home working on a <a title="" href="http://www.pokerjunkie.com/" target="_blank">poker</a> site using the <a title="" href="http://www.postnuke.com/" target="_blank">PostNuke CMS</a>.
He is not very technical but still has many itches to scratch. Most of
the issues he aired was mostly due to a lack of specific functionality
he needed though. He was forced to create many
pages, for example a listing of <a target="" title="" href="http://www.pokerjunkie.com/poker-sites.php">poker sites</a>, manually. This he admitted might just be due to the fact that PostNuke is the wrong system for what he is doing. We had a very interesting discussion regarding PHP CMS applications and functionality.<br> <br>But after our discussion and after reading <a title="" href="http://pooteeweet.org/blog/671" target="_blank">"The state of the PHP5 CMS..."</a> by <a title="" href="http://pooteeweet.org/" target="_blank">Lukas Smith</a>
I thought it would be interesting to have a closer look at PostNuke,
being a well known and widely used PHP application. If I searched google
for <a title="" href="http://www.google.com/search?q=drop+support+for+php+4&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a" target="_blank">"drop support for php 4"</a> I get about 11 million hits. I guess a lot of the hits aren't really relevant but still. If I add the word <a title="" href="http://www.google.com/search?hl=en&amp;client=firefox-a&amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;q=drop+support+for+php+4+postnuke&amp;btnG=Search" target="_blank">"PostNuke"</a>
to the search I can't find one relevant hit in the search result. So
what is a project as PostNuke doing, if anything, with PHP 5?</p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">Problem sending mail with PHP mail function</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=73" title="Problem sending mail with PHP mail function"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=73</id>
  <modified>2008-05-27T13:50:00+01:00</modified>
  <issued>2007-04-17T11:47:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>Occasionally I have had trouble sending emails using the builtin <a target="" title="" href="http://www.php.net/manual/en/function.mail.php">mail() function</a> in PHP. Sometimes emails never reached their intended destination. Naturally I have assumed that there might be a problem with some spam filters used. However, lazy as I am, I have not given it a second thought. Instead I have used a PHP class that allows me to send emails using a remote smtp server using an account on that server. This has been a good solution for my setup anyways. A few days ago <a target="" title="" href="http://www.2good.nu/">a friend of mine</a> was asked to investigate the very same problem for a client.</p><p>The problem seems to be that PHP use the ini directive <span style="font-style: italic;">sendmail_from</span> to set the from email address in the SMTP protocol. If this is not correctly set, or if it does not match the from header in the email headers, the email is caught by spam protection software.</p><p>The simplest solution is to set the directive during execution:</p><pre>ini_set("sendmail_from", $email_from);<br><br><code><span class="html"><span class="default">$headers </span><span class="keyword">= </span><span class="string">"From: $email_from";</span><span class="keyword"><br></span><span class="keyword"><br></span><span class="default">mail</span><span class="keyword">(</span><span class="default">$to</span><span class="keyword">, </span><span class="default">$subject</span><span class="keyword">, </span><span class="default">$message</span><span class="keyword">, </span><span class="default">$headers</span><span class="keyword">);</span></span></code><br></pre><p>The problem as well as the solution was <a target="" title="" href="http://www.php.net/manual/en/ref.mail.php#72249">already known</a> by others. The operating system this time was windows and I know there are differences in the implementation between the windows and linux version of mail(). I am not sure if the problem exist on both platforms.<br></p><p>Still I bet there are lots of people out there with this problem without them knowing it. It could be a good idea to include more detailed information about this ini entry and its implications in the actual mail() documentation. Sending emails from web pages is, to say the least, a very common task.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">The nested set model - hierarchical data in MySQL</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=72" title="The nested set model - hierarchical data in MySQL"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=72</id>
  <modified>2008-01-28T10:58:00+01:00</modified>
  <issued>2007-03-20T01:37:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>I'm working on a small PHP project handling data which is organized in a hierarchical fashion. This is a common task and I have done it before creating forums and the like. This time no different than any other I was swearing over the rather ugly and most of all inefficient code needed for fetching a full hierarchy from the database and displaying it nicely. Vaguely I remembered reading something about a rather different approach.</p><p>Searching Google I finally found a <a target="" title="" href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">MySQL article on the nested set model</a> which is a lot more efficient. The algorigthm basically skips the whole parent/child relationship between nodes. Instead you work with what is best described as "neighbouring" nodes. This allows you to retrieve a fully ordered hierarchical tree, including the level/depth of each node in the tree, using only one simple sql statement.<br></p><p>Those that are not familiar with the nested set model should definitely read the article.<br></p>]]>
  </content>
 </entry>
 <entry>
  <title type="text/plain" mode="escaped">Zend Feed for a Swedish web development blog aggregator</title>
  <link rel="alternate" type="text/html" href="http://www.dotvoid.com/view.php?id=71" title="Zend Feed for a Swedish web development blog aggregator"/>

  <author>
    <name>Danne Lundqvist</name>
  </author>

  <id>http://www.dotvoid.com/view.php?id=71</id>
  <modified>2008-07-15T08:26:00+01:00</modified>
  <issued>2007-03-11T20:09:00+01:00</issued>
  <content type="text/html" mode="escaped">
    <![CDATA[<p>Lately I have begun to get more and more annoyed with my feed reader. I use a simple feed reader which lack most features except for subscribing to and reading feeds. The one thing that annoys me the most is that it can't aggregate several feeds into one feed. Yesterday I finally decided to scratch that itch.</p><p>What I want to aggregate are Swedish web development and web entrepeneur blogs. I like the <a target="" title="" href="http://www.planetplanet.org/">planet-planet</a> concept that for example <a target="" title="" href="http://www.planet-php.net/">planet-php</a> use. (Though I don't think planet-php use python...) Conveniently I had this <a target="" title="" href="http://en.wikipedia.org/wiki/Internationalized_domain_name">idn domain</a>, <a target="" title="" href="http://xn--versikt-80a.se">översikt.se</a>, lying around which I haven't used up until now. As is normal nowadays (for me at least) I used Zend Framework to build the site. It was the first time I used Zend_Feed class. I works like a charm.</p><p>The whole website logic (both model and controller) is about 200 lines of code. And the main logic of fetching the feeds are really nice and short.</p><pre>foreach($urls as $url) {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $feed = Zend_Feed::import($url['feedurl']);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch(PDOException $ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error_log($ex-&gt;getMessage());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; $feedTitle = $feed-&gt;title;<br>&nbsp;&nbsp;&nbsp; $feedLink = $feed-&gt;link;<br>&nbsp;&nbsp;&nbsp; $title = '';<br>&nbsp;&nbsp;&nbsp; $link = '';<br>&nbsp;&nbsp;&nbsp; $desc = '';<br>&nbsp;&nbsp;&nbsp; $pub = '';<br><br>&nbsp;&nbsp;&nbsp; foreach ($feed as $item) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (is_a($feed, "Zend_Feed_Rss")) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $title = $item-&gt;title();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $link = $item-&gt;link();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $desc = $item-&gt;description();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $publ = ($item-&gt;pubDate()) ? $item-&gt;pubDate() : $item-&gt;date();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(is_a($feed, "Zend_Feed_Atom")) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $title = $item-&gt;title();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $link = $item-&gt;link('alternate');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $desc = $item-&gt;content();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $publ = ($item-&gt;issued()) ? $item-&gt;issued() : $item-&gt;published();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error_log("Feed &lt;$feedid&gt; is an unsupported format");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Parse and normalize date and check if new<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $time = strtotime($publ);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $publ = date("c", $time);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Execute the previously prepared sql insert statement<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $result = $sti-&gt;execute(array(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'feedid' =&gt; $url['feedid'],<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'title' =&gt; $title,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'link' =&gt; $link,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'publ' =&gt; $publ,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'desc' =&gt; $desc));<br>&nbsp;&nbsp;&nbsp; }<br>}</pre><p>I skipped database exception and error handing in the above code to make it even more readable. Zend_Feed have failed me only once when trying to read and parse an old weird rss format. Wonderful.</p><p>(For those that don't have browsers that support idn-domains I linked to the punycode variant of the domain name översikt.se, www.xn--versikt-80a.se, above. But mostly because my damn editor refuses to use the Swedish letter "ö" in the href attribute.)<br></p>]]>
  </content>
 </entry>

</feed>