<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>PHP is not Java! - PHP</title>
    <link>http://100days.de/serendipity/</link>
    <description>PHP, Project Management and the Real World</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.5.2 - http://www.s9y.org/</generator>
    <pubDate>Thu, 28 Aug 2008 18:24:48 GMT</pubDate>

    <image>
        <url>http://100days.de/serendipity/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: PHP is not Java! - PHP - PHP, Project Management and the Real World</title>
        <link>http://100days.de/serendipity/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>Dumping MemcacheD Content (Keys) with PHP</title>
    <link>http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html</link>
            <category>PHP</category>
    
    <comments>http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html#comments</comments>
    <wfw:comment>http://100days.de/serendipity/wfwcomment.php?cid=55</wfw:comment>

    <slash:comments>12</slash:comments>
    <wfw:commentRss>http://100days.de/serendipity/rss.php?version=2.0&amp;type=comments&amp;cid=55</wfw:commentRss>
    

    <author>nospam@example.com (Gaylord Aulke)</author>
    <content:encoded>
    &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.danga.com/memcached/&#039;);&quot;  href=&quot;http://www.danga.com/memcached/&quot; target=&quot;_blank&quot;&gt;MemcacheD &lt;/a&gt;is a very cool piece of software. When i did some optimization of a cluster based webapp lately, i was wondering how Memcache was speading my cache entries over the cluster. So i did some research for monitoring tools. A simple approach to monitoring would be to use &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.cacti.net/&#039;);&quot;  href=&quot;http://www.cacti.net/&quot; target=&quot;_blank&quot;&gt;Cacti &lt;/a&gt;to monitor status values like Cache usage, hits/sec etc. This can be done by a template like &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/dealnews.com/developers/cacti/memcached.html&#039;);&quot;  href=&quot;http://dealnews.com/developers/cacti/memcached.html&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt;. An alternative was provided by Harun Yayli: His &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/&#039;);&quot;  href=&quot;http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/&quot; target=&quot;_blank&quot;&gt;memcache.php &lt;/a&gt;which somewhat resembles the APC status page and now is a part of &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/pecl.php.net/package/memcache&#039;);&quot;  href=&quot;http://pecl.php.net/package/memcache&quot; target=&quot;_blank&quot;&gt;PECL/memcache&lt;/a&gt; is easy to setup and works well. It also allows to dive into the data structures but you need to decide for one server first, then click into a &amp;quot;Slab&amp;quot; and then you see the keys. Inspired by this, i wrote a small script that fetches all data from a memcache cluster, gets all keys out of it and then sorts and displays them in a list. Yes it it ugly and yes: the memcacheD is not answering other requests while doing a cachedump. But i found it very useful. Maybe somebody has something more advanced that he wants to point me to? This could save a lot of time...&lt;p&gt;But here is my naive approach: Assumed you have a memcache object in PHP 5 with some servers registered using addServer Method, the following can be used:&lt;/p&gt;&lt;pre&gt;	    $list = array();&lt;br /&gt;	    $allSlabs = $memcache-&amp;gt;getExtendedStats(&#039;slabs&#039;);&lt;br /&gt;	    $items = $memcache-&amp;gt;getExtendedStats(&#039;items&#039;);&lt;br /&gt;	    foreach($allSlabs as $server =&amp;gt; $slabs) {&lt;br /&gt;    	    foreach($slabs AS $slabId =&amp;gt; $slabMeta) {&lt;br /&gt;    	        $cdump = $memcache-&amp;gt;getExtendedStats(&#039;cachedump&#039;,(int)$slabId);&lt;br /&gt;    	        foreach($cdump AS $server =&amp;gt; $entries) {&lt;br /&gt;    	            if($entries) {&lt;br /&gt;        	            foreach($entries AS $eName =&amp;gt; $eData) {&lt;br /&gt;        	                $list[$eName] = array(&lt;br /&gt;        	                     &#039;key&#039; =&amp;gt; $eName,&lt;br /&gt;        	                     &#039;server&#039; =&amp;gt; $server,&lt;br /&gt;        	                     &#039;slabId&#039; =&amp;gt; $slabId,&lt;br /&gt;        	                     &#039;detail&#039; =&amp;gt; $eData,&lt;br /&gt;        	                     &#039;age&#039; =&amp;gt; $items[$server][&#039;items&#039;][$slabId][&#039;age&#039;],&lt;br /&gt;        	                     );&lt;br /&gt;        	            }&lt;br /&gt;    	            }&lt;br /&gt;    	        }&lt;br /&gt;    	    }&lt;br /&gt;	    }&lt;br /&gt;	    ksort($list);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I then added a very simple HTML Table output to list the result array and found out some interesting details about my application that i dont want to share here &lt;img src=&quot;http://100days.de/serendipity/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;&lt;p&gt;It worked for me but it could be that for bigger Memcache Clusters (mine has only 10 servers) or big content tables this will not return the complete content. More to come...&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 28 Aug 2008 20:24:48 +0200</pubDate>
    <guid isPermaLink="false">http://100days.de/serendipity/archives/55-guid.html</guid>
    
