<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Martijn&#039;s PHP Coding Blog &#187; PHP</title>
	<atom:link href="http://php.dijksterhuis.org/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://php.dijksterhuis.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 18 Jan 2010 07:45:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>MySQL Certified Developer 5.0 Part II</title>
		<link>http://php.dijksterhuis.org/mysql-certified-developer-5-0-part-ii/</link>
		<comments>http://php.dijksterhuis.org/mysql-certified-developer-5-0-part-ii/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 06:09:25 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=92</guid>
		<description><![CDATA[While parts of the world are still freezingly cold, Taipei is already slowly warming up to 21 degrees, blue skies and sunshine. Sadly enough as this is my last day in the city for probably a very long time. Tomorrow I will fly off to a new life in the old country. After twelve years [...]<p><a href="http://php.dijksterhuis.org/mysql-certified-developer-5-0-part-ii/">MySQL Certified Developer 5.0 Part II</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://php.dijksterhuis.org/wp-content/uploads/2010/01/taipei.jpg" alt="Taipei Taxi by Robert S. Donovan" title="Taipei Taxi by Robert S. Donovan" width="500" height="296" class="alignnone size-full wp-image-93" /></p>
<p>While parts of the world are still freezingly cold, Taipei is already slowly warming up to  21 degrees, blue skies and sunshine. Sadly enough as this is my last day in the city for probably a very long time. Tomorrow I will fly off to a new life in the old country. After twelve years of travelling all over the island this place really feels like home. </p>
<p>Today was also the last day that I could take the second and final part of the MySQL 5.0 Developer certifications. The US$ 200 SUN exam voucher I had purchased earlier is only valid in Taiwan. Taking the exam in the Netherlands was thus not an option. </p>
<p>Looking back at <a href="http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/">my previous blog entry about the MySQL Examens </a> &#8212; it took me 20 days to prepare this part of the exam. I studied by browsing through the exam book at breakfast and before going to bed and added some more serious study blocks to work through all the exercise questions. </p>
<p>The second exam was quite a bit harder than the first one mostly because it asked many interesting (and confusing/tricky) questions about inner, left and right joins and of course sub-queries. </p>
<p>But what I found the hardest chapter in the book <em>Chapter 18. Stored Procedures and Functions</em> in which a complete programming language is introduced using only about 2-3 examples was good for only a few questions. Just pay attention to the correct syntax. </p>
<p>Overal I really enjoyed studying for the exam. The MySQL exam preparation book is excellent and covers the exam exactly. </p>
<p><a href="http://php.dijksterhuis.org/mysql-certified-developer-5-0-part-ii/">MySQL Certified Developer 5.0 Part II</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/mysql-certified-developer-5-0-part-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preparing for the MySQL Developer examinations</title>
		<link>http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/</link>
		<comments>http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 03:32:08 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[exam]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=83</guid>
		<description><![CDATA[As promised in my last post (twenty days ago &#8212; life has been busy!) I am working through the MySQL Developer 5.0 examinations. I have just completed the first of two exams and I am trying to find time to cram for the second exam. There are plenty of changes going on here &#8212; the [...]<p><a href="http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/">Preparing for the MySQL Developer examinations</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/12/subway2.jpg" alt="Subway in Taipei" title="Subway in Taipei" width="500" height="284" class="alignnone size-full wp-image-87" /></p>
<p>As promised in my last post (twenty days ago &#8212; life has been busy!) I am working through the MySQL Developer 5.0 examinations. I have just completed the first of two exams and I am trying to find time to cram for the second exam.</p>
<p>There are plenty of changes going on here &#8212; the original exam MySQL exam provider was changed this year from Pearson Vu to Prometric as Sun Microsystems acquired MySQL.</p>
<p>And now of course Sun is in limbo as it in turn is being acquired by Oracle &#8212; a deal being blocked in Europe because of , yes :  MySQL. For a by the minute discussion of what is going on there just keep track of the postings at <a title="Planet MySQL" href="http://planet.mysql.com/">Planet MySQL</a>.</p>
<p>Expect many FAQ&#8217;s to be out of date. It is better to check the <a title="MySQL Certification forum" href="http://forums.mysql.com/list.php?6">MySQL Certification forum</a> for the latest changes. The person to note is <a title="David Stokes" href="http://dave-stokes.blogspot.com/">David Stokes</a> who is the MySQL certification manager and who posts regularly to this forum.<span id="more-83"></span></p>
<p><strong>How to study for the exam? </strong></p>
<p>There is only one book which you are going to need &#8212; and that is the &#8220;MySQL 5.0 Certification Study Guide&#8221; (Paul DuBois, Stefan Hinz, and Carsten Pedersen, ISBN 0-672-32812-7) (<a title="link" href="http://www.mysql.com/certification/studyguides/">link</a>). The book itself is split into 4 sections, as there are four different exams.</p>
<ul>
<li>MySQL Developer I &amp; II</li>
<li>MySQL Database Administrator I &amp; II</li>
</ul>
<p>Besides the book you are also going to need a laser printer and a big stack of empty sheets.</p>
<p>On the CD with the book there are four more PDF&#8217;s with Exam study guides. First study the book, then print the PDF&#8217;s and work your way through the exam preparation questions. This is not optional, the preparation guide touches on many things that are explained briefly in the book &#8212; but will catch you off guard if you don&#8217;t work through the very pointed questions.</p>
<p>The book itself is excellent, concise and to the point and after reading it I really felt that I was ready for the exam.</p>
<p><strong>How to book the exam?</strong></p>
<p>To book the exam you need to buy vouchers for the exams from your (national/local) Sun Microsystems branch. For me that was Sun Taiwan. I wrote them an e-mail in English and they quickly responded and helped me with buying the correct vouchers. Great service.</p>
<p>As I mentioned earlier &#8212; the MySQL Developer exam is split into two parts. Each part sets you back a whopping US$ 200 and you need to complete both parts to become certified.  There is some confusion about the exact price of the exams. Some of the documentation in Taiwan mentioned US$ 300 per exam, but in the end I paid the Taiwan dollar equivalent of US$ 200.</p>
<p>Now with the vouchers in hand you can book the exam through the Prometric website, the correct codes for the exams are:</p>
<p>Company: Sun Microsystems 310-Series.</p>
<ul>
<li>310-812 Dev 5.0 I</li>
<li>310-813 Dev 5.0 II</li>
</ul>
<p><strong>What to expect at the exam</strong></p>
<p>I had booked the Prometric exam at a Taiwan government institute in central Taipei. This place is setup for exams and I was not the only person taking an exam this time. I brought the required 2 sets of ID and made sure I carried as little as possible as it all had to fit into a small locker. (No need to cram anymore, right?).</p>
<p>The only gotcha was that they needed my Prometric ID number which I didn&#8217;t know and which wasn&#8217;t mentioned in the e-mail when I made the booking. A quick check of the Prometric website at a nearby computer (what WAS that password again?) helped me out there.</p>
<p>The exam itself was in exactly the same format as the Pearson Vue PHP Zend exam. Multiple choice questions on a computer screen. I needed about an hour to work through the 70 questions, giving me another 30 minutes to look again over the questions I had marked for review.</p>
<p>Press the &#8220;really, really sure&#8221; button ; en pick up your score card at the front desk. And of course realise that you have to do this one more time.</p>
<p><a href="http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/">Preparing for the MySQL Developer examinations</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/preparing-for-the-mysql-developer-examinations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Taipei Zend / PHP 5 Exam Notes</title>
		<link>http://php.dijksterhuis.org/my-taipei-zend-php-5-exam-notes/</link>
		<comments>http://php.dijksterhuis.org/my-taipei-zend-php-5-exam-notes/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 06:29:08 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[exam]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=72</guid>
		<description><![CDATA[I have been busy these last couple of weeks preparing for the Zend Certified Engineer / PHP5 exam. Although I have been using PHP for years &#8211; I never had a need to &#8220;prove&#8221; this. That might change in a few months as I start looking for a new job. Doing the Zend exam in [...]<p><a href="http://php.dijksterhuis.org/my-taipei-zend-php-5-exam-notes/">My Taipei Zend / PHP 5 Exam Notes</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="attachment_77" class="wp-caption alignnone" style="width: 510px"><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/12/taipei.jpg" alt="taipei 101 by orange tuesday @ flickr" title="taipei 101 by orange tuesday @ flickr" width="500" height="245" class="size-full wp-image-77" /><p class="wp-caption-text">taipei 101 by orange tuesday @ flickr</p></div>
<p>I have been busy these last couple of weeks preparing for the Zend Certified Engineer / PHP5 exam. Although I have been using PHP for years &#8211; I never had a need to &#8220;prove&#8221; this. That might change in a few months as I start looking for a new job. Doing the Zend exam in preparation of this sounded like a good start. My first step was to order the <a href="http://www.amazon.com/architects-Zend-Certification-Study-Guide/dp/0973862149">Zend PHP5 Certification Study Guide</a> by Davey Shafik and Ben Ramsey from Amazon.</p>
<p>The difficulty is not so much in the technologies &#8212; most things in PHP are very straightforward &#8212; but the sheer scope of what PHP covers and the potential for in dept questions. The exam covers programming basics such as converting hex / octal and decimal, XML &#038; XPath, Web programming, OOP, Databases, Pattern theory etc. The study guide covers most topics but it alone is not enough to pass the exam. It will set you on the right path &#8212; but you really need to dive deeper. <span id="more-72"></span></p>
<p>After reading the book once or twice, doing the <a href="http://shop.zend.com/en/php-certification/zend-php-certification-online-practice-testing.html">PHP | Architect Vulcan mockup exam</a> (which costs just a few US$ per try) is really a required next step. If after reading the book you are still happy in theory land &#8212; the mock exams quickly bring you back to the nitty gritty of PHP programming. Yes, its all trick questions about code, php.ini settings,  code examples (was that &#038;$var or $var?), cross site scripting and otherwise suspiciously real fake code. </p>
<p>I booked the exam for this morning and the nearest Vue Pearsons exam was at the Chunghua Telecom Corporate University (which is the training centre for Taiwans state run telecom) in Taipei.</p>
<p>This is the district that as a foreigner in Taiwan you visit every few years to extend your resident visa. Past the old visa office, the firebrigade and police station is a big Chunghua compound. The guards were a bit surprised to see me but a little Chinese goes a long way. </p>
<p>No long queues of people taking exams &#8212; the exam room was unlocked for me and I had a cup of coffee while two friendly admin ladies/supervisors setup the exam. All the forms are  in Chinese &#8212; but they managed to dig up an English version from somewhere. </p>
<p>The exam is very much like the mock exam &#8212; having done the mock exam twice I didn&#8217;t feel pressured by the ticking clock. </p>
<p>The VuePearson software is a bit slow, and not free of bugs. (Two exam questions were unreadable dumps of what looks like RTF so I had to skip them). I noted both questions to the supervisors. Expect many trick questions &#8212; and some very detailed questions about basically anything covered by PHP. </p>
<p>With plenty of time left I reviewed all questions one more time &#8212; and probably increased the number of mistakes &#8212; and then pressed the big &#8220;end of exam&#8221; button. </p>
<p>Result? Of course it was a pass &#8212; the paper I received at the end tells me this &#8212; if I failed I would be back at square one. </p>
<p>The only question I had as I left the exam centre was : what kind of grades are there? The mock exam has fail/pass and excellent. The real exam <a href="http://www.zend.com/en/services/certification/faq#faq8">only pass/fail</a>. </p>
<p>The VuePearson website lists my results as &#8220;processing&#8221; .. so I will check back later to confirm that I have been added to the list of Zend exam survivors as #12562. </p>
<p>Next up in my list of things to do are the MySQL Developer exams 1 &#038; 2&#8230; After that I might give the Zend Framework exam a try. </p>
<p><a href="http://php.dijksterhuis.org/my-taipei-zend-php-5-exam-notes/">My Taipei Zend / PHP 5 Exam Notes</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/my-taipei-zend-php-5-exam-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixing htmlentities for xml</title>
		<link>http://php.dijksterhuis.org/fixing-html_entities-for-xml/</link>
		<comments>http://php.dijksterhuis.org/fixing-html_entities-for-xml/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 09:24:23 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=61</guid>
		<description><![CDATA[I am starting to use Google Chrome more often and doing this made me notice that one of my Javascript functions wasn&#8217;t working properly. A little bit of digging revealed that Chrome did not like the XML I was feeding it. Entity '&#38;iexcl' not defined The code generating the XML was using the PHP function [...]<p><a href="http://php.dijksterhuis.org/fixing-html_entities-for-xml/">Fixing htmlentities for xml</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<p>I am starting to use Google Chrome more often and doing this made me notice that one of my Javascript functions wasn&#8217;t working properly. A little bit of digging revealed that Chrome did not like the XML I was feeding it.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Entity '&amp;iexcl' not defined</div></div>
<p>The code generating the XML was using the PHP function <em>htmlentities</em> to filter its output but this does not generate valid XML. Named entities such as  &amp;quot; and  &amp;amp; need to be represented by their Unicode values:  &amp;#34;  and &amp;#38;</p>
<p>A handy table with all the required replacements can be found at <a href="http://techtrouts.com/webkit-entity-nbsp-not-defined-convert-html-entities-to-xml/">Carlos Ouro&#8217;s website</a>.</p>
<p>Below is a simple function that replaces all the named HTML entities found in a string with their numeric HTML/XML counterparts.</p>
<p><strong>Example Usage</strong></p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Test #1<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$test</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&amp;quot; Hello World! &amp;quot;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> xmlentities<span style="color: #009900;">&#40;</span><span style="color: #000088;">$test</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> PHP_EOL<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Test #2<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$test</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span>Hello World<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> xmlentities<span style="color: #009900;">&#40;</span> <a href="http://www.php.net/htmlentities"><span style="color: #990000;">htmlentities</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$test</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> PHP_EOL<span style="color: #339933;">;</span></div></div>
<p><strong>XMLEntities function</strong></p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> xmlentities<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Convert HTML entities to XML</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// http://techtrouts.com/webkit-entity-nbsp-not-defined-convert-html-entities-to-xml/</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000088;">$htmlentities</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;&amp;quot;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;amp;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;lt;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;gt;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;nbsp;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;iexcl;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;cent;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;pound;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;curren;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;yen;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;brvbar;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;sect;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;uml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;copy;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ordf;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;laquo;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;not;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;shy;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;reg;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;macr;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;deg;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;plusmn;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;sup2;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;sup3;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;acute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;micro;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;para;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;middot;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;cedil;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;sup1;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ordm;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;raquo;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;frac14;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;frac12;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;frac34;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;iquest;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Agrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Aacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Acirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Atilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Auml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Aring;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;AElig;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ccedil;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Egrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Eacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ecirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Euml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Igrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Iacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Icirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Iuml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ETH;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ntilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ograve;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Oacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ocirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Otilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ouml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;times;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Oslash;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ugrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Uacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Ucirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Uuml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;Yacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;THORN;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;szlig;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;agrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;aacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;acirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;atilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;auml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;aring;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;aelig;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ccedil;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;egrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;eacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ecirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;euml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;igrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;iacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;icirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;iuml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;eth;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ntilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ograve;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;oacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ocirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;otilde;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ouml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;divide;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;oslash;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ugrave;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;uacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;ucirc;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;uuml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;yacute;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;thorn;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;yuml;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;euro;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$xmlentities</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&amp;#34;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#38;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#60;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#62;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#160;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#161;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#162;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#163;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#164;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#165;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#166;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#167;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#168;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#169;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#170;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#171;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#172;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#173;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#174;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#175;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#176;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#177;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#178;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#179;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#180;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#181;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#182;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#183;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#184;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#185;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#186;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#187;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#188;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#189;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#190;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#191;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#192;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#193;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#194;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#195;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#196;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#197;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#198;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#199;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#200;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#201;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#202;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#203;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#204;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#205;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#206;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#207;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#208;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#209;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#210;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#211;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#212;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#213;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#214;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#215;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#216;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#217;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#218;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#219;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#220;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#221;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#222;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#223;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#224;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#225;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#226;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#227;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#228;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#229;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#230;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#231;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#232;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#233;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#234;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#235;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#236;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#237;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#238;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#239;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#240;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#241;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#242;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#243;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#244;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#245;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#246;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#247;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#248;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#249;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#250;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#251;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#252;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#253;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#254;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#255;&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&amp;#8364;&quot;</span>&nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// HTML entities are case-sensitive (http://htmlhelp.com/reference/html40/entities/)</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$htmlentities</span><span style="color: #339933;">,</span><span style="color: #000088;">$xmlentities</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span></div></div>
<p><a href="http://php.dijksterhuis.org/fixing-html_entities-for-xml/">Fixing htmlentities for xml</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/fixing-html_entities-for-xml/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using PHP to upload E-mail to Google App Mail</title>
		<link>http://php.dijksterhuis.org/using-php-to-upload-e-mail-to-google-app-mailt/</link>
		<comments>http://php.dijksterhuis.org/using-php-to-upload-e-mail-to-google-app-mailt/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 06:15:40 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Google Apps]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=52</guid>
		<description><![CDATA[Google Apps has great benefits for small companies. There is little need to maintain your own IT infrastructure, a simple ADSL line attached to a tiny internal network is sufficient for the majority of tasks. But how do you move an existing company to Google Apps? A company I have been working with uses Thunderbird [...]<p><a href="http://php.dijksterhuis.org/using-php-to-upload-e-mail-to-google-app-mailt/">Using PHP to upload E-mail to Google App Mail</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/11/googleapps-150x150.jpg" alt="Using PHP to upload Thunderbird to Google Apps Mail " title="Using PHP to upload Thunderbird to Google Apps Mail " width="150" height="150" class="alignright size-thumbnail wp-image-57" /></p>
<p><em>Google Apps has great benefits for small companies. There is little need to maintain your own IT infrastructure, a simple ADSL line attached to a tiny internal network is sufficient for the majority of tasks. </p>
<p>But how do you move an existing company to Google Apps?<br />
</em></p>
<p>A company I have been working with uses Thunderbird for its e-mail. </p>
<p>Moving should have been straightforward as Google provides their own migration tool : the <a href="http://mail.google.com/mail/help/email_uploader.html">e-mail uploader</a>.  </p>
<p>The development of this program however appears stagnant and its bugs are not being fixed.  Strange considering how important Google Apps must be for Google. </p>
<p>For me the problem was that 40-50% of the Thunderbird e-mails in the mail store were not being uploaded because the Google Uploader complained that there was something wrong with the date format. </p>
<p><a href="http://code.google.com/p/google-email-uploader/issues/detail?id=13">The bug related to this</a> has been open for over a year.  </p>
<p>If I wanted to continue I needed to find my own solution or give up on migrating altogether. </p>
<p>A quick browse through the Zend Framework manual showed that it can read MBox files (Thunderbirds mailbox format) through the <em>Zend_Mail_Storage*</em> class and communicate with Google using the <em>Zend_Gdata*</em> classes. </p>
<p>The exercise left was to bind it all together into a working PHP script that would take my mailboxes and upload them to Google. </p>
<p>Having done this and having succesfully uploaded several multi-Gigabyte sized mailboxes I have <a href="http://code.google.com/p/googlemailappuploader/">uploaded my code (&#8216;googlemailappuploader&#8217;)</a> to Google Code. </p>
<p>If you find yourself in a similar situation &#8212; I hope you find it usefull. Leave me a comment if something is unclear. </p>
<p><a href="http://php.dijksterhuis.org/using-php-to-upload-e-mail-to-google-app-mailt/">Using PHP to upload E-mail to Google App Mail</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/using-php-to-upload-e-mail-to-google-app-mailt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Eclipse for PHP development with XDebug for remote debugging</title>
		<link>http://php.dijksterhuis.org/installing-eclipse-for-php-development-with-xdebug-for-remote-debugging/</link>
		<comments>http://php.dijksterhuis.org/installing-eclipse-for-php-development-with-xdebug-for-remote-debugging/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 02:47:36 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=21</guid>
		<description><![CDATA[This post contains my installation notes on how to setup the Eclipse PHP IDE with support for XDebug remote debugging in a mixed Windows/Ubuntu development environment. One of the great things of writing PHP code in a modern IDE is that you can step through your code, set break points and inspect variables. No more [...]<p><a href="http://php.dijksterhuis.org/installing-eclipse-for-php-development-with-xdebug-for-remote-debugging/">Installing Eclipse for PHP development with XDebug for remote debugging</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="attachment_38" class="wp-caption alignnone" style="width: 510px"><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/11/debugger1.png" alt="Time to debug by henribergius @ flickr" title="Time to debug by henribergius @ flickr" width="500" height="219" class="size-full wp-image-38" /><p class="wp-caption-text">Time to debug by henribergius @ flickr</p></div>
<p><em>This post contains my installation notes on how to setup the Eclipse PHP IDE with support for XDebug remote debugging in a mixed Windows/Ubuntu development environment.</em></p>
<p><div id="attachment_32" class="wp-caption alignright" style="width: 160px"><a href="http://php.dijksterhuis.org/wp-content/uploads/2009/11/debug.PNG"><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/11/debug-150x150.PNG" alt="Debugging PHP with XDebug in Eclipse" title="Debugging PHP with XDebug in Eclipse" width="150" height="150" class="size-thumbnail wp-image-32" /></a><p class="wp-caption-text">Debugging PHP with XDebug in Eclipse</p></div>One of the great things of writing PHP code in a modern IDE is that you can step through your code, set break points and inspect variables. No more endless print/echo statements, or including your own custom logging code every few lines.</p>
<p>The war to decide the best IDE is far from over. If you would like to write PHP code and are looking for a free IDE (Integrated Development Environment) then both <a id="bhqm" style="color: #551a8b;" title="Eclipse PHP" href="http://www.eclipse.org/downloads/">Eclipse PHP</a> and the <a id="kt_3" title="Netbeans IDE" href="http://netbeans.org/">Netbeans IDE</a> are two very strong candidates. Both are written in JAVA. For this post I concentrate on my own favorite: Eclipse. If you would like to compare several other PHP IDE&#8217;s then Davey Shafik has a great table <a id="ax58" title="comparing IDE features" href="http://daveyshafik.com/ide">comparing IDE features</a> on his site.</p>
<p>Debugging is done through a remote debugger called <a id="irm:" title="XDebug" href="http://xdebug.org/">XDebug</a>. It ties into the PHP runtime on your server allowing Eclipse to communicate with your scripts / web pages. As soon as you start debugging a web page, Eclipse will call your webserver but also pass a couple of parameters. On seeing these parameters (XDEBUG_SESSION_START/KEY), XDebug will start and connect to Eclipse over a TCP/IP connection. From here on Eclipse can control the execution of the script on the webserver.</p>
<p><strong><span style="text-decoration: underline;">My development setup</span></strong><span id="more-21"></span></p>
<p><strong> </strong></p>
<p>For writing PHP code I use two machines. Windows 7 as my main machine and a Linux server that runs the  LAMP development stack. (If you don&#8217;t have two machines available a very good alternative is to install <a id="lu_y" title="VMWare" href="http://www.vmware.com/">VMWare Player</a> and a <a id="osky" title="Ubuntu Server Virtual Appliance" href="http://chrysaor.info/?page=ubuntu">Ubuntu Server Virtual Appliance</a> on the Windows machine.) Why two machines? I guess I grew up this way. It is perfectly possible to install Eclipse for Ubuntu and do everything on a single machine.</p>
<table>
<tr>
<th>IP Address</th>
<th>Machine Function</th>
<th>Software</th>
</tr>
<tr>
<td>10.0.0.1</td>
<td>Ubuntu 8.1 Server</td>
<td>Apache 2 / PHP 5.2.6-2ubuntu4.3</td>
</tr>
<tr>
<td>10.0.0.2</td>
<td>Windows 7</td>
<td> Eclipse Galileo for PHP Developers</td>
</table>
<p>My Eclipse projects are located on the Ubuntu server through a shared path to my home directory (Z:) on the Ubuntu server.</p>
<p>I can access my work through the webserver as <em>http://development/~martijn</em> by using Apache&#8217;s <a id="z9sz" title="mod_userdir" href="http://httpd.apache.org/docs/2.2/mod/mod_userdir.html">mod_userdir</a>.</p>
<p><strong>Step #1: Download and Install SUN Java &amp; Eclipse </strong></p>
<ol style="margin-top: 0px; margin-bottom: 0px;">
<li style="margin-top: 0px; margin-bottom: 0px;">Ensure that you have <a id="mu35" title="Sun JAVA" href="http://www.java.com/en/download/index.jsp">Sun JAVA</a> installed on your Windows machine.</li>
<li style="margin-top: 0px; margin-bottom: 0px;">Download Eclipse for PHP Developers from the Eclipse download site (<a id="etrm" style="color: #551a8b;" title="http://www.eclipse.org/pdt/downloads/" href="http://www.eclipse.org/downloads/">http://www.eclipse.org/pdt/downloads/</a>)</li>
<li style="margin-top: 0px; margin-bottom: 0px;">Untar the tar.gz bundle to a directory on your machine (for example c:\eclipse)</li>
</ol>
<p><strong>Step #2: Install XDebug on the development server</strong></p>
<p>I assume that you have already installed both Apache and PHP5 on your server. If you haven&#8217;t then the following commands will make quick work of this:</p>
<blockquote><p># sudo apt-get install apache2 php5 php5-cli</p></blockquote>
<p>XDebug is installed through the <a id="z-ut" title="PHP Pear repository" href="http://pear.php.net/">PHP Pear repository</a>, but before this we need to ensure that we have both PEAR and phpize (part of php5-dev) installed.</p>
<blockquote>
<p># sudo apt-get install php-pear</p>
<p># sudo apt-get install php5-dev</p>
<p># sudo pecl install xdebug</p>
</blockquote>
<p>Now we need to discover where the xdebug.so file was installed by PEAR:</p>
<blockquote><p># find / &#8211;name xdebug.so</p></blockquote>
<p>For my Ubuntu server this was:</p>
<blockquote><p>/usr/lib/php5/20060613/xdebug.so</p></blockquote>
<p>Create a file named <em>xdebug.ini</em> in <em>/etc/php5/apache2/conf.d</em>, and modify this according to the location of your xdebug.so file:</p>
<blockquote><p>zend_extension=/usr/lib/php5/20060613/xdebug.so</p>
<p>[xdebug]<br />
xdebug.remote_enable=1<br />
xdebug.remote_handler=dbgp<br />
xdebug.remote_host=10.0.0.2</p></blockquote>
<p>The above is a very basic setup. The &#8220;xdebug.remote_host&#8221; is important: it contains the IP address of the Windows development machine. When a web page is called with a special set of parameters XDebug will launch and try to connect to your IDE. Note that the Windows firewall might block Eclipse from listening on Port 9000, if so, then make sure that this port is opened for use by Eclipse.</p>
<p>Restart Apache</p>
<blockquote><p># sudo service apache2 restart</p></blockquote>
<p>We need to test that xdebug was properly installed. Create a small <em>test.php </em>PHP script and place this in your web server root.</p>
<blockquote><p>&lt;?php phpinfo(); ?&gt;</p></blockquote>
<p>On my machine I can retrieve this file by calling:<em> http://development/~martijn/test.php</em>. If XDebug was succesfully installed you should see it listed as one of the PHP modules.</p>
<p><strong>Step #3: Setting up Eclipse for debugging code with XDebug </strong></p>
<p>Create a new PHP Project and ensure that the files are in a path that is accessible by the webserver (my Z:\ drive mapping to http://development/~martijn/). If you have done this then you are ready to debug your first PHP code. (You can of course manually copy the files back and forth, but that gets old fast if you do a lot of coding). Start Eclipse, create a new PHP Project and create a little bit of test code. Something like this:</p>
<blockquote><p>&lt;?php<br />
for ($lp = 0; $lp &lt; 10; $lp++)<br />
echo $lp;<br />
?&gt;</p></blockquote>
<p><a href="http://php.dijksterhuis.org/wp-content/uploads/2009/11/debug_setup.PNG"><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/11/debug_setup-150x150.PNG" alt="Configuring XDebug in Eclipse" title="Configuring XDebug in Eclipse" width="150" height="150" class="alignright size-thumbnail wp-image-33" /></a>Select <em>Run / Debug Configurations &#8230;</em> from the Eclipse menu. Change the Debug Server setting to &#8220;XDebug&#8221; and ensure that the <em>Default Webserver</em> points to your web directory. In the hope that a picture explains it all click on the screenshot to the right.</p>
<p>Select the line you want the code to stop at (by default it will stop at the first line) and toggle a breakpoint with CTRL-SHIFT-B. Then select Debug (F11).</p>
<p>And that should be it&#8230; have fun!</p>
<p><a href="http://php.dijksterhuis.org/installing-eclipse-for-php-development-with-xdebug-for-remote-debugging/">Installing Eclipse for PHP development with XDebug for remote debugging</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/installing-eclipse-for-php-development-with-xdebug-for-remote-debugging/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Ultimate PHP5 OOP Class</title>
		<link>http://php.dijksterhuis.org/the-ultimate-php5-oop-class/</link>
		<comments>http://php.dijksterhuis.org/the-ultimate-php5-oop-class/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 08:26:18 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[zendexam]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=15</guid>
		<description><![CDATA[After reading up on PHP5 object orientation I decided to build a little test class that implemented as many of the OOP features offered by PHP5 as I could find. Think magic functions, constants, cloning, getters and setters, abstract, final, inheritance, serialization and of course var_export support. If I missed any concepts feel free to [...]<p><a href="http://php.dijksterhuis.org/the-ultimate-php5-oop-class/">The Ultimate PHP5 OOP Class</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<p>After reading up on PHP5 object orientation I decided to build a little test class that implemented as many of the OOP features offered by PHP5 as I could find. </p>
<p>Think magic functions, constants, cloning, getters and setters, abstract, final, inheritance, serialization and of course <em>var_export</em> support. </p>
<p>If I missed any concepts feel free to drop a note. </p>
<pre class="brush: php">
&lt;?php

    /* The Ultimate PHP5 OOP Class
     *
     * Implements most of PHP5&#039;s OOP functionality in a single demonstration
     */

	/* PHP_VERSION_ID is available as of PHP 5.2.7, if our
	 * version is lower than that, then emulate it. Some of the
	 * functionality we test here is only available in 5.3.0 and
	 * higher.
	*/

	if(!defined(&#039;PHP_VERSION_ID&#039;))
	{
    	$version = explode(&#039;.&#039;,PHP_VERSION);
	    define(&#039;PHP_VERSION_ID&#039;, ($version[0] * 10000 + $version[1] * 100 + $version[2]));
	}

    /* Interfaces specify a set of functions that a class MUST
     * implement.
     */

    interface DemoInterface
    {
        public function InterfaceTest();
    }

    /* Abstract classes cannot be instantiated. They define concepts that
     * their derived classes must implement.
     */

    abstract class DemoAbstract
    {

    	/* Constructor
    	 *
    	 */

        public function __construct()
        {
            $this-&gt;LogEntry(__CLASS__,__METHOD__);
        }

        /* LogEntry
         *
         * Reports on each methods entry. Defined in the parent class so that
         * we can call it from this constructor as well.
         *
         * @param string	Methodname (from __METHOD__)
         */

        public function LogEntry($methodName)
        {
        	echo &quot;{$methodName} Called&quot; . PHP_EOL;
        }    	

        abstract public function AbstractTest();
    }

    /* The DemoPHP5Class is marked as &quot;final&quot;. Because of this selfish act
     * nobody is able to derive from this work and create their own sub class.
     */

    final class DemoPHP5Class extends DemoAbstract implements DemoInterface
    {
        /* Class Constants cannot be changed */
        const VERSION = &#039;1.0&#039;;

        /* Private members are only available inside this class */
        private $_className;
        private $_constructorName;
        private $_fileName;
        private $_instanceCount;

        /*  Location for overloaded data. */
        private $_data = array();

        /* As the class is marked final there really is not point in declaring
         * any protected (accessible by derived classes) variables but
         * for good measure we include one.
         */

        protected $_meaningOfLife;

        /* The constructor is labeled as final. Because of this derived
         * classes are unable to implement their own constructor.
         */

        final function __construct()
        {
        	parent::__construct(); 					// Calling the parent constructor

            $this-&gt;_className = __CLASS__;          // Magic constants
            $this-&gt;_constructorName = __METHOD__;
            $this-&gt;_fileName = __FILE__;
            $this-&gt;_instanceCount = 0;              // Original, not a clone
            $this-&gt;_meaningOfLife = 42;             // No need to say more

			$this-&gt;LogEntry(__CLASS__,__METHOD__);
        }

        final function __destruct()
        {
			$this-&gt;LogEntry(__METHOD__);
        }

        /* Implements the Abstract members from the DemoAbstract
         * class.
         *
         * @returns string Notification message
         */

        public function AbstractTest()
        {
			$this-&gt;LogEntry(__METHOD__);
        }

        /* Implements the DemoInteface
         *
         * @returns string Notification message
         */

        public function InterfaceTest()
        {
			$this-&gt;LogEntry(__METHOD__);
        }

        /* Static functions are not part of an instance
         * and can only be called through &quot;classname::staticmethod&quot;
         */

        public static function StaticTest($number)
        {
        	/* Note how LogEntry is NOT static, but we can still call it */
        	/* A warning is generated in STRICT mode					 */
 			parent::LogEntry(__CLASS__,__METHOD__);
        	echo &quot;StaticTest call with ({$number}) succesfull&quot; . PHP_EOL;
        }

        /* Returns the name of the class
         *
         * @returns string Name of the class as discovered by the constructor
         */

        public function GetClassName()
        {
        	$this-&gt;LogEntry(__METHOD__);
            return $this-&gt;_className;
        }

        /* Set the meaning of life
         *
         * @param   int         Meaning of life
         * @thows   Exception   On invalid input
         * @returns this        Allow for chaining of calls
         */

        public function SetMeaningOfLife($meaningOfLife)
        {
			$this-&gt;LogEntry(__METHOD__);

            if (is_int($meaningOfLife))
            {
                $this-&gt;_meaningOfLife = $meaningOfLife;
            }
            else
            {
                throw new Exception(&#039;Meaning of Life doubted&#039;);
            }
            return $this;
        }

        /* Returns the meaning of life
         *
         * @returns int      Meaning of life as a core value
         */

        public function GetMeaningOfLife()
        {
			$this-&gt;LogEntry(__METHOD__);
            return $this-&gt;_meaningOfLife;
        }

        /* Returns the instance count
         *
         * @returns int 	Instance count
         */

        public function GetInstanceCount()
        {
        	return $this-&gt;_instanceCount;
        }

        /* Magic Methods
         *
         * These methods have special meaning inside of PHP5.
         */

        /* Return a string description of the class
         *
         * @returns string  Whatever the class fancies. Usually a description
         */

        public function __toString()
        {
			$this-&gt;LogEntry(__METHOD__);
            return &#039;__toString called ; the meaning of life is our domain&#039; . PHP_EOL;
        }

        /* From PHP 5.3.0 its possible to &quot;invoke&quot; a class, using it like
         * a function. Eg. &#039;DemoPHP5Class(50)&#039;.
         */

        public function __invoke($x)
        {
			$this-&gt;LogEntry(__METHOD__);
            echo &quot;__invoke was called with {$x}&quot; . PHP_EOL;
        }

        /* PHP 5 allows the simulation of properties. If a property does not
         * exist when attempting to write the __set method is called giving
         * you an opportunity to handle the variable yourself.
         */

        /* Called when a not-class defined property is set by the user. For
         * example &quot;DemoPHP5Class-&gt;FooBar = 500&quot;. We add an entry to the
         * $this-&gt;_data table.
         *
         * @param   string      A valid name
         * @param   undefined   Any valid PHP value
         * @throws  Exception   Only strings are considered valid names
         */

        public function __set($name,$value)
        {
			$this-&gt;LogEntry(__METHOD__);
            if (is_string($name)) {
             $this-&gt;_data[$name] = $value;
             return;
            }
            throw new Exception(&#039;Invalid Property name&#039;);
        }

        /* Called when a not class defined property is retrieved. We
         * attempt to satisfy the called by checking $this-&gt;_array.
         *
         * @param    string    A valid name
         * @throws   Exception When the property is not defined
         * @returns  undefined Value of the named property
         */

        public function __get($name)
        {
			$this-&gt;LogEntry(__METHOD__);
        	if (is_string($name) &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; array_key_exists($name, $this-&gt;_data))
                return $this-&gt;_data[$name];
            throw new Exception(&quot;Attempted to read undefined proporty&quot;);
        }

        /* This method is called whenever we try to access an inaccessible
         * property. We check $this-&gt;_data to see if a matching key exists.
         *
         * @param   string   A valid string property name
         * @returns bool     True on finding the property in the array
         */

        public function __isset($name)
        {
			$this-&gt;LogEntry(__METHOD__);
        	if (is_string($name) &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; array_key_exists($name, $this-&gt;_data))
                return true;
        }

        /* This method is called when unset is called on an inaccessible
         * class property. We check $this-&gt;_data and try to unset it.
         *
         * @param   string      A valid string property name
         * @throws  Exception   The property must exist, mmmm, ok?
         */

        public function __unset($name)
        {
		   $this-&gt;LogEntry(__METHOD__);
           if (is_string($name) &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; array_key_exists($name, $this-&gt;_data))
            unset($this-&gt;_data[$name]);
           else
            throw new Exception(&quot;Unsetting non-existant property&quot;);
        }

        /* When a class is serialized (eg. put away into cold storage)
         * it is checked for a __sleep method. If it exists it is called
         * to allow the class to prepare a list with names of its most important
         * variables for safe storage.
         *
         * @returns array Critical variables that need to be stored
         */

        public function __sleep()
        {
			$this-&gt;LogEntry(__METHOD__);
            return array(&quot;_meaningOfLife&quot;,&quot;_className&quot;,&quot;_constructorName&quot;,
                         &quot;_fileName&quot;,&quot;_data&quot;);
        }

        /* On deserialization the class needs to re-initialise.
         * This is a good point to re-establish the database connection and
         * any other critical (but not storable) resources.
         */

        public function __wakeup()
        {
			$this-&gt;LogEntry(__METHOD__);
        }

        /* When an object is &quot;cloned&quot; an exact copy is created. This is not
         * always desirable (think resource handles that are now shared by two
         * objects). The __clone magic function is called on the COPY and
         * allows it to initialise any variables it sees fit.
         */

        public function __clone()
        {
			$this-&gt;LogEntry(__METHOD__);
        	// Clones know they are copies because only the original
            // object has an _instanceCount value of 0.
            $this-&gt;_instanceCount++;
        }

        /* Used by var_export which allows the creation of a PHP evaluable
         * string that would re-create this object.
         *
         * See also: http://www.thoughtlabs.com/2008/02/02/phps-mystical-__set_state-method/
         */

        public static function __set_state($an_array)
        {
        	echo &quot;static::__set_state called&quot; . PHP_EOL;			

			// Create a new class, set its parameters and
			// exit. 

			$tmp = new DemoPHP5Class();
			foreach($an_array as $name =&gt; $value)
			 $tmp-&gt;$name = $value;

			return $tmp;
        }

    }

    /* Enable strict warnings */
    error_reporting(E_ALL | E_STRICT);

    /* Test Code */
    $demo = new DemoPHP5Class();

    /* Example of a class constant */
    echo &quot;Class version: &quot; . DemoPHP5Class::VERSION . PHP_EOL;  

    /* Test #1:  Abstract method in parent class, simply call it*/
	$demo-&gt;AbstractTest();

	/* Test #2:  Call the Interface member */
	$demo-&gt;InterfaceTest();

	/* Test #3:  Call of a static member */
	DemoPHP5Class::StaticTest(20);

	/* Test #4:  Call a regular get method  */
	$demo-&gt;GetClassName();

	/* Test #5:  Call a regular set method with valid param */
	$demo-&gt;SetMeaningOfLife(43);

	/* Test #6:  Call a regular set method with INVALID param */
	try {
		$demo-&gt;SetMeaningOfLife(42.5);
	}
	catch (Exception $e) {
		echo &quot;Exception Caught OK&quot; . PHP_EOL;
	}

	/* Test #7: Try to print the object , calling __tostring() */
	echo $demo;

	/* Test #8: Invoke the object , bit like magic really */
	/* 			only available from PHP 5.3.0 up	      */
	if (PHP_VERSION_ID &gt; 50300)
	 $demo(&#039;abacradaba&#039;);

	/* Test #9: Set an non-existant member of the object, causing
	 * a call to __set, which will emulate/store the value
	 */		 

	$demo-&gt;non_existing_member = 256;

	/* Test #10: Confirm that the new member has been set */

	if (isset($demo-&gt;non_existing_member))
	 echo &#039;Confirmed existance of \$demo-&gt;non_existing_member&#039; . PHP_EOL;
	else
	 echo &#039;Failed to verify setting of \$demo-&gt;non_existing_member&#039; . PHP_EOL;

	/* Test #11: Retrieve the non-existing member, causing a call
	 * to __get, which will attempt to retrieve it from the internal
	 * storage array.
	 */

	if ($demo-&gt;non_existing_member == 256)
		echo &quot;Retrieval of \$demo-&gt;non_existing_member succesfull&quot; . PHP_EOL;
	else
		echo &quot;Retrieval of \$demo-&gt;non_existing_member FAILED&quot; . PHP_EOL;

	/* Test #12: Remove the member, and test if this was succesfull */

	unset($demo-&gt;non_existing_member);
	if (!isset($demo-&gt;non_existing_member))
	 	echo &#039;Confirmed removal of \$demo-&gt;non_existing_member&#039; . PHP_EOL;
	else
	 	echo &#039;Failed to remove \$demo-&gt;non_existing_member&#039; . PHP_EOL;

	/* Test #13: Serialization , put the object to sleep and turn it
	 * into a form that we can store away savely.
	 */

	$serialized_data = serialize( $demo );
	$demo2 = unserialize($serialized_data);  

	/* Test #14: Cloning. After cloning the object the clone should
	 * have a higher instance value than the original object because
	 * of the additional changes made by __clone
	 */

	$demo3 = clone $demo;
	if ($demo3-&gt;GetInstanceCount() &gt; $demo-&gt;GetInstanceCount())
	 	echo &quot;Succesfull cloning; instance count has been increased. &quot; . PHP_EOL;
	else
	 	echo &quot;Failed to clone; instance count is the same. &quot; . PHP_EOL;

	/* Test 15: Var_Export must produce valid PHP code that can be
	 * run through &#039;eval&#039;. It has trouble with objects , so it needs
	 * a little help from the __set_state magic function
	 */

	eval(&#039;$demo4 = &#039; . var_export($demo, true) . &#039;;&#039;);

	/* Remember, we modified the meaning of life to 43 in $demo */
	if ($demo4-&gt;GetMeaningOfLife()==$demo-&gt;GetMeaningOfLife())
	 echo &quot;Succesfull re-creation of the \$demo class&quot; . PHP_EOL;
	else
	 echo &quot;Failed to recreate. The meaning of life was lost. &quot; . PHP_EOL; 

	/* EOF */

?&gt;
</pre>
<p><a href="http://php.dijksterhuis.org/the-ultimate-php5-oop-class/">The Ultimate PHP5 OOP Class</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/the-ultimate-php5-oop-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP5 : SimpleXML Study Notes</title>
		<link>http://php.dijksterhuis.org/php5-simplexml-study-notes/</link>
		<comments>http://php.dijksterhuis.org/php5-simplexml-study-notes/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 04:58:10 +0000</pubDate>
		<dc:creator>martijn</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[simplexml]]></category>
		<category><![CDATA[zendexam]]></category>

		<guid isPermaLink="false">http://php.dijksterhuis.org/?p=3</guid>
		<description><![CDATA[Below are some of the notes I made while preparing for the Zend PHP5 exam. They are a quick memory jog of how SimpleXML works and its limitations. The SimpleXML extension provides easier access to XML files. It is simpler to use but also much more limited than the DOM XML extension. If your document [...]<p><a href="http://php.dijksterhuis.org/php5-simplexml-study-notes/">PHP5 : SimpleXML Study Notes</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></description>
			<content:encoded><![CDATA[<div id="attachment_48" class="wp-caption alignright" style="width: 510px"><img src="http://php.dijksterhuis.org/wp-content/uploads/2009/11/xml2.jpg" alt="XML Summer School by psd @ flickr" title="XML Summer School by psd @ flickr" width="500" height="326" class="size-full wp-image-48" /><p class="wp-caption-text">XML Summer School by psd @ flickr</p></div>
<p><em>Below are some of the notes I made while preparing for the Zend PHP5 exam. They are a quick memory jog of how SimpleXML works and its limitations.</em></p>
<p>The SimpleXML extension provides easier access to XML files. It is simpler to use but also much more limited than the DOM XML extension. If your document makes use of XML namespaces (ns:foo) then it is better NOT to use SimpleXML as it will become <a href="http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html">anything but simple</a>.</p>
<p>SimpleXML only supports XML 1.0. If fed an XML 1.1 document it will show &#8220;Unsupported version &#8217;1.1&#8242;&#8221; warnings, but will continue and attempt to read the file.</p>
<p>Removing elements is not really supported and the opportunities for modification are limited. SimpleXML is best used for straightforward reading and using of XML files.<span id="more-3"></span></p>
<h2>1. Documentation</h2>
<p><a href="http://php.net/manual/en/book.simplexml.php">http://php.net/manual/en/book.simplexml.php</a></p>
<h2>2. Demo XML file</h2>
<p>This example XML catalog.xml file <a href="http://msdn.microsoft.com/en-us/library/ms762271%28VS.85%29.aspx">looks really familiar</a>.</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;catalog&gt;
    &lt;book id=&quot;bk101&quot;&gt;
        &lt;author&gt;Gambardella, Matthew&lt;/author&gt;
        &lt;title&gt;XML Developer&#039;s Guide&lt;/title&gt;
        &lt;genre&gt;Computer&lt;/genre&gt;
        &lt;price&gt;44.95&lt;/price&gt;
        &lt;publish_date&gt;2000-10-01&lt;/publish_date&gt;
        &lt;description&gt;An in-depth look at creating applications with XML.&lt;/description&gt;
    &lt;/book&gt;
    &lt;book id=&quot;bk102&quot;&gt;
        &lt;author&gt;Ralls, Kim&lt;/author&gt;
        &lt;title&gt;Midnight Rain&lt;/title&gt;
        &lt;genre&gt;Fantasy&lt;/genre&gt;
        &lt;price&gt;5.95&lt;/price&gt;
        &lt;publish_date&gt;2000-12-16&lt;/publish_date&gt;
        &lt;description&gt;A former architect battles corporate zombies,
         an evil sorceress, and her own childhood to become queen
         of the world.&lt;/description&gt;
    &lt;/book&gt;
&lt;/catalog&gt;
</pre>
<h2>3. Loading an XML file</h2>
<p>There are four approaches to loading an XML file using SimpleXML.</p>
<h3>3.1 Loading from a string</h3>
<pre class="brush: php">
&lt;?php
    $xml = file_get_contents(&quot;catalog.xml&quot;);
    $simple_xml_obj = simplexml_load_string($xml);
    if ($simple_xml_obj !== FALSE) {
        var_dump($simple_xml_obj);
    } else {
        echo &quot;Invalid XML file&quot; . PHP_EOL;
    }
?&gt;
</pre>
<p>3.2 Loading the XML file directly</p>
<pre class="brush: xml">
&lt;?php
    $simple_xml_obj = simplexml_load_file(&quot;catalog.xml&quot;);
    if ($simple_xml_obj !== FALSE) {
        var_dump($simple_xml_obj);
    } else {
        echo &quot;Invalid XML file&quot; . PHP_EOL;
    }
?&gt;
</pre>
<h3>3.3 Loading from a string using the SimpleXML constructor</h3>
<p>If creating an SimpleXML instance from a string we need to be wary of possible exceptions.</p>
<pre class="brush: xml">
&lt;?php
    $xml = file_get_contents(&quot;catalog.xml&quot;);
    try {
        $simple_xml_obj = new SimpleXMLElement($xml);
        var_dump($simple_xml_obj);
    }
    catch (Exception $e)  {
        echo &quot;Oops: &quot; . $e-&gt;getMessage() . PHP_EOL;
    }
?&gt;
</pre>
<h3>3.4 Loading the XML file directly with the class constructor</h3>
<p>By setting the third parameter of the constructor (data_is_url) to true we can ask the class to directly load the XML file.</p>
<pre class="brush: xml">
&lt;?php
    $filename = &quot;catalog.xml&quot;;
    try
    {
        $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
        var_dump($simple_xml_obj);
    }
    catch (Exception $e)
    {
        echo &quot;Oops: &quot; . $e-&gt;getMessage() . PHP_EOL;
    }
?&gt;
</pre>
<h2>4. Usage examples</h2>
<p>The benefit of SimpleXML over other solutions is that it makes accessing elements of the XML file EASY.</p>
<h3>4.1 Stepping through the XML file by name</h3>
<p>If you are familiar with the XML file and know the names of the elements you can refer directly to them in your code:</p>
<pre class="brush: xml">
&lt;?php
    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    foreach($simple_xml_obj-&gt;book as $book)
    {
        // Access attributes through a named array
        echo &quot;Book ID: {$book[&#039;id&#039;]}&quot; . PHP_EOL;

        // Access sub elements using -&gt;
        echo &quot;Book Author: {$book-&gt;author}&quot; . PHP_EOL;
        echo &quot;Book Title: {$book-&gt;title}&quot; . PHP_EOL;
        echo &quot;Book Genre: {$book-&gt;genre}&quot; . PHP_EOL;
        echo &quot;Book Price: {$book-&gt;price}&quot; . PHP_EOL;
        echo &quot;Book Published date: {$book-&gt;publish_date}&quot; . PHP_EOL;
        echo &quot;Book Description: {$book-&gt;description}&quot; . PHP_EOL;
    }
?&gt;
</pre>
<h3>4.2 Discovering the contents of the XML file</h3>
<p>The children() method will returns an itterator of SimpleXMLElement elements containing each of the children. If used from the top node, this will allow you to step through the entire XML file. The attributes() method returns an iterator of key, value pairs containing all the attributes of the current XML tag.</p>
<pre class="brush: xml">
&lt;?php

    /* Discover the contents of an XML file recursivly
     *
     * @param    $input     A SimpleXMLElement to discover
     * @param    $depth     (optional) recursive dept, used for spacing
     * @returns
     */

    function DiscoverXML($xml,$depth = 0)
    {
        $spacing = str_repeat(&#039; &#039;,$depth);

        // Show the name of the current node
        echo $spacing . &#039;&lt;&#039; . $xml-&gt;getName() . &#039;&gt;&#039; ;

        // Show the value of the current node, do this by casting the
        // current element to a string.
        echo trim((string) $xml);

        // Show the attributes of the current node
        foreach($xml-&gt;attributes() as $name =&gt; $value)
            echo $spacing . &quot; Atrribute {$name} = {$value}&quot; . PHP_EOL;

        // Go deeper and discover any child nodes
        foreach($xml-&gt;children() as $child)
         DiscoverXML($child,$depth+1);

        // Close the current tag
        echo $spacing . &#039;&lt;/&#039; . $xml-&gt;getName() . &#039;&gt;&#039; . PHP_EOL;
    }

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    DiscoverXML($simple_xml_obj);
?&gt;
</pre>
<h3>4.3 Changing elements</h3>
<p>Existing elements can be simply modified by assigning them a new value.</p>
<pre class="brush: xml">
&lt;?php

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    $simple_xml_obj-&gt;book[0]-&gt;title = &quot;Hello World&quot;;
    $simple_xml_obj-&gt;book[1]-&gt;title = &quot;Vampire Mania&quot;;

    var_dump($simple_xml_obj);
?&gt;
</pre>
<h3>4.4 Adding a new element</h3>
<pre class="brush: xml">
&lt;?php

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    $book = $simple_xml_obj-&gt;addChild(&#039;book&#039;);

    $book-&gt;addAttribute(&#039;id&#039;,&#039;1234&#039;);
    $book-&gt;addChild(&#039;author&#039;,&#039;Vars Unlimited&#039;);
    $book-&gt;addChild(&#039;title&#039;,&#039;PHP through the ages&#039;);
    $book-&gt;addChild(&#039;genre&#039;,&#039;historical&#039;);
    $book-&gt;addChild(&#039;price&#039;,&#039;10.95&#039;);
    $book-&gt;addChild(&#039;publish date&#039;,&#039;2010-1-1&#039;);
    $book-&gt;addChild(&#039;description&#039;,&#039;One of the finest examples of rewriting history&#039;);

    var_dump($simple_xml_obj);
?&gt;
</pre>
<h3>4.5 Using XPath</h3>
<p>XPath, the XML Path Language, is a query language for selecting nodes from an XML document. In the code below we locate all the prices. Note the &#8216;element/sub element/sub sub element&#8217; notation.</p>
<pre class="brush: xml">
&lt;?php

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    $search_result = $simple_xml_obj-&gt;xpath(&#039;/catalog/book/price&#039;);

    foreach($search_result as $price)
        echo $price . PHP_EOL;

?&gt;
</pre>
<p>XPath is a query language &#8212; it allows you to select nodes based on criteria. For example, to only pick the books more expensive than $6 :</p>
<pre class="brush: xml">
&lt;?php

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    $search_result = $simple_xml_obj-&gt;xpath(&#039;/catalog/book[price&gt;6]/price&#039;);

    foreach($search_result as $price)
        echo $price . PHP_EOL;

?&gt;
</pre>
<h3>4.6 Exporting XML</h3>
<p>To export the in memory contents of a SimpleXMLElement we can use the &#8216;asXML&#8217; method:</p>
<pre class="brush: xml">
&lt;?php
    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);
    echo $simple_xml_obj-&gt;asXML();
?&gt;
</pre>
<p>It is also possible to write the XML to disk by passing a file name:</p>
<pre class="brush: xml">
&lt;?php

    $filename = &quot;catalog.xml&quot;;
    $simple_xml_obj = new SimpleXMLElement($filename,NULL,true);

    if (!$simple_xml_obj-&gt;asXML(&#039;/tmp/out.xml&#039;))
        echo &quot;Unable to save the XML file!&quot; . PHP_EOL;

?&gt;
</pre>
<p><a href="http://php.dijksterhuis.org/php5-simplexml-study-notes/">PHP5 : SimpleXML Study Notes</a> is a post from: <a href="http://php.dijksterhuis.org">Martijn&#039;s PHP Coding Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://php.dijksterhuis.org/php5-simplexml-study-notes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
