<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.tigerheron.com" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>PHP-GTK</title>
 <link>http://www.tigerheron.com/category/php-gtk</link>
 <description>The taxonomy view with a depth of 0.</description>
 <language>en-US</language>
<item>
 <title>A Tale of Two Patterns</title>
 <link>http://www.tigerheron.com/article/2007/11/tale-two-patterns</link>
 <description>&lt;p&gt;
  Originally, I planned to write about how to configure the Apache
  server to run both PHP4 and PHP5. With the push toward PHP5 (see &lt;a
  href=&quot;http://gophp5.org/&quot;&gt;Go PHP5&lt;/a&gt;), there are now hundreds of
  articles covering that topic. Instead, I will talk about two IT
  patterns I use for PHP development on Windows. The patterns are
  ancient and familiar to most Unix developers, but little used in the
  Windows world.
&lt;/p&gt;
&lt;!--break--&gt;
&lt;p&gt;
  Since the patterns existed long before the term &amp;quot;design
  patterns&amp;quot; came into vogue, they don&amp;#39;t have any names that I am aware
  of. In this article, I will call them the &lt;em&gt;Bait-and Switch &lt;/em&gt;
  and the &lt;em&gt;Shell Game&lt;/em&gt; patterns.
&lt;/p&gt;
&lt;h2&gt;Junction points&lt;/h2&gt;
&lt;p&gt;
  On Unix, the Bait-and-Switch pattern is implemented using soft
  links. On Windows, the equivalent feature (at least for folders) is a
  junction point. Since this is an obscure feature for many Windows users, let me
  start by describing what junction points do and how to manage them.
&lt;/p&gt;
&lt;p&gt;
  Junction points can be used to assign the address of one directory to another.
  Once created, file operations performed on the junction point
  are actually forwarded to the linked directory. Essentially, you are
  reaching the same files through alternate file paths.
&lt;/p&gt;
&lt;p&gt;
  The concept is similar to a Windows &amp;quot;shortcut&amp;quot;, but
  shortcuts are limited in the number of file operations they support.
  Junction points are much better at &amp;quot;fooling&amp;quot; the operating
  system.
&lt;/p&gt;
&lt;p&gt;
  How do you create a junction point? Microsoft must feel that this
  feature is too confusing for most users as they omitted creating a
  user interface for it. I&amp;#39;ve been using a great open source tool: &lt;a
  href=&quot;http://sourceforge.net/projects/ntfslinkext&quot;&gt;NTFS Link&lt;/a&gt;,
  written originally by &lt;a href=&quot;http://www.elsdoerfer.info/&quot;&gt;Michael
  Elsdoerfer&lt;/a&gt; and now maintained on &lt;a
  href=&quot;http://sourceforge.net/&quot;&gt;SourceForge&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  I won&amp;#39;t go into the details of installing and configuring NTFS Link
  since there is plenty of information on Michael&amp;#39;s site. The only tip
  I&amp;#39;ll give is to take advantage of the icon overlays feature in the
  configuration dialog so that junction points are easy to see in an
  Explorer window. You won&amp;#39;t have any trouble spotting the junction points in my
  screen capture below.
&lt;/p&gt;
&lt;p&gt;
  I don&amp;#39;t believe NTFS Link will work on Vista, since Microsoft has
  introduced a replacement for junction points called &lt;a
  href=&quot;http://en.wikipedia.org/wiki/NTFS_symbolic_link&quot;&gt;NTFS symbolic
  links&lt;/a&gt;. These can point to files as well as folders, which is
  somewhat closer to the Unix soft link command. You can use the
  &amp;quot;mklink&amp;quot;  to create these links, but that&amp;#39;s quite a step
  down from the beautiful interface that NTFS Link provides.
&lt;/p&gt;
&lt;p&gt;
  One caveat, specially for Unix users on Windows: if you delete a
  junction point, you will also delete the files in the folder pointed
  to by the junction point. On Unix, deleting a soft link only removes
  the link. This is one reason why it&amp;#39;s important to ensure that
  junction points are easy to spot. The good news is that the NTFS
  Link package  intercepts folder deletions and implements the Unix
  behavior. This works only for the junction points it creates.
&lt;/p&gt;
&lt;p&gt;
  Folder copies can also pose problems, but NTFS Link helps us there
  as well. When you attempt to copy a junction point, it will ask
  whether you want to copy just the junction point or to copy it as
  they it were a real directory.
&lt;/p&gt;
&lt;h2&gt;The Bait-and-Switch pattern&lt;/h2&gt;
&lt;p&gt;
  To use the  Bait-and-Switch pattern, start by installing multiple versions
  of a software package. Each version is usually placed in a directory
  with the package and version as part of the name; for example,
  php-5.2.5-Win32. Then create a junction point to the
  version you want to use. Finally, have the rest of the system access the
  package through the junction point. Now, changing the package version is as
  easy as redirecting the junction point.
&lt;/p&gt;
&lt;p&gt;
  Junction points can be cascaded. For example, you could use
  &amp;quot;php&amp;quot; to point to the latest version of PHP. Then use
  &amp;quot;php4&amp;quot; and &amp;quot;php5&amp;quot; to point to the latest version
  of PHP 4 or 5. So &amp;quot;php&amp;quot; would point to &amp;quot;php5&amp;quot;
  which would point to the latest version of php5. When PHP 6 is
  released, &amp;quot;php&amp;quot; would change to point to &amp;quot;php6&amp;quot;,
  but &amp;quot;php5&amp;quot; would continue to point to the latest PHP 5
  version.
&lt;/p&gt;
&lt;h2&gt;The Shell Game pattern&lt;/h2&gt;
&lt;p&gt;
  The Shell Game pattern uses a different way of fooling the operating
  system. The idea is to run a program by first running a script that
  configures the program environment and then starts the program. If
  set up properly, the command you type to start the script can be the same
  as what you would normally type to start the program (e.g. typing &quot;php&quot; to
  start the CLI PHP program). On Unix, the script is usually a &lt;em&gt;sh&lt;/em&gt;
  (shell) script and thus my name for this pattern.
&lt;/p&gt;
&lt;p&gt;
  This pattern is not as useful on Windows as Bait-and-Switch because
  so many programs store their environment in the registry. Unix
  programs rely more on environment variables and command-line
  options. The registry is global and any change affects all versions
  of the running program. Environment variables and command-line
  options, however, can be set per-application, so that we can
  simultaneously run multiple copies of a program, each tailored to
  behave different from the others.
&lt;/p&gt;
&lt;p&gt;
  PHP uses environment variables and command-line options for its
  behavior, so the Shell Game pattern works well for it.
&lt;/p&gt;
&lt;p&gt;
  On Windows, you can write the script using any of a number of tools.
  A batch file should be sufficient, but I use &lt;a
  href=&quot;http://www.perl.org/&quot;&gt;Perl&lt;/a&gt;. Perl is fast and also provides
  a solution for properly starting a windowed application based on &lt;a
  href=&quot;http://gtk.php.net/&quot;&gt;PHP-GTK&lt;/a&gt;. You can get a version of
  Perl for Windows from &lt;a
  href=&quot;http://www.activestate.com/Products/activeperl/features.plex&quot;&gt;ActiveState&lt;/a&gt;.
  I use &lt;a
  href=&quot;http://www.indigostar.com/indigoperl.htm&quot;&gt;IndigoPerl&lt;/a&gt;, but
  it hasn&amp;#39;t been updated since early 2005.
&lt;/p&gt;
&lt;p&gt;
  Some Windows scripting tools are very slow, so be careful with your
  choice.
&lt;/p&gt;
&lt;h2&gt;Applying Bait-and-Switch to a PHP installation&lt;/h2&gt;
&lt;p&gt;
  Here&amp;#39;s a screen shot of my PHP installation.
&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;/files/blogs/developer/node91/tale-two-patterns-1.png&quot; alt=&quot;Explorer window screen shot showing my PHP installation&quot; width=&quot;234&quot; height=&quot;325&quot;&gt;&lt;/p&gt;
&lt;p&gt;
  I&amp;#39;ve installed PHP in C:&amp;#92;Program Files&amp;#92;php instead of C:&amp;#92;php. A few
  things to note:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The files with the large green arrows are junction points.&lt;/li&gt;
  &lt;li&gt;There are multiple PHP 4 and 5 installations as well as PHP-GTK. &lt;/li&gt;
  &lt;li&gt;The junction points point to one of the PHP 4, PHP 5 or PHP-GTK installations (typically, the latest, but it can be any version). &lt;/li&gt;
  &lt;li&gt;The &amp;quot;bin&amp;quot; directory is the only directory in the execution path.&lt;/li&gt;
  &lt;li&gt;There is one &amp;quot;pear&amp;quot; directory shared by all PHP versions. When I add a new PEAR package, all PHP versions have access to it. &lt;/li&gt;
  &lt;li&gt;There is one &amp;quot;php5-ext&amp;quot; directory where I place extensions that are independent of the PHP 5 version (currently, I have XCache and XDebug).&lt;/li&gt;
  &lt;li&gt;All the files needed to run PHP are stored in C:&amp;#92;Program Files&amp;#92;php. This includes the php.ini file. Each PHP version has one php.ini file, although I could also have had  one copy shared by all versions. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  Why did I configure PHP this way?
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;I was able to place PHP where I wanted it.&lt;/li&gt;
  &lt;li&gt;I was able to keep the php.ini file with the rest of the PHP installation. &lt;/li&gt;
  &lt;li&gt;I can easily switch from one version of PHP to another.&lt;/li&gt;
  &lt;li&gt;I can quickly install a new version of PHP without deleting my current version.&lt;/li&gt;
  &lt;li&gt;I need to maintain only one version of PEAR.&lt;/li&gt;
  &lt;li&gt;I can simultaneously run CLI versions of PHP 4, PHP 5 and PHP-GTK without any conflicts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  There may be other and better ways to achieve these goals, but this
  approach works well for me.
&lt;/p&gt;
&lt;h2&gt;Playing the  PHP Shell Game&lt;/h2&gt;
&lt;p&gt;
  My Bait-and-Switch configuration wouldn&amp;#39;t work without the support
  of the Shell Game pattern.
&lt;/p&gt;
&lt;p&gt;
  The first step is to place C:&amp;#92;Program Files&amp;#92;php&amp;#92;bin in the execution
  path (Control Panel &amp;gt; System &amp;gt; Advanced &amp;gt; Environment
  Variables). None of the PHP installations should be placed on the
  path.
&lt;/p&gt;
&lt;p&gt;
  Next, create a set of Shell Game scripts that will take the place of
  the php.exe, php-cgi.exe and php-win.exe. Since I use perl, I make
  the process easier by adding PL to the PATHEXT environment variable
  and then running a batch file that contains these two lines:
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
assoc .pl=pl_auto_file
ftype pl_auto_file=&amp;quot;C:&amp;#92;indigoperlperl&amp;#92;bin&amp;#92;perl.exe&amp;quot; &amp;quot;%%1&amp;quot; %%*
&lt;/pre&gt;
&lt;p&gt;
  If you use ActivePerl, you will need to adjust the path to perl.
  Having done all the steps listed so far, you could now write a perl
  script called sample.pl, place it in the bin directory and execute
  it from any directory by typing &amp;quot;sample&amp;quot;. Because we need
  to ensure that the PATH and PATHEXT variables are properly inherited
  by all processes, you may want to log out and back in again.
&lt;/p&gt;
&lt;p&gt;
  Here&amp;#39;s the Perl script I use for the CLI version of PHP5:
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
#!/usr/bin/perl
# Command line (CLI) PHP 5

our $phpMainDir = &quot;C:&amp;#92;&amp;#92;Program Files&amp;#92;&amp;#92;php&quot;;
our $phpDir = &quot;$phpMainDir&amp;#92;&amp;#92;php5&quot;;
our $phpBinDir = &quot;$phpDir&quot;;
our $phpExtDir  = &quot;$phpDir&amp;#92;&amp;#92;ext&quot;;
our $phpBin = &quot;$phpBinDir&amp;#92;&amp;#92;php.exe&quot;;
our $phpMibsDir = &quot;$phpDir&amp;#92;&amp;#92;extras&amp;#92;&amp;#92;mibs&quot;;
our $pearDir = &quot;$phpMainDir&amp;#92;&amp;#92;pear&quot;;
our $pearBin = &quot;$phpMainDir&amp;#92;&amp;#92;bin&amp;#92;&amp;#92;php5.pl&quot;;

$ENV{&amp;#39;PATH&amp;#39;} = $phpDir . &amp;#39;;&amp;#39; . $ENV{&amp;#39;PATH&amp;#39;};
$ENV{&amp;#39;MIBDIRS&amp;#39;} = $phpMibsDir;
$ENV{&amp;#39;PHP_PEAR_BIN_DIR&amp;#39;} = $pearDir;
$ENV{&amp;#39;PHP_PEAR_DATA_DIR&amp;#39;} = &quot;$pearDir&amp;#92;&amp;#92;pear&amp;#92;&amp;#92;data&quot;;
$ENV{&amp;#39;PHP_PEAR_DOC_DIR&amp;#39;} = &quot;$pearDir&amp;#92;&amp;#92;pear&amp;#92;&amp;#92;docs&quot;;
$ENV{&amp;#39;PHP_PEAR_INSTALL_DIR&amp;#39;} = &quot;$pearDir&amp;#92;&amp;#92;pear&quot;;
$ENV{&amp;#39;PHP_PEAR_PHP_BIN&amp;#39;} = $pearBin;
$ENV{&amp;#39;PHP_PEAR_SYSCONF_DIR&amp;#39;} = $pearDir;
$ENV{&amp;#39;PHP_PEAR_TEST_DIR&amp;#39;} = &quot;$pearDir&amp;#92;&amp;#92;pear&amp;#92;&amp;#92;tests&quot;;

system &quot;&amp;#92;&quot;$phpBin&amp;#92;&quot;&quot;, &quot;-c&quot;, $phpDir, @ARGV;
&lt;/pre&gt;
&lt;p&gt;
  The initial set of variable definitions set up a number of
  locations. The code is structured so that this is the only section
  that needs to be altered when creating CGI and CLI versions of PHP
  4, 5 or GTK. GTK has no CGI version, so there are five scripts
  total. If you&amp;#39;d like to see all five versions, you can get them from
  this &lt;a href=&quot;/files/downloads/PHP scripts.zip&quot;&gt;ZIP file&lt;/a&gt;
  (3KB).
&lt;/p&gt;
&lt;p&gt;
  We&amp;#39;re not done yet! If you want to run a CGI version of PHP in
  Apache, you can just point Apache at the appropriate script. If you
  want to run PHP as an Apache module, however, you will also need to use the
  Shell Game pattern for the Apache executable. Start with the same script as
  for the CGI version of PHP you want use, delete the last line and append these
  instead:
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;
our $apache = 
  &amp;quot;C:&amp;#92;&amp;#92;Program Files&amp;#92;&amp;#92;Apache Software Foundation&amp;#92;&amp;#92;Apache2.2&amp;#92;&amp;#92;bin&amp;#92;&amp;#92;httpd.exe&amp;quot;;
system &amp;quot;&amp;quot;$apache&amp;quot;&amp;quot;, @ARGV;
&lt;/pre&gt;
&lt;p&gt;
  Save the result in a file called httpd.pl, place it in the Apache bin directory and
  change the Apache service to
  use &amp;quot;C:&amp;#92;indigoperlperl&amp;#92;bin&amp;#92;perl.exe&amp;quot; &amp;quot;C:&amp;#92;Program
  Files&amp;#92;Apache Software Foundation&amp;#92;Apache2.2&amp;#92;bin&amp;#92;httpd.pl&amp;quot; -k
  runservice. (I edited the entry by using a registry editor&amp;mdash;does anyone
  know a better way?).
&lt;/p&gt;
&lt;p&gt;
  Finally, if you want to run  some of the scripts in the pear
  directory (pear.bat, pecl.bat, phing.bat), you will need to modify
  the scripts to use the Perl scripts rather than directly calling the PHP
  executables. I&amp;#39;ll leave this as an exercise for the reader.
&lt;/p&gt;
&lt;p&gt;
  One caveat: there are some programs (such as IDEs) that will ask you
  for the location of your installed PHP. Then they get very clever
  and try to determine if you have a valid installation. Well, the
  installation is valid, but the program won&amp;#39;t be able to figure that
  out and will refuse to accept your choice. The solutions vary with
  the programs. Sometimes you can tell the program to set up an
  environment for the PHP subprocess. Sometimes you will need to write
  a Shell Game script for that tool. I haven&amp;#39;t encountered many of these types
  of problems and  haven&amp;#39;t found any that I couldn&amp;#39;t work around.
&lt;/p&gt;
</description>
 <comments>http://www.tigerheron.com/article/2007/11/tale-two-patterns#comments</comments>
 <category domain="http://www.tigerheron.com/category/design-patterns">design patterns</category>
 <category domain="http://www.tigerheron.com/category/perl">Perl</category>
 <category domain="http://www.tigerheron.com/category/php">PHP</category>
 <category domain="http://www.tigerheron.com/category/php-gtk">PHP-GTK</category>
 <category domain="http://www.tigerheron.com/category/unix">Unix</category>
 <pubDate>Wed, 28 Nov 2007 23:24:16 +0000</pubDate>
 <dc:creator>developer</dc:creator>
 <guid isPermaLink="false">91 at http://www.tigerheron.com</guid>
</item>
</channel>
</rss>