</item>
<item>
    <title>Notification Free PHP Coding</title>
    <link>http://100days.de/serendipity/archives/50-Notification-Free-PHP-Coding.html</link>
            <category>PHP</category>
    
    <comments>http://100days.de/serendipity/archives/50-Notification-Free-PHP-Coding.html#comments</comments>
    <wfw:comment>http://100days.de/serendipity/wfwcomment.php?cid=50</wfw:comment>

    <slash:comments>26</slash:comments>
    <wfw:commentRss>http://100days.de/serendipity/rss.php?version=2.0&amp;type=comments&amp;cid=50</wfw:commentRss>
    

    <author>nospam@example.com (Gaylord Aulke)</author>
    <content:encoded>
    &lt;p&gt;Sorry guys, flamebait again. But i need to say this: I HATE NOTIFICATION FREE PROGRAMMING in PHP!&lt;br /&gt;If you want to code Java, go ahead! If you use PHP, enjoy the simplicity it brings!&lt;br /&gt;Today i found this code by someone who really wants to do it right:&lt;/p&gt;&lt;pre&gt;   $email = (key_exists(&#039;email&#039;, $values)) ? $values[&#039;email&#039;] : null;&lt;br /&gt;   $password = (key_exists(&#039;password&#039;, $values)) ? $values[&#039;password&#039;] : null;&lt;br /&gt;   $firstName = (key_exists(&#039;firstname&#039;, $values)) ? $values[&#039;firstname&#039;] : null;&lt;br /&gt;   $secondName = (key_exists(&#039;secondname&#039;, $values)) ? $values[&#039;secondname&#039;] : null;&lt;/pre&gt;&lt;p&gt;Honestly: This does not make any sense at all. It just pollutes your code with technical constructs that don&#039;t contribute to a solution.&lt;/p&gt;&lt;p /&gt;&lt;p&gt;UPDATE: Just to make this clear: I am _not_ talking about not input filtering here! Of course every input needs to be whitelist-filtered. And every ouput escaped to prevent XSS. What i mean is internals of you script: You can count on PHP to do things for you. This is exact because PHP does it in exact the same way everytime the script is executed.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Sat, 21 Jun 2008 16:22:13 +0200</pubDate>
    <guid isPermaLink="false">http://100days.de/serendipity/archives/50-guid.html</guid>
    
</item>
<item>
    <title>PHP vs. Java</title>
    <link>http://100days.de/serendipity/archives/45-PHP-vs.-Java.html</link>
            <category>PHP</category>
    
    <comments>http://100days.de/serendipity/archives/45-PHP-vs.-Java.html#comments</comments>
    <wfw:comment>http://100days.de/serendipity/wfwcomment.php?cid=45</wfw:comment>

    <slash:comments>12</slash:comments>
    <wfw:commentRss>http://100days.de/serendipity/rss.php?version=2.0&amp;type=comments&amp;cid=45</wfw:commentRss>
    

    <author>nospam@example.com (Gaylord Aulke)</author>
    <content:encoded>
    &lt;p&gt;Everyone working with PHP is probably asked quite often what the difference is between PHP and Java (or C#/.Net). Besides the usual aspects: scripting vs. compiled and in-process vs. seperate process and Multithreading etc., i think there are some &amp;quot;soft facts&amp;quot; that might be even more important for commercial software development.&lt;/p&gt;&lt;p&gt;For example: In Java (or C#) you can code any architecture for any Problem. Some will need more development time and more hardware, others less. In PHP you still have a lot of ways to solve a problem but not as many as in other languages because of the limits to object lifetime. Some of the possible solutions will lead to a dead-end road in terms of performance and maintainability. Therefore, intelligent PHP developers tend to communicate first. They search for proven solutions, maybe existing PHP-Extensions and working code before defining an architecture (and i dont mean Design Patterns, but examples of working solutions). Maybe it even helps in this case that quite some PHP developers don&#039;t have a solid computer science background and therefore they need this kind of inspiration to find a solution at all. On the other side, people tend to be proud if they have something working in PHP thus blog about it and opensource their architecture and code.&lt;/p&gt;&lt;p&gt;Of course you find all this also in Java or C#, but much much more in the PHP area. It seems like the &amp;quot;Not-Invented-Here&amp;quot; syndrome is less mighty here or people are more motivated to share.&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Anyway, the result is: Even though there are not so many standards in the PHP world, successful developers have a common understanding about the do&#039;s and don&#039;ts in PHP. This unwritten standardization leads to a very interesting fact (also shown in the &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.plat-forms.org/2007&#039;);&quot;  href=&quot;http://www.plat-forms.org/2007&quot; target=&quot;_blank&quot;&gt;Plat-Forms&lt;/a&gt; contest): PHP solutions of different teams (of comparable skill level) are much more consistent than in Java (or probably C# (&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.mi.fu-berlin.de/wiki/bin/view/Main/LutzPrechelt&#039;);&quot;  href=&quot;https://www.mi.fu-berlin.de/wiki/bin/view/Main/LutzPrechelt&quot; target=&quot;_blank&quot;&gt;Prof. Prechelt&lt;/a&gt;, please forgive me this un-scientific deduction)). Meaning: PHP appears more predictable than other programming languages. Now this is a fact that the business decision takers might be interested in...&lt;/p&gt; 
    </content:encoded>

    <pubDate>Sun, 18 May 2008 13:01:23 +0200</pubDate>
    <guid isPermaLink="false">http://100days.de/serendipity/archives/45-guid.html</guid>
    
</item>
<item>
    <title>requirements management, the php way</title>
    <link>http://100days.de/serendipity/archives/32-requirements-management,-the-php-way.html</link>
            <category>PHP</category>
    
    <comments>http://100days.de/serendipity/archives/32-requirements-management,-the-php-way.html#comments</comments>
    <wfw:comment>http://100days.de/serendipity/wfwcomment.php?cid=32</wfw:comment>

    <slash:comments>9</slash:comments>
    <wfw:commentRss>http://100days.de/serendipity/rss.php?version=2.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    

    <author>nospam@example.com (Gaylord Aulke)</author>
    <content:encoded>
    
&lt;p&gt;In typical PHP projects, people are afraid of spending more hours in development that actually planned. As a main reason for this exceeding the estimated (thus paid) budget of hours, usually &amp;quot;technical problems&amp;quot; are given. But the experience (and some empirical studies) show that this is not really true: Especially for bigger projects (&amp;gt;100 person days) a much bigger danger lies in understanding the requirements right. Of course we work iteratively and of course we re-estimate each feature right before we start implementig it. But our customers have internal processes and thus they need to scope the project  very detailed upfront. So we need to tell them what we will deliver and what cost are involved with it. Actually, what we need is an adapted form of planning game as described in agile methods: We need to gather all functional requirements from an unstructured document and we need to roughly estimate on a basis of these requirements in order to define features and scope the project right. &lt;/p&gt;&lt;p&gt;There are a lot of books about classical requirements management for the usual waterfall project model. In the PHP world, things are more dynamic and change more often. We have solved this problem for a quite big project currently. Our PHP-minded approach looks like this:&lt;/p&gt;&lt;p&gt;1. We get a functional requirements document from the customer. This is his &amp;quot;wishlist&amp;quot;&lt;/p&gt;&lt;p&gt;2. We derive the actual requirements from this document. This is important because the customer tends to distribute similar requirements via the whole specification and thus, the structure of his document is usually not suitable for our project organisation.&lt;/p&gt;&lt;p&gt;We list the requirements in an excel sheet that has the following columns:&lt;/p&gt;&lt;p&gt;- Chapter in the original document of the customer&lt;br /&gt;- Brief description of the feature&lt;br /&gt;- Rough first estimation of the development effort (we use person days, but you could also use &amp;quot;feature points&amp;quot;)&lt;br /&gt;- Comment field for assumptions regarding the estimation&lt;br /&gt;- a feature number and feature name&lt;/p&gt;&lt;p&gt;While we isolate requirements, we immediately associate them with features. If no feature had been defined before that matches the new requirement, we add a new one. In excel that is easy: just type a new feature name, the completion feature of excel helps to aviod mis-spelling when referring to a previously defined feature. Feature numbers we assign in a separate list and also write to our requirements list.&lt;/p&gt;&lt;p&gt;We put every requirement we find into the list. Even if it is double (i.e. mentioned in a different chapter). This way, we build a relation between chapters in the requirements document and our feature numbers.&lt;/p&gt;&lt;p&gt;3. Now we sort the list by feature. After that we see all the requirements that were redundant. We keep them in the list, but reduce the estimated hours if the redundant ones to 0. This way we keep the relation but avoid doubling the estimated cost.&lt;/p&gt;&lt;p&gt;4. My new favorite feature in Excel: Pivot Tables. I am not a microsoft fan, but this is really cool: Excel can aggregate all estimated hours per feature in such a table. The result is a list if disctinct features with the associated estimated days.&lt;/p&gt;&lt;p&gt;5. This table we can then discuss with the customer. We know where the effort comes from and we know where in the specification document the requirements for this were hidden. The customer might then say: &amp;quot;Let us talk about this feature, i don&#039;t want to spend so much time on it&amp;quot;. We can then look into the requirements list for this feature and check what the biggest points are and if we can reduce effort here.&lt;/p&gt;&lt;p&gt;6. During this discussion, we add another 2 Columns to our excel sheet: New Estimation and New Comment. After (or better: during) the discussion with the customer, we fill in the newly estimated person days and the comment, what was changed towards the old estimation in these columns. Then we define another Column in the Pivot Table that aggregates this new estimations per Feature for us.&lt;/p&gt;&lt;p&gt;7. Finally we write down the features along with the references to the specification document, the new estimated time and the new comments (if any) in a technical specification document, add some design and architecture information and we have our offer.&lt;/p&gt;&lt;p&gt;We tried quite a lot of approaches in projects of different sizes but this seemed to be the best way so far for us to deal with big specification documents the PHP way. Maybe someday if i have a lot of time, i will write a database driven PHP app replacing the Excel sheet. But so far, it works great this way &lt;img src=&quot;http://100days.de/serendipity/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 15 Apr 2008 09:23:59 +0200</pubDate>
    <guid isPermaLink="false">http://100days.de/serendipity/archives/32-guid.html</guid>
    
</item>
<item>
    <title>Zend Download Server</title>
    <link>http://100days.de/serendipity/archives/29-Zend-Download-Server.html</link>
            <category>PHP</category>
    
    <comments>http://100days.de/serendipity/archives/29-Zend-Download-Server.html#comments</comments>
    <wfw:comment>http://100days.de/serendipity/wfwcomment.php?cid=29</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://100days.de/serendipity/rss.php?version=2.0&amp;type=comments&amp;cid=29</wfw:commentRss>
    

    <author>nospam@example.com (Gaylord Aulke)</author>
    <content:encoded>
    
&lt;p&gt;The Zend Download Server (ZDS) (Part of the &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.zend.com/en/products/platform/&#039;);&quot;  target=&quot;_blank&quot; href=&quot;http://www.zend.com/en/products/platform/&quot;&gt;Zend Platform&lt;/a&gt; product) takes over long running download processes from the apache/php running the actual web application. The download is then handled by a very lighweight process, saving resources. This is very similar to &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/trac.lighttpd.net/trac/wiki/HowToFightDeepLinking&#039;);&quot;  href=&quot;http://trac.lighttpd.net/trac/wiki/HowToFightDeepLinking&quot; target=&quot;_blank&quot;&gt;X-LIGHTTPD-send-file&lt;/a&gt; of &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/www.lighttpd.net/&#039;);&quot;  href=&quot;http://www.lighttpd.net/&quot; target=&quot;_blank&quot;&gt;lighty &lt;/a&gt;or its apache-port &lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/tn123.ath.cx/mod_xsendfile/&#039;);&quot;  href=&quot;http://tn123.ath.cx/mod_xsendfile/&quot; target=&quot;_blank&quot;&gt;mod_xsendfile&lt;/a&gt; (while this only does half of the job). The advantage of ZDS is that it can also send strings and streams that do not nessecarily reside as files on any harddrive. It is as easy as calling: &lt;/p&gt;&lt;pre&gt;zend_send_file(&amp;lt;filename&amp;gt;,&amp;lt;mimetype&amp;gt;,&amp;lt;headers&amp;gt;) &lt;/pre&gt;&lt;p&gt;or &lt;/p&gt;&lt;pre&gt;zend_send_buffer($phpVar,&amp;lt;mimetype&amp;gt;,&amp;lt;headers&amp;gt;).&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;Then, the PHP process is terminated and the content is delivered using the ZDS.&lt;/p&gt;&lt;p&gt;So much the theory. There are three issues to consider though:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;ZDS discards all headers that have been set by the PHP header() function in advance. If you want to send headers (like content-disposition of filename), you need to use the optional &amp;lt;headers&amp;gt; parameter.&lt;/li&gt;&lt;li&gt;To determine the mime type of the file to be sent, ZDS uses its own mime-Type-Lookup-File. It does not use the apache mime.types.&lt;/li&gt;&lt;li&gt;If sending a file, make sure that it resides on local file system since ZDS uses mmapping to access the file, which is quite inefficient (if not dangerous) on network mounts like NFS3.&lt;/li&gt;&lt;/ul&gt; 
    </content:encoded>

    <pubDate>Tue, 25 Mar 2008 12:45:30 +0100</pubDate>
    <guid isPermaLink="false">http://100days.de/serendipity/archives/29-guid.html</guid>
    
</item>

</channel>
</rss>