<?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-1893324312984055455</id><updated>2011-12-31T11:32:17.907Z</updated><category term='solr'/><category term='php 5.3'/><category term='php build script'/><category term='query string'/><category term='design patterns'/><category term='upgrading ports'/><category term='php 5.3 hosting'/><category term='debugging'/><category term='get_called_class'/><category term='DateTimeZone'/><category term='php standards group'/><category term='singleton'/><category term='strategy'/><category term='migration'/><category term='lucene'/><category term='compiling php iconv'/><category term='conversion'/><category term='upgrading macports'/><category term='hosting'/><category term='doctrine_task'/><category term='date'/><category term='doctrine_cli'/><category term='service'/><category term='installing ports'/><category term='PHP 5'/><category term='strategy pattern'/><category term='php compile script'/><category term='PHP'/><category term='problem solving'/><category term='design pattern'/><category term='Doctrine'/><category term='timezone'/><category term='Doctrine 1.2'/><category term='DateTime'/><category term='namespaces'/><category term='os service'/><category term='search'/><category term='unit testing'/><category term='dreamhost'/><category term='installing macports'/><category term='compiling php'/><category term='macports'/><title type='text'>Dan Bettles</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dan</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><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-7756946902176315502</id><published>2009-12-29T07:22:00.007Z</published><updated>2010-07-28T07:39:35.799+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compiling php iconv'/><title type='text'>PHP 5.3 Compile Error: Undefined Symbols in iconv</title><content type='html'>&lt;span style="font-size:130%;"&gt;Problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I tried to exactly replicate my production environment on my MacBook recently, compilation failed with the following message.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Undefined symbols:&lt;br /&gt;"_iconv_close", referenced from:&lt;br /&gt;_do_convert in gdkanji.o&lt;br /&gt;_php_iconv_string in iconv.o&lt;br /&gt;_php_iconv_string in iconv.o&lt;br /&gt;__php_iconv_strlen in iconv.o&lt;br /&gt;__php_iconv_strpos in iconv.o&lt;br /&gt;__php_iconv_mime_decode in iconv.o&lt;br /&gt;__php_iconv_mime_decode in iconv.o&lt;br /&gt;__php_iconv_mime_decode in iconv.o&lt;br /&gt;_zif_iconv_substr in iconv.o&lt;br /&gt;_zif_iconv_substr in iconv.o&lt;br /&gt;_php_iconv_stream_filter_dtor in iconv.o&lt;br /&gt;_zif_iconv_mime_encode in iconv.o&lt;br /&gt;_zif_iconv_mime_encode in iconv.o&lt;br /&gt;"_iconv", referenced from:&lt;br /&gt;_do_convert in gdkanji.o&lt;br /&gt;"_iconv_open", referenced from:&lt;br /&gt;_do_convert in gdkanji.o&lt;br /&gt;_php_iconv_string in iconv.o&lt;br /&gt;__php_iconv_strlen in iconv.o&lt;br /&gt;__php_iconv_strpos in iconv.o&lt;br /&gt;__php_iconv_mime_decode in iconv.o&lt;br /&gt;__php_iconv_mime_decode in iconv.o&lt;br /&gt;_zif_iconv_substr in iconv.o&lt;br /&gt;_zif_iconv_substr in iconv.o&lt;br /&gt;_zif_iconv_mime_encode in iconv.o&lt;br /&gt;_zif_iconv_mime_encode in iconv.o&lt;br /&gt;_php_iconv_stream_filter_factory_create in iconv.o&lt;br /&gt;ld: symbol(s) not found&lt;br /&gt;collect2: ld returned 1 exit status&lt;br /&gt;make: *** [sapi/cgi/php-cgi] Error 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add "--with-iconv=&amp;lt;iconv base dir&amp;gt;" to your configure line, replacing &amp;lt;iconv base dir&amp;gt; with the path of the root of the install location of iconv on your system (e.g. "/opt/local").&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-7756946902176315502?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/7756946902176315502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=7756946902176315502' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7756946902176315502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7756946902176315502'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/12/php-53-compile-error-undefined-symbols.html' title='PHP 5.3 Compile Error: Undefined Symbols in iconv'/><author><name>Dan</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-266358229045976976</id><published>2009-12-06T12:07:00.006Z</published><updated>2010-04-06T18:09:02.624+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macports'/><category scheme='http://www.blogger.com/atom/ns#' term='installing macports'/><category scheme='http://www.blogger.com/atom/ns#' term='installing ports'/><category scheme='http://www.blogger.com/atom/ns#' term='upgrading ports'/><category scheme='http://www.blogger.com/atom/ns#' term='upgrading macports'/><title type='text'>Cleaning-Up After MacPorts</title><content type='html'>&lt;span style="font-size:130%;"&gt;Preamble&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm a bit short on time at the moment, so over the next couple of weeks I'll be making some very brief posts.  They'll mostly be just notes I've made at one time or another, but they should still be useful in some way.  On with the show then...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;MacPorts is brilliant, but left to its own devices, it behaves like a lazy teenager; not tidying-up its room and leaving dirty washing lying around your hard-drive.&lt;br /&gt;&lt;br /&gt;The problem is that downloads and build-files tend to linger, and old versions of packages are not automatically removed after being upgraded.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Cleaning-Up The Mess&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Execute the following (self-explanatory) commands to clean-up MacPorts at any time.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo port -f clean --all installed&lt;br /&gt;sudo port -f uninstall inactive&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I freed-up over a gig the first time I ran these commands!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Laying Down The Law&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To upgrade your installed Ports - including dependencies - &lt;span style="font-style: italic;"&gt;and remove the outdated versions&lt;/span&gt;, all at the same time, execute the following commands.  (For a complete solution, I've included the command to update MacPorts itself.)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo port selfupdate&lt;br /&gt;sudo port -fuc upgrade outdated&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;-f&lt;/code&gt; = force upgrade&lt;br /&gt;&lt;code&gt;-u&lt;/code&gt; = uninstall inactive ports when upgrading and uninstalling&lt;br /&gt;&lt;code&gt;-c&lt;/code&gt; = auto-clean after install&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-266358229045976976?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/266358229045976976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=266358229045976976' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/266358229045976976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/266358229045976976'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/12/cleaning-up-after-macports.html' title='Cleaning-Up After MacPorts'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-7233107661228508600</id><published>2009-11-21T17:52:00.003Z</published><updated>2009-12-07T19:18:42.364Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='compiling php'/><title type='text'>PHP 5.3 Compile Error: Undefined References in dns.c</title><content type='html'>&lt;span style="font-size:130%;"&gt;Problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Compilation fails with an error like the following.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;ext/standard/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;dns&lt;/span&gt;.o: In function `&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;php&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;parserr&lt;/span&gt;':&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:418: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:468: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:652: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:674: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:513: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;ext/standard/dns.o:/home/danbettles/build/php-5.3.1/ext/standard/dns.c:519: more undefined references to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;dn&lt;/span&gt;_expand' follow&lt;br /&gt;ext/standard/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;dns&lt;/span&gt;.o: In function `&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;zif&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;dns&lt;/span&gt;_check_record':&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:393: undefined reference to `__res_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;nsearch&lt;/span&gt;'&lt;br /&gt;ext/standard/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;dns&lt;/span&gt;.o: In function `&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;zif&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;dns&lt;/span&gt;_get_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;mx&lt;/span&gt;':&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:933: undefined reference to `__res_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;nsearch&lt;/span&gt;'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:944: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;dn&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;skipname&lt;/span&gt;'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:951: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;dn&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;skipname&lt;/span&gt;'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:964: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;dn&lt;/span&gt;_expand'&lt;br /&gt;ext/standard/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;dns&lt;/span&gt;.o: In function `&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;zif&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;dns&lt;/span&gt;_get_record':&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:810: undefined reference to `__res_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;nsearch&lt;/span&gt;'&lt;br /&gt;/home/danbettles/build/php-5.3.1/ext/standard/dns.c:833: undefined reference to `__&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;dn&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;skipname&lt;/span&gt;'&lt;br /&gt;collect2: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;ld&lt;/span&gt; returned 1 exit status&lt;br /&gt;make: *** [&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;sapi&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;cgi&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;php&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;cgi&lt;/span&gt;] Error 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Execute the following command before running configure.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;export EXTRA_LIBS="-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;lresolv&lt;/span&gt;"&lt;/pre&gt;&lt;br /&gt;That fixed the problem on Debian.  Hopefully it'll do the trick for you, too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-7233107661228508600?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/7233107661228508600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=7233107661228508600' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7233107661228508600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7233107661228508600'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/11/php-53-compile-error-undefined.html' title='PHP 5.3 Compile Error: Undefined References in dns.c'/><author><name>Dan</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-4662037097229070464</id><published>2009-11-18T08:02:00.020Z</published><updated>2009-12-07T19:19:58.545Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3 hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='dreamhost'/><category scheme='http://www.blogger.com/atom/ns#' term='php build script'/><category scheme='http://www.blogger.com/atom/ns#' term='hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='compiling php'/><category scheme='http://www.blogger.com/atom/ns#' term='php compile script'/><title type='text'>Dreamhost's Shared Hosting Offers PHP 5.3</title><content type='html'>&lt;span style="font-weight: bold;"&gt;UPDATE: My &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://wiki.dreamhost.com/Installing_PHP5#Improved_script_for_a_minimal_PHP_5.3.x_install_with_mysqlnd_and_APC"&gt;improved script for a minimal PHP 5.3.x install with mysqlnd and APC&lt;/a&gt;&lt;span style="font-weight: bold;"&gt; is now available on Dreamhost's wiki.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Sort Of&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With shell access to the server, you're free to compile your own copy of PHP.  Then, with a couple of lines in an .htaccess file under your site's root, you can be up and running with the latest - and greatest - version of PHP.&lt;br /&gt;&lt;br /&gt;The only caveat: Dreamhost will not provide technical support if you go down this route.  (That's unlikely to concern you, however, if you're willing to build your own copy of PHP.)&lt;br /&gt;&lt;br /&gt;Whilst this may not be the most optimal arrangement, it's great if you can't afford - or don't really &lt;span style="font-style: italic;"&gt;need&lt;/span&gt; - a VPS, and just want something to tide you over until other hosts adopt PHP 5.3 - and there's choice in the marketplace.&lt;br /&gt;&lt;br /&gt;It's been only a few days since I started setting-up my web space, so I'm not in any position to comment on performance and the like.  For what Dreamhost are charging, though, I reckon you'd be hard-pressed to complain.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Compiling PHP 5.3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are &lt;a href="http://wiki.dreamhost.com/Installing_PHP5#PHP_5.3"&gt;basic instructions and an install script for PHP 5.3&lt;/a&gt; on Dreamhost's wiki.&lt;br /&gt;&lt;br /&gt;In the interests of saving time, I started-out using their script.  PHP failed to build on the first run-through, however, so I've just started stripping-down the script and altering it for my own purposes.  When I'm done, I'll post the script and instructions on the wiki for reference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-4662037097229070464?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/4662037097229070464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=4662037097229070464' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/4662037097229070464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/4662037097229070464'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/11/dreamhosts-shared-hosting-offers-php-53.html' title='Dreamhost&apos;s Shared Hosting Offers PHP 5.3'/><author><name>Dan</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-3457520724445739155</id><published>2009-11-07T09:50:00.006Z</published><updated>2009-11-11T18:43:46.357Z</updated><title type='text'>Doctrine API Documentation Search Plugin for Firefox</title><content type='html'>I eventually got fed-up of having to navigate over to the Doctrine site every time I wanted to view a class' documentation, so I created a very simple Firefox search plugin to make things easier.&lt;br /&gt;&lt;br /&gt;The Doctrine API documentation doesn't have a proper search so the plugin simply takes advantage of their URL naming conventions.  The plugin is fundamentally limited, therefore, allowing you to search only by class name, but that's as much as I need.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/45316"&gt;download it from the Firefox Add-ons site&lt;/a&gt;, or, if you navigate over to &lt;a href="http://www.doctrine-project.org/"&gt;www.doctrine-project.org&lt;/a&gt;, your Firefox search box should light-up and a download link appear at the bottom of the drop-down.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-3457520724445739155?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/3457520724445739155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=3457520724445739155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3457520724445739155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3457520724445739155'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/11/doctrine-api-documentation-search.html' title='Doctrine API Documentation Search Plugin for Firefox'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-8003634478269287748</id><published>2009-11-03T13:30:00.018Z</published><updated>2009-11-07T09:48:19.857Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP 5'/><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine 1.2'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine'/><category scheme='http://www.blogger.com/atom/ns#' term='doctrine_task'/><category scheme='http://www.blogger.com/atom/ns#' term='doctrine_cli'/><title type='text'>New Features in Doctrine 1.2, Part 2: Custom Tasks, and CLI Options and Refactorings</title><content type='html'>I made two key changes to Doctrine_Cli, but in doing so also made the class a great deal more customisable.  It's because I had problems customising the class before that I was more or less forced into submitting a patch.&lt;br /&gt;&lt;br /&gt;You can now:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create and use custom Tasks without having to follow any special naming conventions, which means you can easily use namespaced custom Tasks (PHP 5.3).&lt;/li&gt;&lt;li&gt;Set Task names manually - and independently from their class names.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Force the CLI to rethrow exceptions on error, which is useful - neh, &lt;span style="font-style: italic;"&gt;vital &lt;/span&gt;- if, like me, you're using the CLI and Tasks to create install scripts.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Creating and Using Custom Tasks&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Doctrine_Cli now automatically registers &lt;span style="font-style: italic;"&gt;all&lt;/span&gt; loaded Tasks (i.e. all Tasks extending Doctrine_Task).  All you have to do to ensure that your Task appears in the list, then, is to include your Tasks before creating an instance of Doctrine_Cli - which will most likely be the case anyway.  (Should you need to load Tasks afterwards, however, you can call Doctrine_Cli::registerIncludedTaskClasses() to add them all to the CLI, or you can use Doctrine_Cli::registerTaskClass() to register individual Tasks.)&lt;br /&gt;&lt;br /&gt;The following code includes and registers Doctrine core Tasks, and then registers loaded custom Tasks.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;$cli &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Cli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$cli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;run&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$_SERVER&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'argv'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The following code includes and registers only Doctrine core Tasks.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;$oCli &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Cli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'autoregister_custom_tasks' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oCli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;run&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$_SERVER&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'argv'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The following code includes and registers Doctrine core Tasks and loaded custom Tasks, and then registers a custom Task loaded after the CLI was instantiated.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;$oCli &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Cli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;require_once(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;dirname&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;_FILE_&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) . &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'/TestTask02.php'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;//Either...:&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oCli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;registerTaskClass&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'Doctrine_Cli_TestCase_TestTask02'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;//...Or:&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oCli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;registerIncludedTaskClasses&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oCli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;run&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$_SERVER&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'argv'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;Custom Task Names&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you're using namespaced Tasks, or Tasks with long names, you'll probably want to override the default, automatically assigned, Task names.  Not only does this make invoking Tasks easier, but it also gives you the opportunity to organise your Tasks in the CLI, to differentiate them from the core Tasks.&lt;br /&gt;&lt;br /&gt;Doctrine_Task will still automatically derive Task names at runtime, but you can now override this behaviour, specifying your own at design-time.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;namespace &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;fully&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;qualified&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;CustomTaskName &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends \&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Task &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;//This task would otherwise be automatically registered as&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    //"fully-qualified-custom-task-name"&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$taskName &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'custom-task-name'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;execute &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {}&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Rethrowing Exceptions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've been using the CLI and Tasks to create install scripts, which means running two or more Tasks, in sequence, in a single script.&lt;br /&gt;&lt;br /&gt;While this doesn't present a problem on a good day, it does, however, have the potential to make a complete mess if an earlier Task fails for some reason: Doctrine_Cli does not raise errors; exceptions are swallowed and a formatted message displayed on screen.  I needed, therefore, to get the CLI to rethrow any caught exceptions.&lt;br /&gt;&lt;br /&gt;For the sake of backwards compatibility, I added an &lt;span style="font-style: italic;"&gt;option&lt;/span&gt; to force the CLI to rethrow exceptions.&lt;br /&gt;&lt;br /&gt;At construction time, set the value of the new "rethrow_exceptions" option to TRUE - the default is FALSE.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;$oCli &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Cli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'rethrow_exceptions' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;5 &lt;/span&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;6 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;7 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oCli&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;run&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$_SERVER&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'argv'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now, assuming your Tasks throw exceptions in all the right places, you can run a batch of Tasks, catch any errors, and then rollback any changes, if necessary.&lt;br /&gt;&lt;br /&gt;All changes were made across three commits: &lt;a href="http://trac.doctrine-project.org/changeset/6475"&gt;r6475&lt;/a&gt;, &lt;a href="http://trac.doctrine-project.org/changeset/6561"&gt;r6561&lt;/a&gt;, &lt;a href="http://trac.doctrine-project.org/changeset/6673"&gt;r6673&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-8003634478269287748?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/8003634478269287748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=8003634478269287748' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/8003634478269287748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/8003634478269287748'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/11/new-features-in-doctrine-12-part-2.html' title='New Features in Doctrine 1.2, Part 2: Custom Tasks, and CLI Options and Refactorings'/><author><name>Dan</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-1859050246506728663</id><published>2009-10-26T08:51:00.011Z</published><updated>2009-11-07T09:39:14.181Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine 1.2'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='migration'/><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine'/><title type='text'>New Features in Doctrine 1.2, Part 1: Default Table Settings for Migrations</title><content type='html'>I've implemented a couple of new features for Doctrine 1.2.&lt;br /&gt;&lt;br /&gt;The first is a simple change to Doctrine_Migration_Base that makes creating migrations that little bit easier.  It enables you to set default table options that will be applied whenever createTable() is used to create a table.&lt;br /&gt;&lt;br /&gt;Let's say you want all new tables to use the InnoDB engine - imagine we're using MySQL - and use UTF-8 encoding.&lt;br /&gt;&lt;br /&gt;You &lt;span style="font-style: italic;"&gt;could &lt;/span&gt;add the necessary options to all createTable() statements in all your migrations, but rather than risk forgetting to add them, you can now simply set defaults at startup, say in your boot script alongside your other Doctrine config.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;Doctrine_Migration_Base&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setDefaultTableOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;  &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;5 &lt;/span&gt;  &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;6 &lt;/span&gt;  &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;br /&gt;&lt;span class="drb-lineno"&gt;7 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;8 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Since the code - see &lt;a href="http://trac.doctrine-project.org/changeset/6540"&gt;1.2 r6540&lt;/a&gt; - simply merges specified table options into the default table options, you can override the defaults at any time.&lt;br /&gt;&lt;br /&gt;Next time, some more interesting changes to Doctrine_Cli.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-1859050246506728663?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/1859050246506728663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=1859050246506728663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/1859050246506728663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/1859050246506728663'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/10/new-features-in-doctrine-12-part-1.html' title='New Features in Doctrine 1.2, Part 1: Default Table Settings for Migrations'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-709811020961550876</id><published>2009-08-02T15:47:00.009+01:00</published><updated>2010-04-06T18:13:20.824+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='strategy'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='design pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='strategy pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='os service'/><title type='text'>serviceman: Cross-Platform Service Management</title><content type='html'>Having been forced into writing some crappy code at work last week - there was no time to do the job properly, as usual - I thought I'd spend a little time thinking about how I &lt;span style="font-style: italic;"&gt;might&lt;/span&gt; otherwise have implemented a solution because it's something that might come in handy in future.&lt;br /&gt;&lt;br /&gt;The problem: starting and stopping operating-system services without having to worry about the platform your script is running on.&lt;br /&gt;&lt;br /&gt;Starting with the interface, the serviceman "Controller", I've written a simple little library based around a number of strategy classes implementing the service management for each platform.  You can find the code in SVN on &lt;a href="https://sourceforge.net/projects/serviceman/"&gt;Sourceforge&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's an example demonstrating the task the library was originally built for:&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;$oController &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;serviceman&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Controller&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$serviceName &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oController&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;findOneService&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'/^tomcat([0-9]+)?$/i'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;5 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oController&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;restartService&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$serviceName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;6 &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;I'll be implementing strategies for Darwin, Windows, and at least one other flavour of *NIX.&lt;br /&gt;&lt;br /&gt;Please drop me a line if you're willing to contribute a strategy for your platform, or if you've got any comments / suggestions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-709811020961550876?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/709811020961550876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=709811020961550876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/709811020961550876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/709811020961550876'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/08/serviceman-cross-platform-service.html' title='serviceman: Cross-Platform Service Management'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-6374147082101049748</id><published>2009-07-26T19:58:00.010+01:00</published><updated>2009-11-07T09:39:43.633Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='solr'/><category scheme='http://www.blogger.com/atom/ns#' term='lucene'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='query string'/><title type='text'>Sequin: Now With Added Sparkle</title><content type='html'>I've just committed some major updates to &lt;a href="http://sourceforge.net/projects/sequin/"&gt;Sequin&lt;/a&gt;, my search-engine query-string builder, mentioned in my previous post.&lt;br /&gt;&lt;br /&gt;It's still a work-in-progress, but the interface will be more stable now.&lt;br /&gt;&lt;br /&gt;Updates include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Replaced "query" namespace with "lucene".  This will avoid clashes if the code is updated to handle other engines.&lt;/li&gt;&lt;li&gt;Greatly simplified the code, eliminating Clause, ComponentAbstract, Group, and - temporarily - InclusiveRange.&lt;/li&gt;&lt;li&gt;Cleaned-up the interface, and added support for nested queries - see below for an example, taken from /trunk/test/demo.php.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Here's an example, taken from /trunk/test/demo.php, using the new interface.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;require_once(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;dirname&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__DIR__&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) . &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'/include/boot.php'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;use &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;sequin&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;lucene &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;as &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;lucene&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oQuery &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;lucene&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Query&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;newInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'"Thomas Newman"'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;andTerm&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'soundtrack'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;null&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;3&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;andQuery&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'music'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'dept'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;        -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;orTerm&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'film'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;endQuery&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;()&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;notTerm&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'"Erin Brockovich"'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;14 &lt;/span&gt;print(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oQuery&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This produces the following output.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;"Thomas Newman" AND soundtrack^3 AND dept:(music OR film) NOT "Erin Brockovich"&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-6374147082101049748?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/6374147082101049748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=6374147082101049748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/6374147082101049748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/6374147082101049748'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/07/sequin-now-with-added-sparkle.html' title='Sequin: Now With Added Sparkle'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-7570119265520287485</id><published>2009-07-19T13:04:00.009+01:00</published><updated>2009-11-07T09:40:23.337Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='solr'/><category scheme='http://www.blogger.com/atom/ns#' term='lucene'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='query string'/><title type='text'>Sequin: A Search Query Builder For PHP 5.3</title><content type='html'>Yes, this &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; a departure from my planned schedule, but I thought &lt;span style="font-style: italic;"&gt;something&lt;/span&gt; would be better than nothing.  I was working on this little project this weekend - because I hope to use the code at work next week - so I thought I might as well finish-off with a quick post about it.&lt;br /&gt;&lt;br /&gt;So what is &lt;a href="http://sourceforge.net/projects/sequin/"&gt;Sequin&lt;/a&gt;?  Well, basically, it's a library that provides a fancy way of building search-engine query strings.  At present, its output is good only for &lt;a href="http://lucene.apache.org/java/docs/index.html"&gt;Lucene&lt;/a&gt;-based search implementations, but my intention is to extend the framework so it can be used with other engines.&lt;br /&gt;&lt;br /&gt;Why go to all the trouble?  We're using &lt;a href="http://lucene.apache.org/solr/"&gt;Apache Solr&lt;/a&gt;, at work, as the basis for our CMS' search functionality.  The code we use to interface with the Java service has been designed so we &lt;span&gt;could&lt;/span&gt; replace Solr with another backend, should we ever want to.  Unfortunately, though, we're currently lacking an engine-independent means of building queries: we're having to build query-strings manually, thus tying us down to Lucene and effectively sabotaging my colleague's fine work.&lt;br /&gt;&lt;br /&gt;Inspired by &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, and &lt;a href="http://www.doctrine-project.org/"&gt;Doctrine&lt;/a&gt;'s query-builder, amongst other things, I thought I should be able to quickly rope something together that will allow us - and other folks - to build query-strings by making a series of method calls, rather than writing the text directly.  And, if nothing else, I thought it might serve as a interesting exercise.&lt;br /&gt;&lt;br /&gt;In reality, I'm far from achieving my lofty goals of complete engine-independence, but I &lt;span style="font-style: italic;"&gt;have&lt;/span&gt; at least made the first step in abstracting away from raw query strings.&lt;br /&gt;&lt;br /&gt;Here's an  example, taken from demo.php in /trunk/test.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;require_once(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;dirname&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__DIR__&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) . &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'/include/boot.php'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;use &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;sequin&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;query &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;as &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;query&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oQueryBuilder &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;query&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;\&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Builder&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;find&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'"Thomas Newman"'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;andTerm&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'soundtrack'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;andValueIn&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'music'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'film'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;), &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'dept'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;    -&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;andValueBetween&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'20060719'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'20090719'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'date'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;print(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oQueryBuilder&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;And here's the output:&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;"Thomas Newman" AND soundtrack AND dept:(music OR film) AND date:[20060719 TO 20090719]&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;There are no file-downloads at present - this is very definitely alpha-grade material - but you can check-out a copy of the code by following the instructions on the &lt;a href="http://sourceforge.net/projects/sequin/develop"&gt;project's developers' page at Sourceforge&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Please drop me a line if this is at all useful, if you've got any suggestions, or you'd like to contribute or incorporate it into your own project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-7570119265520287485?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/7570119265520287485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=7570119265520287485' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7570119265520287485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/7570119265520287485'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/07/sequin-search-query-builder-for-php-53.html' title='Sequin: A Search Query Builder For PHP 5.3'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-232930265862833001</id><published>2009-06-27T09:05:00.007+01:00</published><updated>2009-06-27T18:00:43.081+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='namespaces'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine'/><category scheme='http://www.blogger.com/atom/ns#' term='singleton'/><category scheme='http://www.blogger.com/atom/ns#' term='php standards group'/><title type='text'>Coming Soon...</title><content type='html'>I have rather a poor track record of posting, but I hope to rectify that over the coming weeks and months.&lt;br /&gt;&lt;br /&gt;I've been so busy that I haven't found the time to report on the things I've been working on and discovering.  However, that does mean that I've been building up a bunch of ideas for articles that should be appearing here soon.&lt;br /&gt;&lt;br /&gt;Here's what you can expect to see some time in the near(ish) future.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Re-usable class loader class for namespaced PHP 5.3 code&lt;/span&gt;. I recently wrote a really simple class for loading classes in projects using namespaces. It's intended to be used primarily for auto-loading, but you can also use it to manually load classes. It follows the same &lt;a href="http://groups.google.com/group/php-standards/web/php-coding-standard?pli=1"&gt;conventions&lt;/a&gt; as those proposed by the newly formed PHP Standards Group.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;An improved, more test-friendly Singleton class for PHP 5.3&lt;/span&gt;.  The code presented in my post last year was really intended only as a demonstration of one of the great new features of PHP 5.3, not a definitive implementation of Singleton.  I've learned a lot since then, and having re-implemented the class for a product I've been working on, I can focus more on the nature of Singleton and the issues associated with its use.  I want to put that one to bed because Singleton, I find, is one of the least useful of all patterns.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The pleasure and pain of Doctrine Collections&lt;/span&gt;.  I've been working with large data-sets and this has highlighted some quite serious issues with Collections.  Not only that, but the behaviour of some of the methods is, I think, really rather odd - behaviour that caught me out when I first started working with them.  I will identify the advantages and pitfalls of using Collections, and some tips on how to deal with the problems.  I may also discuss my experiences of processing large amounts of data using Doctrine.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Unit testing tips&lt;/span&gt;.  I've been dabbling with unit-testing for only 18 months, but I've learned a few things along the way.  There's loads of information out there, but it's quite difficult to get your head around testing when you first start out.  There's no denying the usefulness of testing, the reasons for doing it, but it's hard to get into the right mind-set.  It's difficult to know &lt;span style="font-style: italic;"&gt;how&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;what&lt;/span&gt; to test.  It's one of those things you really need to &lt;span style="font-style: italic;"&gt;understand&lt;/span&gt; because otherwise you can end up writing crappy, worthless tests just like you can the code you're trying to test.  I still write crappy tests - I think - but my brain is starting to align itself to the testing way.  I've been trying to keep a note of the things I've found helpful and I'll try to get them up on the site.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-232930265862833001?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/232930265862833001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=232930265862833001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/232930265862833001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/232930265862833001'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/06/coming-soon.html' title='Coming Soon...'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-3216906579745138335</id><published>2009-05-02T10:11:00.010+01:00</published><updated>2009-05-02T11:28:35.377+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP 5'/><category scheme='http://www.blogger.com/atom/ns#' term='timezone'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='conversion'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTime'/><category scheme='http://www.blogger.com/atom/ns#' term='date'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTimeZone'/><title type='text'>Converting The Time Zone of a Date</title><content type='html'>This is as much a reminder to myself as it is a helping hand for anyone else working with international dates in PHP.&lt;br /&gt;&lt;br /&gt;Converting from one time-zone to another is very easily - and cleanly - accomplished using the DateTime and DateTimeZone classes.  The key, the DateTime::setTimezone() method, has been available since PHP 5.2.&lt;br /&gt;&lt;br /&gt;The following example shows how to convert a UTC date, in a string, to EST (Eastern Standard Time).  The date can be supplied in any format supported by strtotime() - which doesn't, it seems, include forward-specified dates containing slashes (e.g. "23/03/2009").&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;1 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;2 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;3 &lt;/span&gt;$oDateTime &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;DateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'2-5-2009 10:12:00'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;DateTimeZone&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'UTC'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;4 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;print_r&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oDateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;5 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;6 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oDateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setTimezone&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;DateTimeZone&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'EST'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;7 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;print_r&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oDateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here's the output:&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;DateTime Object&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;    [date] =&amp;gt; 2009-05-02 10:12:00&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;    [timezone_type] =&amp;gt; 3&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;    [timezone] =&amp;gt; UTC&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;DateTime Object&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    [date] =&amp;gt; 2009-05-02 06:12:00&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;    [timezone_type] =&amp;gt; 3&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;    [timezone] =&amp;gt; America/New_York&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;You've then got a couple of options for retrieving the converted date, as the next snippet shows.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;// ...&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;// Return the date in the internal, MySQL-like, format&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;print &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oDateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;date&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;  &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;// =&amp;gt; 2009-05-02 06:12:00&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;// Return the date in an alternate format.  Use the date() formatting options.&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;print &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oDateTime&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;format&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'jS F, Y'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);  &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;// =&amp;gt; 2nd May, 2009&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Oh, and while we're on the subject of dates, don't forget that strtotime() always outputs a UTC timestamp.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-3216906579745138335?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/3216906579745138335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=3216906579745138335' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3216906579745138335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3216906579745138335'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/05/converting-time-zone-of-date.html' title='Converting The Time Zone of a Date'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-4724403922390168882</id><published>2009-04-26T12:49:00.015+01:00</published><updated>2009-11-11T18:55:01.363Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP 5'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='migration'/><category scheme='http://www.blogger.com/atom/ns#' term='Doctrine'/><title type='text'>A Custom Doctrine Migration Class With Default Table Options and Other Loveliness</title><content type='html'>&lt;span style="font-weight: bold;"&gt;UPDATE: The functionality described below is now available in Doctrine 1.2.  Please see my article &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://danbettles.blogspot.com/2009/10/new-features-in-doctrine-12-part-1.html"&gt;New Features in Doctrine 1.2, Part 1: Default Table Settings for Migrations&lt;/a&gt;&lt;span style="font-weight: bold;"&gt; for details.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Migrations are one of Doctrine's big draws, but it didn't take long - two tables, in fact - before I wanted more from the experience.&lt;br /&gt;&lt;br /&gt;First, I wanted to be able to create tables using a set of default table options, so I didn't have to explicitly specify them every time; and, second, I wanted to be able to create column definitions using the data types I know from MySQL (e.g. "SMALLINT", an &lt;span style="font-style: italic;"&gt;integer&lt;/span&gt; stored in &lt;span style="font-style: italic;"&gt;two bytes&lt;/span&gt;).  (As a bonus, the solution to the second problem allows us to deal with another minor annoyance: the wordiness of it all.)&lt;br /&gt;&lt;br /&gt;Both improvements were implemented in an application-specific subclass of Doctrine_Migration_Base.  All I need do now, to take advantage of the new functionality, is create migration classes extending the new class.  (We can do this, by the way, because when you migrate your database, Doctrine_Migration looks for all classes, in your migrations directory, &lt;span style="font-style: italic;"&gt;extending&lt;/span&gt; Doctrine_Migration_Base.)&lt;br /&gt;&lt;br /&gt;Here's a very simple example showing how you can set default table options, and how you create column definitions using 'aliases', or "option groups" as I've called them internally, using this extended migration class.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;// Load and initialise Doctrine&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;// Load application-specific migration class&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;MyDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setDefaultTableOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;// ...&lt;br /&gt;&lt;span class="drb-lineno"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;15 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;CreateTest &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;MyDoctrineMigrationBase &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;16 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;17 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;up &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;18 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;createTable&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'test'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;19 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'id' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnDef&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;20 &lt;/span&gt;        ));&lt;br /&gt;&lt;span class="drb-lineno"&gt;21 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;22 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;23 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;down &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;24 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;dropTable&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'test'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;25 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;26 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here's the class I created for the application I'm working on.  I've defined my default table options and column option-groups in the class for now.  The code is reusable, so I'll shortly be renaming the class and adding it to my component library.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;001 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;002 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;003 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;004 &lt;/span&gt; * @author Dan Bettles &amp;lt;danbettles@yahoo.co.uk&amp;gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;005 &lt;/span&gt; */&lt;br /&gt;&lt;span class="drb-lineno"&gt;006 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;abstract class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Doctrine_Migration_Base &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;007 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;008 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;009 &lt;/span&gt;     * @var array&lt;br /&gt;&lt;span class="drb-lineno"&gt;010 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;011 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;protected static &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aDefaultTableOption &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;012 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;013 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;014 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;,&lt;br /&gt;&lt;span class="drb-lineno"&gt;015 &lt;/span&gt;    );&lt;br /&gt;&lt;span class="drb-lineno"&gt;016 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;017 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;018 &lt;/span&gt;     * @var array&lt;br /&gt;&lt;span class="drb-lineno"&gt;019 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;020 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;protected static &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aColumnOptionGroup &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;021 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;022 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;023 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;024 &lt;/span&gt;    );&lt;br /&gt;&lt;span class="drb-lineno"&gt;025 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;026 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;027 &lt;/span&gt;     * @param array $p_aOption&lt;br /&gt;&lt;span class="drb-lineno"&gt;028 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;029 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setDefaultTableOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;030 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aDefaultTableOption &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;031 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;032 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;033 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;034 &lt;/span&gt;     * @return array&lt;br /&gt;&lt;span class="drb-lineno"&gt;035 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;036 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;defaultTableOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;037 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aDefaultTableOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;038 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;039 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;040 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;041 &lt;/span&gt;     * @param array $p_aDefaultOption&lt;br /&gt;&lt;span class="drb-lineno"&gt;042 &lt;/span&gt;     * @param array $p_aOption&lt;br /&gt;&lt;span class="drb-lineno"&gt;043 &lt;/span&gt;     * @return array&lt;br /&gt;&lt;span class="drb-lineno"&gt;044 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;045 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergeOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aDefaultOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;046 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;array_merge&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aDefaultOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;047 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;048 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;049 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;050 &lt;/span&gt;     * Adds a create-table change, as per Doctrine_Migration_Base, but applies default table options, defined in&lt;br /&gt;&lt;span class="drb-lineno"&gt;051 &lt;/span&gt;     * $aDefaultTableOption, first&lt;br /&gt;&lt;span class="drb-lineno"&gt;052 &lt;/span&gt;     *&lt;br /&gt;&lt;span class="drb-lineno"&gt;053 &lt;/span&gt;     * @param string $tableName Name of the table&lt;br /&gt;&lt;span class="drb-lineno"&gt;054 &lt;/span&gt;     * @param array [$fields] Array of fields for table&lt;br /&gt;&lt;span class="drb-lineno"&gt;055 &lt;/span&gt;     * @param array [$options] Array of options for the table&lt;br /&gt;&lt;span class="drb-lineno"&gt;056 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;057 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;createTable &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$tableName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$fields &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array(), array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$options &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array()) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;058 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;parent&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;createTable&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$tableName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$fields&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergeOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aDefaultTableOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$options&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;059 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;060 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;061 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;062 &lt;/span&gt;     * @param array $p_aColumnOptionGroup&lt;br /&gt;&lt;span class="drb-lineno"&gt;063 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;064 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setColumnOptionGroups &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;065 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aColumnOptionGroup &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;066 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;067 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;068 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;069 &lt;/span&gt;     * @return array&lt;br /&gt;&lt;span class="drb-lineno"&gt;070 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;071 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnOptionGroups &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;072 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;073 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;074 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;075 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;076 &lt;/span&gt;     * @param string,... $p_columnOptionGroupName&lt;br /&gt;&lt;span class="drb-lineno"&gt;077 &lt;/span&gt;     * @return array&lt;br /&gt;&lt;span class="drb-lineno"&gt;078 &lt;/span&gt;     * @throws BadMethodCallException&lt;br /&gt;&lt;span class="drb-lineno"&gt;079 &lt;/span&gt;     * @throws InvalidArgumentException&lt;br /&gt;&lt;span class="drb-lineno"&gt;080 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;081 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnDef &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;082 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array();&lt;br /&gt;&lt;span class="drb-lineno"&gt;083 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;084 &lt;/span&gt;        if (&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;func_num_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() &amp;lt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;085 &lt;/span&gt;            throw new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;BadMethodCallException&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"Column option-group not specified"&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;086 &lt;/span&gt;        }&lt;br /&gt;&lt;span class="drb-lineno"&gt;087 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;088 &lt;/span&gt;        foreach (&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;func_get_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() as &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;089 &lt;/span&gt;            if (&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;is_array&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;090 &lt;/span&gt;                &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergeOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;091 &lt;/span&gt;                continue;&lt;br /&gt;&lt;span class="drb-lineno"&gt;092 &lt;/span&gt;            }&lt;br /&gt;&lt;span class="drb-lineno"&gt;093 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;094 &lt;/span&gt;            if (! isset(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;])) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;095 &lt;/span&gt;                throw new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;InvalidArgumentException&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;"The column option-group \"&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;}&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;\" does not exist"&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;096 &lt;/span&gt;            }&lt;br /&gt;&lt;span class="drb-lineno"&gt;097 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;098 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergeOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;self&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$optionGroupName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;]);&lt;br /&gt;&lt;span class="drb-lineno"&gt;099 &lt;/span&gt;        }&lt;br /&gt;&lt;span class="drb-lineno"&gt;100 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;101 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;;&lt;br /&gt;&lt;span class="drb-lineno"&gt;102 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;103 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And here are the PHPUnit tests I've written so far.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;001 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;002 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;003 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;require_once(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'PHPUnit/Framework.php'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;004 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;005 &lt;/span&gt;require_once(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__DIR__ &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;. &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'/../../../include/loadAll.php'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;006 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;007 &lt;/span&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBaseTest &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;PHPUnit_Framework_TestCase &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;008 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;009 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testIsAbstract &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;010 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oReflectionClass &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;ReflectionClass&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'EmrsDoctrineMigrationBase'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;011 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertTrue&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$oReflectionClass&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;isAbstract&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;());&lt;br /&gt;&lt;span class="drb-lineno"&gt;012 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;013 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;014 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;015 &lt;/span&gt;     * @dataProvider tableOptions&lt;br /&gt;&lt;span class="drb-lineno"&gt;016 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;017 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testDefaulttableoptionsReturnsOptionsSetWithSetdefaulttableoptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;018 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setDefaultTableOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;019 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertEquals&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aOption&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;defaultTableOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;());&lt;br /&gt;&lt;span class="drb-lineno"&gt;020 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;021 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;022 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;tableOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;023 &lt;/span&gt;        return array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;024 &lt;/span&gt;            array(array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)),&lt;br /&gt;&lt;span class="drb-lineno"&gt;025 &lt;/span&gt;            array(array()),&lt;br /&gt;&lt;span class="drb-lineno"&gt;026 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;027 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;028 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;029 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;030 &lt;/span&gt;     * @dataProvider mergedOptions&lt;br /&gt;&lt;span class="drb-lineno"&gt;031 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;032 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testMergeoptionsMergesUserOptionsIntoDefaultOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_defaults&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_user&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;033 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertEquals&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergeOptions&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_defaults&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_user&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;034 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;035 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;036 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mergedOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;037 &lt;/span&gt;        return array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;038 &lt;/span&gt;            array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;039 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;040 &lt;/span&gt;                array(),&lt;br /&gt;&lt;span class="drb-lineno"&gt;041 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;042 &lt;/span&gt;            ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;043 &lt;/span&gt;            array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;044 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'utf8_unicode_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;045 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'latin1'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'latin1_general_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;046 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'INNODB'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'charset' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'latin1'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'collate' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'latin1_general_ci'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;047 &lt;/span&gt;            ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;048 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;049 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;050 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;051 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testCreatetableCreatesATableUsingTheDefaultTableOptions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;052 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;markTestIncomplete&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;053 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;054 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;055 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;056 &lt;/span&gt;     * @dataProvider columnOptionGroups&lt;br /&gt;&lt;span class="drb-lineno"&gt;057 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;058 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testColumnoptiongroupsReturnsTheColumnOptionGroupsSetWithSetcolumnoptiongroups &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;059 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setColumnOptionGroups&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;060 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertEquals&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_aColumnOptionGroup&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnOptionGroups&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;());&lt;br /&gt;&lt;span class="drb-lineno"&gt;061 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;062 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;063 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnOptionGroups &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;064 &lt;/span&gt;        return array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;065 &lt;/span&gt;            array(array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;))),&lt;br /&gt;&lt;span class="drb-lineno"&gt;066 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;067 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;068 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;069 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;070 &lt;/span&gt;     * @dataProvider columnDefinitions&lt;br /&gt;&lt;span class="drb-lineno"&gt;071 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;072 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testColumndefReturnsAColumnDefinitionArrayCreatedFromTheSpecifiedOptionGroups &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_groupNames&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;073 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setColumnOptionGroups&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_groupNames&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;074 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertEquals&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;call_user_func_array&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'EmrsDoctrineMigrationBase::columnDef'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;075 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;076 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;077 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnDefinitions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;078 &lt;/span&gt;        return array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;079 &lt;/span&gt;            array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;080 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)),&lt;br /&gt;&lt;span class="drb-lineno"&gt;081 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;082 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;083 &lt;/span&gt;            ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;084 &lt;/span&gt;            array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;085 &lt;/span&gt;                array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;086 &lt;/span&gt;                    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;087 &lt;/span&gt;                    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;088 &lt;/span&gt;                    &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)&lt;br /&gt;&lt;span class="drb-lineno"&gt;089 &lt;/span&gt;                ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;090 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;091 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;092 &lt;/span&gt;            ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;093 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;094 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;095 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;096 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testColumndefThrowsAnExceptionIfOneOfTheSpecifiedOptionGroupsDoesNotExist &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;097 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setExpectedException&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'InvalidArgumentException'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;098 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setColumnOptionGroups&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(array());&lt;br /&gt;&lt;span class="drb-lineno"&gt;099 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnDef&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'foo'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;100 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;101 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;102 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testColumndefThrowsAnExceptionIfCalledWithoutArguments &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;103 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setExpectedException&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'BadMethodCallException'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;104 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;columnDef&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;105 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;106 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;107 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;/**&lt;br /&gt;&lt;span class="drb-lineno"&gt;108 &lt;/span&gt;     * @dataProvider mixedColumnDefinitions&lt;br /&gt;&lt;span class="drb-lineno"&gt;109 &lt;/span&gt;     */&lt;br /&gt;&lt;span class="drb-lineno"&gt;110 &lt;/span&gt;    &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testColumndefWillAcceptAnArrayOfOptionsInPlaceOfAnOptionGroupName &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_groupNames&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;111 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;EmrsDoctrineMigrationBase&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;setColumnOptionGroups&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_groupNames&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;112 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertEquals&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_expected&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;call_user_func_array&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'EmrsDoctrineMigrationBase::columnDef'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$p_args&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;));&lt;br /&gt;&lt;span class="drb-lineno"&gt;113 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;114 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;115 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;mixedColumnDefinitions &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;116 &lt;/span&gt;        return array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;117 &lt;/span&gt;            array(&lt;br /&gt;&lt;span class="drb-lineno"&gt;118 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)),&lt;br /&gt;&lt;span class="drb-lineno"&gt;119 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'smallint'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;)),&lt;br /&gt;&lt;span class="drb-lineno"&gt;120 &lt;/span&gt;                array(&lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'type' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'integer'&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'length' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'unsigned' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;, &lt;/span&gt;&lt;span style="color: rgb(221, 0, 0);"&gt;'notnull' &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;),&lt;br /&gt;&lt;span class="drb-lineno"&gt;121 &lt;/span&gt;            ),&lt;br /&gt;&lt;span class="drb-lineno"&gt;122 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;123 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;124 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Hope you find this useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-4724403922390168882?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/4724403922390168882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=4724403922390168882' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/4724403922390168882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/4724403922390168882'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2009/04/custom-doctrine-migration-class-with.html' title='A Custom Doctrine Migration Class With Default Table Options and Other Loveliness'/><author><name>Dan</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-3251060635451648274</id><published>2008-10-23T14:08:00.004+01:00</published><updated>2009-04-26T12:36:56.725+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='problem solving'/><title type='text'>Debugging Made Easier</title><content type='html'>Fact: you can make your life a whole lot easier, when debugging, simply by not making assumptions - by &lt;span style="font-style: italic;"&gt;guessing&lt;/span&gt;, essentially - about what might be at fault.  Concentrate on what you can see and what you &lt;span style="font-style: italic;"&gt;know&lt;/span&gt; to be true - or what you can find out by directly querying the system.  (Really, this applies to &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; kind of problem solving, in any walk of life.)&lt;br /&gt;&lt;br /&gt;I often forget, and that's why I'm making a point to bring it up now.  As a means of drumming it into my own thick head.  Only last week, in a moment of weakness, I fell into the trap of assuming I knew the cause of a problem I was having.  The curious thing is that when I discovered that my initial assumption was wrong, I went and replaced it with another, equally invalid one.  And so my fate was sealed.  I might just as well have packed it in then and there, but instead, I spent Lord-knows how long flitting aimlessly from one source-file to another.  I was blinded by my assumptions: I couldn't see the wood for the trees.  Worst of all, they were the wrong trees in the wrong forest.&lt;br /&gt;&lt;br /&gt;I wonder, actually, how I came to find the source of the problem on that occasion.  I'm guessing it was the result of a kind of brute-force attack on my subconscious: I must have fully memorized the entire section of code after the 80th reading, pieced it together somehow, and then - thank God - had an epiphany.  I clearly remember, afterwards, thinking that I'd looked at the block of code that would have quickly led me to the fault, but because I thought I already knew what the cause was, I didn't take the time to &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; look at the lines in front of me.  My mind was closed-off and wandering elsewhere.  You don't want to know the awful feeling you get after wasting hours tracking down a bug &lt;span style="font-style: italic;"&gt;that&lt;/span&gt; insignificant.&lt;br /&gt;&lt;br /&gt;Even if you find yourself in the middle of such a predicament, there's still hope.  Take a break.  Give yourself 30 minutes, say, and if, at the end of that, you still haven't had any success, get a change of scenery.  Better still, seek help from a colleague.  There have been countless times when I've been in the middle of explaining a problem to my buddy, and I've spotted the cause.  By explaining a problem, by breaking it down for another person to understand, you're forced to confront the facts.  Sometimes that's all it takes.  And if &lt;span style="font-style: italic;"&gt;they&lt;/span&gt; can't help, at least you'll be in the right mindset.&lt;br /&gt;&lt;br /&gt;And don't go thinking that it's safe to take a stab at the answer because a problem looks simple.  Remember that one problem can often turn out to be the work of a whole &lt;span style="font-style: italic;"&gt;gang&lt;/span&gt; of pesky little bugs.  If you go into a fight like that without an open mind, you're gonna be in for a world of pain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-3251060635451648274?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/3251060635451648274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=3251060635451648274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3251060635451648274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/3251060635451648274'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2008/10/debugging-made-easier.html' title='Debugging Made Easier'/><author><name>Dan</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><entry><id>tag:blogger.com,1999:blog-1893324312984055455.post-299834593928339468</id><published>2008-10-04T09:54:00.012+01:00</published><updated>2009-05-02T11:30:41.662+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='get_called_class'/><category scheme='http://www.blogger.com/atom/ns#' term='php 5.3'/><category scheme='http://www.blogger.com/atom/ns#' term='design pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='singleton'/><title type='text'>Implementing a Singleton Base Class in PHP 5.3</title><content type='html'>&lt;span style="font-size:130%;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To my mind, PHP 5.3 is the most exciting thing to happen to PHP since PHP 5 itself was released.  There's plenty to say about the new features and the opportunities that are now available to us, but in this article I want to get down to some good ol' fashioned coding.  I'll save the eulogising for another time.&lt;br /&gt;&lt;br /&gt;At the heart of the code I'll shortly be introducing, is a new, seemingly innocuous function, get_called_class.  On its own, it really &lt;span style="font-style: italic;"&gt;doesn't &lt;/span&gt;do much.  This simple little function, however, plugs a sizeable hole in PHP's object-oriented feature-set and makes it possible to write some really elegant code.&lt;br /&gt;&lt;br /&gt;Just one of the things it allows us to do is build a complete, all singing, all dancing Singleton base-class that we can simply &lt;span style="font-style: italic;"&gt;extend &lt;/span&gt;to create any number of &lt;span style="font-style: italic;"&gt;fully functioning &lt;/span&gt;singletons.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Roughing-Out the Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We can start by creating an abstract class – there won't ever be a need to get an instance of the Singleton class – with stubs for the main methods.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;abstract class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Singleton &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;    protected function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__construct&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    final public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;    final private function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__clone&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The first thing we've done is create a protected constructor: although we don't want our &lt;span style="font-style: italic;"&gt;users&lt;/span&gt; creating instances directly, we &lt;span style="font-style: italic;"&gt;do &lt;/span&gt;want subclasses of Singleton to be able to implement their own initialization code – so we can't make it private.&lt;br /&gt;&lt;br /&gt;Next, we've got a public, static method, “getInstance”, that'll serve-up the single instance of a subclass.  (“getInstance”, or simply “instance”, appear to be the preferred names for the instance getter in implementations of the singleton pattern, at least in PHP.)  The method &lt;span style="font-style: italic;"&gt;must &lt;/span&gt;be at class-level (i.e. static) because we'll be needing privileged access to the class' internals now that we've hidden the constructor from the outside world.  getInstance is additionally marked “final” to prevent subclasses re-implementing it.  (If there &lt;span style="font-style: italic;"&gt;was &lt;/span&gt;a need to re-implement getInstance, which is small and well focused, it &lt;span style="font-style: italic;"&gt;may &lt;/span&gt;be a sign that the subclass isn't actually a Singleton after all, or it may be that we need to expand our definition of the singleton pattern.)&lt;br /&gt;&lt;br /&gt;Finally, we've created an empty, private implementation of the magic “__clone” to prevent &lt;span style="font-style: italic;"&gt;anyone &lt;/span&gt;cloning an instance – using the keyword “clone”.  If it were possible to clone an instance, the class could no longer claim to be a singleton and the integrity of our code could be in jeopardy.  __clone is marked “final” only for completeness: since it is already private, subclasses won't be able to re-implement it anyway.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, let's take a look inside getInstance, the real meat of the pattern.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;abstract class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Singleton &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;    protected function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__construct&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;    final public static function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;        static &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aoInstance &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= array();&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$calledClassName &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;= &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;get_called_class&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;        if (! isset (&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aoInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$calledClassName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;])) {&lt;br /&gt;&lt;span class="drb-lineno"&gt;14 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aoInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$calledClassName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;] = new &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$calledClassName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;();&lt;br /&gt;&lt;span class="drb-lineno"&gt;15 &lt;/span&gt;        }&lt;br /&gt;&lt;span class="drb-lineno"&gt;16 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;17 &lt;/span&gt;        return &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$aoInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$calledClassName&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;];&lt;br /&gt;&lt;span class="drb-lineno"&gt;18 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;19 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;20 &lt;/span&gt;    final private function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__clone&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;21 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;22 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The first thing you'll notice is an &lt;span style="font-style: italic;"&gt;array &lt;/span&gt;of instances.  If you remember, our objective is to create a class that we can just &lt;span style="font-style: italic;"&gt;extend &lt;/span&gt;to create a working singleton: we don't want to have to implement &lt;span style="font-style: italic;"&gt;any &lt;/span&gt;singleton-related code further down the class hierarchy.  Since we want to inherit &lt;span style="font-style: italic;"&gt;all&lt;/span&gt; functionality in subclasses, the getInstance method must store &lt;span style="font-style: italic;"&gt;many &lt;/span&gt;single instances: one for each subclass of Singleton.  Once we get round to actually storing instances, we'll key each of them on the name of the class to which they belong.&lt;br /&gt;&lt;br /&gt;Now, to create and store an instance.  Using PHP's extremely useful variable variables we can instantiate a class by name.  The problem is we must first get hold of the name of the class to instantiate.  Let's say we're gearing-up to create a DatabaseConnection subclass – the “Hello World!” of singleton examples.  Once written, we want to be able to call DatabaseConnection::getInstance() to fetch the instance.  We get the name of the class we're calling, the name in front of the two colons - “DatabaseConnection” in the case of the previous example - using the new function, get_called_class.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Testing the Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All that remains is to introduce some tests to prove that Singleton does actually do what it says on the tin.  Here's a script, written for SimpleTest, that tests two key aspects of our class.&lt;br /&gt;&lt;br /&gt;&lt;div class="drb-sourcecodeviewer"&gt;&lt;pre class="drb-sourcecode"&gt;&lt;span class="drb-lineno"&gt;01 &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;&amp;lt;?php&lt;br /&gt;&lt;span class="drb-lineno"&gt;02 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;03 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 128, 0);"&gt;//@todo Load SimpleTest&lt;br /&gt;&lt;span class="drb-lineno"&gt;04 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;05 &lt;/span&gt;//@todo Load Singleton&lt;br /&gt;&lt;span class="drb-lineno"&gt;06 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;07 &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01 &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Singleton &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;08 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;09 &lt;/span&gt;    protected function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__construct&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;10 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;11 &lt;/span&gt;}&lt;br /&gt;&lt;span class="drb-lineno"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;13 &lt;/span&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton02 &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;Singleton &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;15 &lt;/span&gt;    protected function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__construct&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;16 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;17 &lt;/span&gt;}&lt;br /&gt;&lt;span class="drb-lineno"&gt;18 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;19 &lt;/span&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton03 &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01 &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;21 &lt;/span&gt;    protected function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;__construct&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;22 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;23 &lt;/span&gt;}&lt;br /&gt;&lt;span class="drb-lineno"&gt;24 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;25 &lt;/span&gt;class &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;SingletonUnitTestCase &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;extends &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;UnitTestCase &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;{&lt;br /&gt;&lt;span class="drb-lineno"&gt;26 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;27 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testGetInstanceAlwaysReturnsSingleInstanceOfSubclass&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;28 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertTrue &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;29 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() instanceof &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;br /&gt;&lt;span class="drb-lineno"&gt;30 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;31 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;32 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertReference &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;33 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(),&lt;br /&gt;&lt;span class="drb-lineno"&gt;34 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;()&lt;br /&gt;&lt;span class="drb-lineno"&gt;35 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;36 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;37 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;38 &lt;/span&gt;    public function &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;testGetInstanceReturnsCorrectInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() {&lt;br /&gt;&lt;span class="drb-lineno"&gt;39 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertTrue &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;40 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() instanceof &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;br /&gt;&lt;span class="drb-lineno"&gt;41 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;42 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;43 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertReference &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;44 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(),&lt;br /&gt;&lt;span class="drb-lineno"&gt;45 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton01&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;()&lt;br /&gt;&lt;span class="drb-lineno"&gt;46 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;47 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;48 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertTrue &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;49 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton02&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() instanceof &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton02&lt;br /&gt;&lt;span class="drb-lineno"&gt;50 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;51 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;52 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertReference &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;53 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton02&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(),&lt;br /&gt;&lt;span class="drb-lineno"&gt;54 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton02&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;()&lt;br /&gt;&lt;span class="drb-lineno"&gt;55 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;56 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;57 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertTrue &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;58 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton03&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;() instanceof &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton03&lt;br /&gt;&lt;span class="drb-lineno"&gt;59 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;);&lt;br /&gt;&lt;span class="drb-lineno"&gt;60 &lt;/span&gt;&lt;br /&gt;&lt;span class="drb-lineno"&gt;61 &lt;/span&gt;        &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;assertReference &lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(&lt;br /&gt;&lt;span class="drb-lineno"&gt;62 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton03&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;(),&lt;br /&gt;&lt;span class="drb-lineno"&gt;63 &lt;/span&gt;            &lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;TestSingleton03&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 0, 187);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 119, 0);"&gt;()&lt;br /&gt;&lt;span class="drb-lineno"&gt;64 &lt;/span&gt;        );&lt;br /&gt;&lt;span class="drb-lineno"&gt;65 &lt;/span&gt;    }&lt;br /&gt;&lt;span class="drb-lineno"&gt;66 &lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The first test checks if getInstance always returns the same instance when called repeatedly against a subclass.  The second test is almost certainly over the top, but ensures that no matter what, Singleton will always return the &lt;span style="font-style: italic;"&gt;correct &lt;/span&gt;instance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1893324312984055455-299834593928339468?l=danbettles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://danbettles.blogspot.com/feeds/299834593928339468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1893324312984055455&amp;postID=299834593928339468' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/299834593928339468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1893324312984055455/posts/default/299834593928339468'/><link rel='alternate' type='text/html' href='http://danbettles.blogspot.com/2008/10/implementing-singleton-base-class-in.html' title='Implementing a Singleton Base Class in PHP 5.3'/><author><name>Dan</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>6</thr:total></entry></feed>
