Zend Studio 5.5 debugging on OS X via Ubuntu and Parallels

Here's how to get debugging working in Zend Studio Server 5.5 for the Mac. There is no native version of Zend Platform for OS X on Intel Macs yet, so this solution uses Ubuntu on Parallels as an interim solution.

Installing Ubuntu on Parallels

I downloaded Ubuntu 6.10.
In Parallels, new virtual machine, typical installation.
Guest OS Type: Linux.
Guest OS Version: Debian Linux.
Called the Virtual Machine "Ubuntu".
Uncheck "Start guest OS installation".
Clicked on CD/DVD-ROM and changed the Emulation from Use CD/DVD-ROM to Use image file.
Pointed the image file to ubuntu-6.10-desktop-i386.iso
Blicked on Options, then Booting Options.
Changed Boot sequence to have CD-ROM boot first.
Started virtual machine which booted off the image file.
Pressed enter to boot from LiveCD.
Selected U.S. English.
Selected "Erase entire disk".
After installation, selected "Continue using LiveCD"
Powered off virtual machine.
Changed boot sequence to have hard disk boot first.
Booted and logged in.
System - Preferences - Screensaver Preferences, uncheck Activate screensaver.
Tested network connection.

Installing Apache, PHP, and Samba

You can use either the command line or Synaptic Package Manager to install software. If you use Synaptic:
System - Administration - Synaptic Package Manager
Settings - Repositories, check Community maintained Open Source software

I used the command line:

sudo bash
apt-get update
apt-get install apache2-mpm-prefork apache2 libapache2-mod-php5 php5-mysql smbfs

Mounting OS X Filesystem on Ubuntu

Now Apache and PHP are installed. Next, I wanted to mount my OS X filesystem on Ubuntu.

Started Windows File Sharing on OS X.

Firewall, chose New... and selected SMB (without netbios) (445 TCP).

Made the following addition to /etc/smb.conf on OS X (xxx.xxx.xxx.xxx is the IP of the Ubuntu virtual machine).

; allow connections only from the VM
hosts allow = xxx.xxx.xxx.xxx

; verbose logging in /var/log/samba/log.smbd
log level = 3 passdb:5 auth:10 winbind:2

; share my Sites folder
  path = /Users/john/Sites
  read only = no
  browseable = no
  comment = Websites

And I commented out the [homes] section because I'm paranoid.

Now I went to Ubuntu's terminal to mount the share:

mkdir /home/john/sites
mount -t smbfs //my.mac.ip.address/sites /home/john/sites -o username=myosxusername

I tested and doing ls gave me a list of the files in /Users/john/Sites. OK so far.

Serving my Sites directory via Ubuntu

