<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4072966502572230680</id><updated>2012-05-05T17:16:50.680+02:00</updated><category term='test'/><category term='ranting'/><category term='mediawiki'/><category term='mdb2'/><category term='phpCodeSniffer'/><category term='scorm'/><category term='tools'/><category term='mysql'/><category term='php'/><category term='bugs'/><category term='html'/><category term='CruiseControl'/><category term='dev'/><category term='pear'/><category term='performance'/><category term='code'/><category term='ms sql'/><category term='Google'/><category term='pdf'/><category term='bugzilla'/><title type='text'>bglog</title><subtitle type='html'>Bertrand Gorge's Log</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-41198178636019275</id><published>2011-08-08T19:27:00.000+02:00</published><updated>2011-08-08T19:27:42.613+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mediawiki'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>New extension for MediaWiki + Google for your domain</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;We wrote a new extension to MediaWiki so that it can authentify users from a Google Apps account directly (using their version of OpenId). Was greatly missing for us !&amp;nbsp;&lt;a href="http://www.mediawiki.org/wiki/Extension:GoogleAppsAuthentification"&gt;http://www.mediawiki.org/wiki/Extension:GoogleAppsAuthentification&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-41198178636019275?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.mediawiki.org/wiki/Extension:GoogleAppsAuthentification' title='New extension for MediaWiki + Google for your domain'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/41198178636019275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=41198178636019275' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/41198178636019275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/41198178636019275'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2011/08/new-extension-for-mediawiki-google-for.html' title='New extension for MediaWiki + Google for your domain'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-1816324825461204499</id><published>2009-03-17T12:15:00.002+01:00</published><updated>2009-03-17T12:23:41.095+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dev'/><category scheme='http://www.blogger.com/atom/ns#' term='pdf'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>html2pdf alternatives</title><content type='html'>I'm offen asked about libraries that do what html2pdf (the one on &lt;a href="http://html2fpdf.sourceforge.net/"&gt;http://html2fpdf.sourceforge.net/&lt;/a&gt;), but without the bugs.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have found 3 others that you might want to try:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;DomPDF: &lt;a href="http://www.digitaljunkies.ca/dompdf/"&gt;http://www.digitaljunkies.ca/dompdf/&lt;/a&gt; (not much maintained, but works much beter than the original html2pdf)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;html2pdf (uses ghostscript, not fPDF): &lt;a href="http://code.google.com/p/html2pdf/"&gt;http://code.google.com/p/html2pdf/&lt;/a&gt; or &lt;a href="http://www.tufat.com/s_html2ps_html2pdf.htm"&gt;http://www.tufat.com/s_html2ps_html2pdf.htm&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-1816324825461204499?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/1816324825461204499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=1816324825461204499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/1816324825461204499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/1816324825461204499'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2009/03/html2pdf-alternatives.html' title='html2pdf alternatives'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-3542934594481056266</id><published>2008-10-07T22:35:00.002+02:00</published><updated>2008-10-07T22:46:26.302+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='phpCodeSniffer'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Everything is under control</title><content type='html'>To follow up on my last post, we've made the jump from Phing to CruiseControl and phpUnderControl. The reasons behind the change are :&lt;div&gt;&lt;ul&gt;&lt;li&gt;Phing didn't work well&lt;/li&gt;&lt;li&gt;phpUnderControl works well !&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;To be constructive, I find Phing to be a nice piece of software, but the fact it's written in PHP, and that in a few places it has to includes stuff from our application defies a little the &lt;a href="http://en.wikipedia.org/wiki/Black_box_testing"&gt;black-box&lt;/a&gt; testing concept - in particular, it broke the code coverage analysis, and all in all was a pain to set up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the contrary, CruiseControl and its patch phpUnderControl did roll quite nicely. I had to dig a little to make it work, tune the xml files here and there, but very quickly we ended up with a running setup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I found that the documentation is not as good as Phing, but now, these tools are for grown men, we're suppose to find our way in it...!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I'm twicking phpCodeSniffer, and find myself having quite a lot of fun picking the rules to match our style. Next step: &lt;a href="http://pear.php.net/manual/en/package.php.php-codesniffer.svn-pre-commit.php"&gt;hook it up to SVN&lt;/a&gt; (will my developpers like that ?)...&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-3542934594481056266?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/3542934594481056266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=3542934594481056266' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/3542934594481056266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/3542934594481056266'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/10/everything-is-under-control.html' title='Everything is under control'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-9009339674546704297</id><published>2008-09-29T22:48:00.002+02:00</published><updated>2008-09-29T23:05:08.051+02:00</updated><title type='text'>Testing a web application</title><content type='html'>We've set up a built server, with &lt;a href="http://www.phpunit.de/"&gt;PHPUnit&lt;/a&gt;, &lt;a href="http://selenium-rc.openqa.org/"&gt;Selenium RC&lt;/a&gt;, &lt;a href="http://phing.info/"&gt;Phing&lt;/a&gt; and &lt;a href="http://code.google.com/p/xinc/"&gt;Xinc&lt;/a&gt;. These tools are absolutely mind blowing !&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm still in awe in front of &lt;a href="http://www.slideshare.net/sebastian_bergmann/testing-with-phpunit-and-selenium"&gt;the level of integration&lt;/a&gt; between &lt;a href="http://www.slideshare.net/spriebsch/end-to-end-web-testing-with-selenium-presentation"&gt;PHPUnit and Selenium&lt;/a&gt;, being able to control Internet Explorer on a distant machine using PHP, that's just excellent...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We're still at the beginning of our learning curve, in particular I'm still undecided between keeping Phing and Xinc or moving to Ant, &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; and &lt;a href="http://www.phpundercontrol.org/"&gt;phpUnderControl&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now we're reaching a perfect setup, with, for each feature, a (Scrum) &lt;a href="http://www.agileadvice.com/2008/04/09/scrumxplean/three-ways-of-expanding-the-scrum-definition-of-done/"&gt;Definition of Done&lt;/a&gt; that includes a Selenium or PHPUnit scenario and a documentation page on MediaWiki. It's alreadybeen  proven usefull !&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-9009339674546704297?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/9009339674546704297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=9009339674546704297' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/9009339674546704297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/9009339674546704297'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/09/testing-web-application.html' title='Testing a web application'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-4836291934933632956</id><published>2008-08-11T11:00:00.002+02:00</published><updated>2008-08-11T11:03:23.272+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>When to use Get or Post</title><content type='html'>Every time I get someone interviewed for a position here, I ask the the same question: what's the difference between Get and Post in an HTML form, and when to use one or the other. At last, here is the answer - just RTFM!&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.w3.org/2001/tag/doc/whenToUseGet.html"&gt;http://www.w3.org/2001/tag/doc/whenToUseGet.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-4836291934933632956?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.w3.org/2001/tag/doc/whenToUseGet.html' title='When to use Get or Post'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/4836291934933632956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=4836291934933632956' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4836291934933632956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4836291934933632956'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/08/when-to-use-get-or-post.html' title='When to use Get or Post'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-2906390341142922174</id><published>2008-06-23T22:32:00.002+02:00</published><updated>2008-06-23T22:35:53.418+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Two very interesting reads</title><content type='html'>&lt;div&gt;Two powerpoints from Jay Pipes - worth a read: &lt;a href="http://jpipes.com/index.php?/archives/239-Slides-for-Join-Fu-The-Art-of-SQL-I-and-II.html"&gt;http://jpipes.com/index.php?/archives/239-Slides-for-Join-Fu-The-Art-of-SQL-I-and-II.html&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I agree with most of it !&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;a href="http://jpipes.com/index.php?/archives/239-Slides-for-Join-Fu-The-Art-of-SQL-I-and-II.html"&gt;&lt;img style="WIDTH: 400px; CURSOR: hand" alt="" src="http://jpipes.com/presentations/joinfu/joinfu_part_one.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-2906390341142922174?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://jpipes.com/index.php?/archives/239-Slides-for-Join-Fu-The-Art-of-SQL-I-and-II.html=' title='Two very interesting reads'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/2906390341142922174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=2906390341142922174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2906390341142922174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2906390341142922174'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/06/two-very-interesting-reads.html' title='Two very interesting reads'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-4645154439313311419</id><published>2008-06-06T23:12:00.001+02:00</published><updated>2008-06-06T23:16:07.994+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ranting'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>In reaction to "Where did all the PHP programmers go?"</title><content type='html'>&lt;div align="left"&gt;&lt;a href="http://mamchenkov.net/" rel="external nofollow"&gt;Leonid Mamchenkov&lt;/a&gt; is ranting about the difficulties of hiring a good PHP dev. I find the question quite valid...&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;a href="http://mamchenkov.net/wordpress/2008/06/04/where-did-all-the-php-programmers-go/"&gt;http://mamchenkov.net/wordpress/2008/06/04/where-did-all-the-php-programmers-go/&lt;/a&gt;&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;I've been hiring PHP devs for the last few years, and I too have a test that I find desesperatly easy, and that too many (even senior) applicant fail miserably... It's based on &lt;a href="http://www.techinterviews.com/"&gt;http://www.techinterviews.com/&lt;/a&gt;, with questions going from sorting an array (I only ask the applicant what he should use) to the differences between GET and POST (very highlighting question).&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;I've even been challenged by my collegues, who thought the test was too hard, so I just ran it over a few people I would hire if they'd been available, and of course, they found the test to be just fine...&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;I still believe PHP is a great language, and we produce software that is really cool with it, with low effort. It is a pleasure to write code in PHP, and the low training curve is a good thing.&lt;br /&gt;Now I've decided I'd rather hire a good professional and train him (as long as he's aware of the particularities of web applications - jumping from java to php is easier than from C++ to PHP - the syntax is one thing, the understanding of stateless software is another). All in all I agree it's very hard to find a good php developper, and I believe they all go to .Net, which I hope they like....&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-4645154439313311419?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://mamchenkov.net/wordpress/2008/06/04/where-did-all-the-php-programmers-go/' title='In reaction to &quot;Where did all the PHP programmers go?&quot;'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/4645154439313311419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=4645154439313311419' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4645154439313311419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4645154439313311419'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/06/in-reaction-to-where-did-all-php.html' title='In reaction to &quot;Where did all the PHP programmers go?&quot;'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-6981522123990840295</id><published>2008-06-05T17:43:00.003+02:00</published><updated>2008-06-05T23:55:44.145+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='pdf'/><title type='text'>PDFtk</title><content type='html'>Found PDFtk - one of these tools that save you time, exceptionnal features, free, works on windows and linux. Need no more ! (if you need to merge, split, modify PDF files)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-6981522123990840295?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.pdfhacks.com/pdftk/' title='PDFtk'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/6981522123990840295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=6981522123990840295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/6981522123990840295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/6981522123990840295'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/06/pdftk.html' title='PDFtk'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-3962080995962656401</id><published>2008-03-12T09:13:00.001+01:00</published><updated>2008-03-19T21:39:57.547+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Perfomance trics for your web application</title><content type='html'>Stéphane Thomas, from Simple Entrepreneur, has gathered a bunch of slideshares from people around town that have worked on scaling web applications:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.simpleentrepreneur.com/2008/03/11/comment-gerer-la-montee-en-charge-d-une-application-web/"&gt;http://www.simpleentrepreneur.com/2008/03/11/comment-gerer-la-montee-en-charge-d-une-application-web/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's an interesting read, to complete with &lt;a href="http://highscalability.com/"&gt;http://highscalability.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-3962080995962656401?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.simpleentrepreneur.com/2008/03/11/comment-gerer-la-montee-en-charge-d-une-application-web/' title='Perfomance trics for your web application'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/3962080995962656401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=3962080995962656401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/3962080995962656401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/3962080995962656401'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/03/perfomance-trics-for-your-web.html' title='Perfomance trics for your web application'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-6304230844216952912</id><published>2008-03-10T10:46:00.008+01:00</published><updated>2010-05-01T18:19:39.050+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugzilla'/><category scheme='http://www.blogger.com/atom/ns#' term='mediawiki'/><title type='text'>Bug Milestone</title><content type='html'>I've created a mediawiki extension that mimics Trac's ability to follow the progression of a Bugzilla milestone. All you have to do is put some bugs in a milestone, then put a tag in your wiki page with the name of the milestone, and you get a nice clickable progress bar with the bugs that are open or not: &lt;a href="http://www.mediawiki.org/wiki/Extension:BugMilestone"&gt;http://www.mediawiki.org/wiki/Extension:BugMilestone&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_CefeAc3Csf8/S9xUjrl8lhI/AAAAAAAAGgA/2_Snx_xOGNs/s1600/BugMilestone-726084%5B1%5D.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_CefeAc3Csf8/S9xUjrl8lhI/AAAAAAAAGgA/2_Snx_xOGNs/s320/BugMilestone-726084%5B1%5D.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-6304230844216952912?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.mediawiki.org/wiki/Extension:BugMilestone' title='Bug Milestone'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/6304230844216952912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=6304230844216952912' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/6304230844216952912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/6304230844216952912'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2008/03/bug-milestone.html' title='Bug Milestone'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_CefeAc3Csf8/S9xUjrl8lhI/AAAAAAAAGgA/2_Snx_xOGNs/s72-c/BugMilestone-726084%5B1%5D.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-4946520818072573982</id><published>2007-09-17T21:18:00.000+02:00</published><updated>2007-10-09T22:30:21.163+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='pear'/><category scheme='http://www.blogger.com/atom/ns#' term='ms sql'/><title type='text'>Moving from MySQL to MS SQL using PEAR MDB2</title><content type='html'>&lt;a href="http://pear.php.net/MDB2"&gt;MDB2&lt;/a&gt; is a PEAR package that performs some abstraction on the native PHP DB calls. In short, it allows to use $DB-&gt;query($sql) instead of mysql_query or mssql_query (plus a few more things).&lt;br /&gt;&lt;br /&gt;The following article is the list of pitfalls we had to fix in order to get a fully compatible application, that would run the same on MySQL or MSSQL (for now).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Field types&lt;/h2&gt;Field types are not the same between the two engines of course, but all in all it is not too bad. &lt;strong&gt;ENUMs&lt;/strong&gt; don't exist in MS SQL so these will have to be moved to CHAR(1), MEDIUMTEXT should be TEXT.&lt;br /&gt;&lt;br /&gt;If you want to use MDB2 Schema, beware that it considers ENUM('Y', 'N') to be booleans if the field starts with an "is_" or "has_", but then builds a database with boolean being TINYINT (we'll have to get back on them about that).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;SQL syntax&lt;/h2&gt;There's a few things that work in MySQL and breaks in MS SQL. Here's what we found:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;REPLACE INTO: &lt;/strong&gt;this one is a bugger, we used REPLACE extensively. Well that doesn't exist on MS SQL.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;ISNULL: &lt;/strong&gt;&lt;code&gt;ISNULL(somefield)&lt;/code&gt; should be &lt;code&gt;somefield IS NULL&lt;/code&gt;. That's the ANSI way and ISNULL won't work on MS SQL...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;IFNULL: &lt;/strong&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html"&gt;IFNULL&lt;/a&gt; is &lt;a href="http://msdn2.microsoft.com/en-us/library/ms184325.aspx"&gt;ISNULL&lt;/a&gt; on MS SQL, but you should really use the function &lt;a href="http://msdn2.microsoft.com/en-us/library/ms190349.aspx"&gt;COALESCE&lt;/a&gt;, which works the same (when used with two parameters) and is more ANSI.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;ORDER BY, GROUP BY: &lt;/strong&gt;on MS SQL, you should be carefull that all the fields that you want to ORDER BY on, should be in the SELECT clause. Same goes for GROUP BY it seems. See further for GROUP BY as it can be a real bugger...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;COUNT: &lt;/strong&gt;on MS SQL, COUNT only works with one field somehow&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;DISTINCT: &lt;/strong&gt;DISTINCT is a bit touchy on MS SQL - you should be carefull not to have fields that have type TEXT for example.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;NOW: &lt;/strong&gt;Won't work on MS SQL. MDB2 provides some utility functions to build dates for SQL, but that really does a &lt;code&gt;date('Y-m-d H:i:s')&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;TO_DAYS: &lt;/strong&gt;Won't work on MS SQL either. We really missed that one.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;LIMIT: &lt;/strong&gt;LIMIT doesn't exist in MS SQL, but MDB2 prevides a &lt;a href="http://pear.php.net/package/MDB2/docs/latest/MDB2/MDB2_Driver_Common.html#methodsetLimit"&gt;setLimit()&lt;/a&gt; function that will do the trick on all DBMS. Good enough.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;AutoIncremented fields&lt;/h2&gt;That's a big one. It'd be a good thing that DBMS makers could standardize on something for autoincremented indexes.&lt;br /&gt;&lt;br /&gt;In MySQL, if your field id is an autoincremented field, you could do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;INSERT INTO my_table (id, name) VALUES (NULL, 'first');&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That won't work on MS SQL (you can't leave a NULL value on them). The proper way to do it with MDB2 is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$values = array();&lt;br /&gt;&lt;br /&gt;$values['name'] = $GLOBALS['mdb2']-&gt;quote("first");&lt;br /&gt;&lt;br /&gt;$newId = $GLOBALS['mdb2']-&gt;extended-&gt;getBeforeID('my_table', 'id', true, true);&lt;br /&gt;if($newId != 'NULL')&lt;br /&gt; $values['id'] = $newId;&lt;br /&gt;&lt;br /&gt;$sql = "INSERT INTO my_table (".implode(',', array_keys($values)).") ".&lt;br /&gt;    " VALUES (" . implode(',', $values) . ")";&lt;br /&gt;&lt;br /&gt;$result = $GLOBALS['mdb2']-&gt;query($sql);&lt;br /&gt;if (EpiDBTools::IsMDB2Error($result))&lt;br /&gt; return false;&lt;br /&gt;&lt;br /&gt;$newId = $GLOBALS['mdb2']-&gt;extended-&gt;getAfterID($newId, 'my_table', 'id');&lt;br /&gt;if (PEAR::isError($newId))&lt;br /&gt;{&lt;br /&gt; $newId = false;&lt;br /&gt; return false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's a bit verbose but it works. The getBeforeID is required if you want your code to work some day on PostgreSQL, which uses sequences instead of AutoIncrement values.&lt;br /&gt;&lt;br /&gt;Now if you want to insert a row in table with an autoincremented field, and still want to explicit the value of the index, you'll need to enable the IDENTITY_INSERT first, like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if ($GLOBALS['mdb2']-&gt;dbsyntax == 'mssql')&lt;br /&gt;{&lt;br /&gt; // On MS SQL, allow temporarilly to insert a row by specifying the id&lt;br /&gt; $result = $GLOBALS['mdb2']-&gt;query('SET IDENTITY_INSERT my_table ON');&lt;br /&gt; if (PEAR::isError($result))&lt;br /&gt;   return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$sql = "INSERT INTO my_table (id, name) VALUES (4, 'first')";&lt;br /&gt;&lt;br /&gt;$result = $GLOBALS['mdb2']-&gt;query($sql);&lt;br /&gt;if (PEAR::isError($result))&lt;br /&gt; return false;&lt;br /&gt;&lt;br /&gt;if ($GLOBALS['mdb2']-&gt;dbsyntax == 'mssql')&lt;br /&gt;{&lt;br /&gt; $result = $GLOBALS['mdb2']-&gt;query('SET IDENTITY_INSERT my_table OFF');&lt;br /&gt; if (PEAR::isError($result))&lt;br /&gt;   return false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Even more verbose, but it works.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;MS SQL settings&lt;/h2&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa259217%28SQL.80%29.aspx"&gt;ANSI_NULL_DFLT_ON&lt;/a&gt;: &lt;/strong&gt;you should set this parameter to ON, if you don't want all your fields to be NOT NULL...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa259220%28SQL.80%29.aspx"&gt;IMPLICIT_TRANSACTIONS&lt;/a&gt;: &lt;/strong&gt;beware that if you leave that ON, then you'll have to do COMMITs from time to time, otherwise your changes won't be taken in account in the database. If you come from the MyISAM world, set this one to off (which is ON by default if you set ANSI_DEFAULTS to on).&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;GROUP BY&lt;/h2&gt;In MySQL, I allow myself to do queries like the following to get all the clients that have at least one order:&lt;br /&gt;&lt;br /&gt;SELECT * FROM client&lt;br /&gt;INNER JOIN order ON order.client_id = client.id&lt;br /&gt;GROUP BY client.id&lt;br /&gt;&lt;br /&gt;That &lt;span style="font-weight: bold;"&gt;won't&lt;/span&gt; work with MS SQL. In the SELECT clause, you are allowed to put things that appear in the GROUP BY clause (ie. client.id), or GROUP BY functions (MAX, AVERAGE, ...). It appears that MySQL is much more flexible than MSSQL regarding to this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-4946520818072573982?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/4946520818072573982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=4946520818072573982' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4946520818072573982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/4946520818072573982'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/09/moving-from-mysql-to-ms-sql-using-pear.html' title='Moving from MySQL to MS SQL using PEAR MDB2'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-2746661827958892061</id><published>2007-05-08T20:39:00.000+02:00</published><updated>2007-05-08T22:54:19.250+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Dynamic inheritence for application extension in PHP</title><content type='html'>In any big enough PHP application, comes a time when some of the objects that are used in the application might be overriden by some extensions, to customize the functionnality of the application.&lt;br /&gt;&lt;br /&gt;Let's take a example: your application has a class Employee that deals with the logic for every employee in your client's organization. Now imagine you have a client that wants to buy your application but wants to synchronize the employee table with its LDAP directory - fair enough.&lt;br /&gt;&lt;br /&gt;What we want to do, is really to extend the Employee class, so that we can change the code of a few functions and add a few others to give your final client the behaviour he asks for.&lt;br /&gt;&lt;br /&gt;So we add an extension (a folder really) where we put a class that extends Employee. We call that class LDAP_Employee for the sake of clarity:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;class LDAP_Employee extends Employee&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;function LDAP_Employee($id)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&gt;Employee($id);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Some more code to deal with the LDAP directory ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;// ...&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now the problem we have, is that everywhere in our application, the instances are still created out of the original Employee class.&lt;br /&gt;&lt;br /&gt;The trick is to use function variables to create the instances.&lt;br /&gt;&lt;br /&gt;Let's say you have a global variable defined at the top of the application:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$GLOBALS['ClassDefinitions']['Employee'] = 'Employee'; // Name of the original class&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now, to instanciate an employee we just need to do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$MyEmployee = new $GLOBALS['ClassDefinitions']['Employee']($MyId);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If we want to use the LDAP_Employee class, we just need to change the global once, high enough in the application initialization routine - where the extensions are loaded, basically:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$GLOBALS['ClassDefinitions']['Employee'] = 'LDAP_Employee'; // Now we'll use the overriden class everywhere&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The rest of the code is left unchanged, but the behaviour of the whole application is now changed.&lt;br /&gt;&lt;br /&gt;The only downside of this method, is that the overriden classes need to know exactly what class they extend (you can't have a variable after the extend keyword). So if you have a second extension that wanted to extends Employee, you're cooked. (you can, however, have a third extension that extends LDAP_Employee, of course)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-2746661827958892061?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/2746661827958892061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=2746661827958892061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2746661827958892061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2746661827958892061'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/05/dynamic-inheritence-for-application.html' title='Dynamic inheritence for application extension in PHP'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-2586768909953628151</id><published>2007-04-06T10:30:00.001+02:00</published><updated>2008-03-19T21:44:57.716+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>file_exists - the performance killer....</title><content type='html'>I recently went into some profiling for one of our apps, because a page was taking more than two minutes to display...&lt;br /&gt;&lt;br /&gt;I found, to my surprise, that a call to file_exists (in a loop) was taking 95 percent of that time... Wtf ??? I just cached the result to the call to gain that much time... Good to know !&lt;br /&gt;&lt;br /&gt;As a side note, I did the profiling with the latest version of PHPEd (Nusphere), great tool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-2586768909953628151?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/2586768909953628151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=2586768909953628151' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2586768909953628151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/2586768909953628151'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/04/fileexists-performance-killer.html' title='file_exists - the performance killer....'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-336255440471927954</id><published>2007-03-09T11:35:00.002+01:00</published><updated>2010-05-01T18:21:11.353+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Hierarchical structures in SQL</title><content type='html'>I wish I read this before... The "id, name, parent_id" way of storing trees in a SQL table is probably the most inneficient way to do it! There is a better way of doing things, and here it is:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html"&gt;http://dev.mysql.com/tech-resources/articles/hierarchical-data.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_CefeAc3Csf8/S9xU8WnXGtI/AAAAAAAAGgI/ut03-0oD42I/s1600/hierarchical-data-5-743056%5B1%5D.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_CefeAc3Csf8/S9xU8WnXGtI/AAAAAAAAGgI/ut03-0oD42I/s320/hierarchical-data-5-743056%5B1%5D.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://blogs.epistema.com/bg/uploaded_images/hierarchical-data-5-754430.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-336255440471927954?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://dev.mysql.com/tech-resources/articles/hierarchical-data.html' title='Hierarchical structures in SQL'/><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/336255440471927954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=336255440471927954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/336255440471927954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/336255440471927954'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/03/hierarchical-structures-in-sql.html' title='Hierarchical structures in SQL'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_CefeAc3Csf8/S9xU8WnXGtI/AAAAAAAAGgI/ut03-0oD42I/s72-c/hierarchical-data-5-743056%5B1%5D.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-7962356780394603708</id><published>2007-01-05T17:49:00.000+01:00</published><updated>2007-01-05T20:15:49.403+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='scorm'/><title type='text'>Fun with SCORM 2004</title><content type='html'>I'm doing some work making one of our app "Scorm 2004" compliant. I'm baffled to see how easy it is now that we have &lt;a href="http://prototype.conio.net/"&gt;prototype.js&lt;/a&gt;, as if the people who designed SCORM way back then had XHRs in mind... In any case, it helps to just do a ajax.request for the commit function...&lt;br /&gt;&lt;br /&gt;Now, they didn't always have such a good visionnary view on things, especially when they decided to switch the format of cmi.session_time. WTF is that ? &lt;span style="font-family:courier new;"&gt;PT3H5M3.5S&lt;/span&gt; for 3 hours 5 minutes and 3.5 seconds...? Not only is it complex to parse (for the PHP minded, I give away the code right below), but now look at this: &lt;span style="font-family:courier new;"&gt;P1Y3M2DT3H&lt;/span&gt; equals 1 year, 3 months, 2 days and 3 hours. Her.... What's a month, please ? Is that 30 days ? 31 ? Should I guess ? And why choose the same character for months and minutes ? bah.&lt;br /&gt;&lt;br /&gt;Ok. Now some code:&lt;br /&gt;&lt;pre&gt;function GetSecondsForScormPeriod&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$strScormPeriod&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt; $matches &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; array&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;  if&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;!&lt;/span&gt;preg_match&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:PURPLE;"&gt;"/^P([0-9]+Y)?([0-9]+M)?([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+(.[0-9]+)?S)?)?$/"&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt; $strScormPeriod&lt;span style="color:BLUE;"&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt; $matches&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:RED;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BROWN;"&gt;0&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; $seconds &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BROWN;"&gt;0&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt; $InTime &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; false&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; foreach &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$matches as $aMatch&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;  {&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;   if&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$aMatch&lt;span style="color:BLUE;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BROWN;"&gt;0&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;=&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'P'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:RED;"&gt;&lt;b&gt;   continue&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;    &lt;span style="color:RED;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$aMatch&lt;span style="color:BLUE;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BROWN;"&gt;0&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;=&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'T'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:BLUE;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;     $InTime &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; true&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:RED;"&gt;&lt;b&gt;   continue&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;   }&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   $unit &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; substr&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$aMatch&lt;span style="color:BLUE;"&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;-&lt;/span&gt;&lt;span style="color:BROWN;"&gt;1&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;   $val &lt;span style="color:BLUE;"&gt;=&lt;/span&gt; substr&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$aMatch&lt;span style="color:BLUE;"&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BROWN;"&gt;0&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;-&lt;/span&gt;&lt;span style="color:BROWN;"&gt;1&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;   switch&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$unit&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;   {&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:RED;"&gt;&lt;b&gt;   case&lt;/b&gt;&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'Y'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;:&lt;/span&gt; $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;365&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;24&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt; &lt;span style="color:RED;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color:RED;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'M'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;:&lt;/span&gt;&lt;br /&gt;       &lt;span style="color:RED;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;!&lt;/span&gt;$InTime&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;         $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;30&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;24&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color:RED;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;         $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color:RED;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;      &lt;span style="color:RED;"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'D'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;:&lt;/span&gt; $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;24&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt; &lt;span style="color:RED;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:RED;"&gt;&lt;b&gt;   case&lt;/b&gt;&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'H'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;:&lt;/span&gt; $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt; &lt;span style="color:BLUE;"&gt;*&lt;/span&gt; &lt;span style="color:BROWN;"&gt;60&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt; &lt;span style="color:RED;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:RED;"&gt;&lt;b&gt;   case&lt;/b&gt;&lt;/span&gt; &lt;span style="color:PURPLE;"&gt;'S'&lt;/span&gt;&lt;span style="color:BLUE;"&gt;:&lt;/span&gt; $seconds &lt;span style="color:BLUE;"&gt;+&lt;/span&gt;&lt;span style="color:BLUE;"&gt;=&lt;/span&gt; &lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;float&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;$val&lt;span style="color:BLUE;"&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt; &lt;span style="color:RED;"&gt;&lt;b&gt;break&lt;/b&gt;&lt;/span&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;   }&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;  }&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:RED;"&gt;&lt;b&gt;  return&lt;/b&gt;&lt;/span&gt; $seconds&lt;span style="color:BLUE;"&gt;&lt;b&gt;;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:BLUE;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-7962356780394603708?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/7962356780394603708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=7962356780394603708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/7962356780394603708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/7962356780394603708'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/01/fun-with-scorm-2004.html' title='Fun with SCORM 2004'/><author><name>Bertrand Gorge</name><uri>http://www.blogger.com/profile/03049826000504937239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_CefeAc3Csf8/S5KfbutNUZI/AAAAAAAAGME/isFOfmp-u-k/s1600-R/a19a6d8d6908e0b44ef6ffb90a9da253.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4072966502572230680.post-5020150841044076911</id><published>2007-01-05T15:02:00.000+01:00</published><updated>2007-05-08T23:00:45.250+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='scorm'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP Bug</title><content type='html'>Found what I'd call &lt;a href="http://bugs.php.net/bug.php?id=40000"&gt;a rather anoying bug in PHP&lt;/a&gt;. Because of the historic way of passing POST and GET values through global variables instead of the &lt;span style="font-family:courier new;"&gt;$_POST&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;$_GET&lt;/span&gt; autoglobals everyone uses nowadays, any character that is not valid in the name of a variable is replaced with an underscore...&lt;br /&gt;&lt;br /&gt;For example, if you have a form with &lt;&lt;span style="font-family:courier new;"&gt;input name="cmi.session_time" value="P1Y3M2DT3H" type="hidden"&lt;/span&gt;&gt; you'll get &lt;span style="font-family:courier new;"&gt;$_POST['cmi_session_time']&lt;/span&gt;. Not very usefull at all (spot the dot that became an underscore)...&lt;br /&gt;&lt;br /&gt;Let's just hope it gets fixed someday.&lt;br /&gt;&lt;br /&gt;Funilly enough, the bug reported on bugs.php.net got numbered 40000... lucky number !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4072966502572230680-5020150841044076911?l=bglog.blogs.epistema.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bglog.blogs.epistema.com/feeds/5020150841044076911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4072966502572230680&amp;postID=5020150841044076911' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/5020150841044076911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4072966502572230680/posts/default/5020150841044076911'/><link rel='alternate' type='text/html' href='http://bglog.blogs.epistema.com/2007/01/php-bug.html' title='PHP Bug'/><author><name>Bertrand Gorge</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