Now I want Apache to serve out of /home/john/sites instead of the default /var/www. (I have no other use for Apache on this VM, so I'm editing the default settings.) So in Ubuntu I said

nano /etc/apache2/sites-enabled/000-default

When I was done it looked like this:

<VirtualHost *>
	ServerAdmin my@email.address
	DocumentRoot /home/john/sites
	<Directory /home/john/sites
	  Options Indexes FollowSymLinks MultiViews
	  AllowOverride All
	  Order deny,allow
	  deny from all
	  allow from
	  allow from my.mac.ip.address

I restarted Apache with apache2ctl restart.

I made a little file called test.php with just <?php phpinfo(); ?> in it. Going to http://xxx.xxx.xxx.xxx/test.php showed the PHP info page. So Apache and PHP are now running.

Installing Zend Platform on Ubuntu

Now it's time to install Zend Platform. I downloaded it from Zend and installed it on Ubuntu:

tar -xvf ZendPlatform-3.0.0Beta-linux-glibc21-i386.tar.gz
cd ZendPlatform-3.0.0Beta-linux-glibc21-i386/
bash ./install

Note that you need to type bash ./install instead of ./install because /bin/bash is really /bin/dash on Ubuntu.

I accepted all the defaults except on the WEB SERVER SETTINGS page, where I entered /home/john/sites in the htdocs field.

I did the Express option. It took several minutes and then completed.

On Ubuntu I started Firefox and went to http://localhost/ZendPlatform and logged in. Only localhost is allowed to do debugging and profiling sessions by default, and I wanted to do that from my Mac (that's sort of the whole point of this exercise!). So I clicked on Configuration and added my host to Allowed Hosts.

Configuring Zend Studio 5.5

Now I needed to configure Zend Studio 5.5 on my Mac to use Ubuntu. In Zend Studio, I added the IP of the Ubuntu virtual machine to Tools - Preferences - debug.

One final step: the debugger on Ubuntu connects back to Zend Studio on the Mac via port 10000. So I opened that port on my firewall.

To test, I chose Tools - Test Debug Server Connection and it reported success.


I now have a single filesystem that I can access via normal HTTP by issuing a request to my Mac, or via debugging by using Zend Studio to issue a debugging request via Ubuntu.

Drupal ninjas will notice that I haven't installed MySQL on Ubuntu. That's because I'll configure the site-specific Drupal settings file to point to the MySQL on my Mac. One database. One filesystem. Two Apache/PHP installs. Sweet.

Note: after trying this for a bit, it seems that Zend Platform's "Dynamic Content Caching" causes Apache/2.0.55 PHP/5.1.6 to segfault. Turning it off in the Zend Platform control panel at Performance - Settings -Dynamic Content Caching made the problem go away.

Update: after more investigation, it turns out that the segfaulting is due to the Zend Optimizer. Commenting out the following line in /usr/local/Zend/Platform/etc/php.ini eliminates the segfaults:


Cultural awareness

I had a chance to sit down and talk with Arun Pereira, author of The Culturally Customized Web Site: Customizing Web Sites for the Global Marketplace recently. He has studied the use of the web by different cultural groups, and come to the conclusion that translation is only a part of the picture; a website should be presented differently to an individualistic American vs. a collectivist Asian. I found that interesting, as I hadn't thought about it much before. Applying that thought to Drupal, the t() function becomes less important, though still essential, and theming becomes more important.


Drupal book

Yowza! Lookee here! And here.

Serving static files with Apache and directories with url aliasing in Drupal using mod_rewrite

A common task is to move a static site to a Drupal site. For example, you might have


You think to yourself, "I'll just leave the image files on the existing filesystem. They don't really need to go into Drupal anyway." So after your content migration is complete your content is in Drupal but you've got the following left in the directory:


What happens when someone tries to go to http://example.com/site/2004/ ?

They get either a directory listing or a Forbidden message, depending on how you have Apache's Indexes directive set for that directory or its parents. But you don't want that! You want it to pass through to Drupal, where you've created a url_alias entry so that all the old URLs, including directory URLs get mapped to Drupal nodes.

Suddenly you come upon a clever idea. Why not just edit the relevant portion of Drupal's .htaccess file to stop Drupal from aborting the rewrite if the path points to a directory?

  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]


  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

All is happy. Happy happy. Your files are being served, Drupal is handling requests with url aliasing, but wait! What's this? Going to


Results in a Bad Request error from Apache. But


works fine. What's going on? It's a long story, but basically the DirectorySlash magic is happening before mod_rewrite can get ahold of the request (because mod_dir runs before mod_rewrite). Here's the answer:

# Fake out DirectorySlash so that Drupal can serve up the directory.
# Don't use [L] here as we pass on to the next rule.
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.+)$ $1/

# Allow apache to serve up existant files directly but pass
# everything else to Drupal, including 'directory' requests
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]

Thanks to noodl in #apache for this solution. chx notes that you need [L, QSQ] instead of [QSA] on your last rewrite rule.

Note that this is an either-or situation. You can't serve some former-directories-which-are-now-URL-aliases from Drupal and leave other directories with index.html files in them and have Apache serve those. When you try to hit http://www.example.org/somedirectory/ you will not get http://www.example.org/somedirectory/index.html; instead you will get Drupal's 404 handler.



Subscribe to RSS - Drupal