Archive for June, 2006

A Networked Virtual Hosting Party on Mac OS X

Wednesday, June 28th, 2006

There are plenty of articles on setting up virtual hosts on Mac OS X but I’d not found a simple one that showed you how to set up named virtual hosting that could be read across your LAN. The aim for me is to be able to type in e.g., http://myparty/, in any browser on our small local network and get to the locally hosted site.

My requirements are pretty minimal, needing only to have one or two other Macs running OS X (Tiger) access the development server. I’m not going to go into too much detail, partly as I’m too lazy, but also as your setup and needs will be different to mine anyhow. Instead I’ll just give a general run through and point to further reading.

Decide where we’re going to host the party

The first thing we need to establish is the main server which requires that that server have a static IP address. In my case this involved going to System Preferences > Network > TCP/IP and setting Configure IPv4 to “Using DHCP with manual address”. In that same dialog I then set an IP address of 192.168.1.100 and clicked “Apply Now”. That now means that this machine has a consistent address that others on the network will refer to.

Tell everyone where the party is

When the other OS X machines on the network type http://myparty/ in their browsers the first thing their machines do is check in the file /etc/hosts to see if there’s an IP address that matches “myparty”. If there isn’t things won’t go very far. So if you take a look at my one…

127.0.0.1   localhost
127.0.0.1   myparty
255.255.255.255 broadcasthost
::1             localhost

…you’ll see that http://myparty/ maps to my localhost IP address 127.0.0.1 which is fine as my machine is the host. In order that the other machines know where to go for “myparty” we have to edit their /etc/host files to send requests to the static IP address I set earlier:

127.0.0.1   localhost
192.168.1.100   myparty
255.255.255.255 broadcasthost
::1             localhost

Set up the virtual hosts

Now that everyone knows where myparty is being hosted we need to prepare. First you need to edit the Apache web server configuration file httpd.conf which by default lives here /private/etc/httpd/httpd.conf. I’ve installed Apache2 in /usr/local/ which is the more generally expected place for it to be and since this is my notepad I’m going to go with that. So first I need to open httpd.conf as the all powerful root user so I need to type…

$ sudo vim /usr/local/apache2/conf/httpd.conf

…whereas you could go…

$ open -a TextWrangler.app /private/etc/httpd/httpd.conf

…or whatever your personal setup/preference is. Once open you might like to use this little tip I picked up of having your specific settings in a separate file so e.g. at the end of my httpd.conf I have the following…

include /Users/nicklo/Sites/apacheconf/users

…that points to a directory which contains the file nicklo.conf. Inside that file are my virtual host settings. Having those settings separate from the main httpd.conf makes them more easy to backup along with all my other projects. It also potentially keeps them out of harms way in case a Software Update decides it’s time to fiddle with your httpd.conf file.

In keeping with the example my nicklo.conf could then have the following…

NameVirtualHost *:80

<Directory "/Users/nicklo/Sites">
    Options Indexes MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

<VirtualHost *:80>
    ServerName 127.0.0.1
    DocumentRoot /Users/nicklo/Sites
</VirtualHost>

<VirtualHost *:80>
    ServerName myparty 
    DocumentRoot /Users/nicklo/Sites/myparty
</VirtualHost>

You’ll notice the settings specific to “myparty” are the last ones. These basically say if you get any requests for “myparty” on any IP address (* wildcard) via port 80 then send them through to /Users/nicklo/Sites/myparty.

Party on!

All that’s left now is restart Apache via System Preferences > Sharing > Services > Personal Web Sharing or…

$ sudo apachectl graceful

…which is actually better as it will at least tell you if there are any issues rather than just sit there.

Actually, we we still have to build the myparty website/web application in /Users/nicklo/Sites/myparty/public_html but hey, that’s the easy part right?!

Now in an even more perfect world I would be able to tell you how to set up a proper DNS Server on the host machine, that would replace the somewhat hacky need for individually configured /etc/host files. However, right now I’m just too stupid and honestly, a bit scared, to even attempt that. If anyone can give me a simple and if possible metaphorical run through I’d be very interested.

Further Reading

Virtual Hosting on Mac OS X I need to give credit to the comments by “Mats” on that page for much of my setup above.

Staging websites on Mac OS X

Virtual Hosts for Dummies

Location, Location, Location: Tips for Storing Web Site Files

Apache Virtual Host documentation

VirtualHost Examples

Custom View Helpers in Zend Framework

Monday, June 26th, 2006

The Zend Framework Manual describes View Helpers like so:

“In your view scripts, often it is necessary to perform certain complex functions over and over; e.g., formatting a date, generating form elements, or displaying action links. You can use helper classes to perform these behaviors for you.”

Currently the framework (version 0.1.3) includes a small selection of form helpers which will no doubt expand as it matures. For now I’m more interested in the ability to add custom helpers for specific project use. The first thing I did was to set up the same directory structure as Zend_View_Helper as is suggested when subclassing controllers:

library/
    Zend/
        View/
            Helper/
    MyProject/
        View/
            Helper/

Having my project specific helper files in library/MyProject/View/Helper/ will make it easy to keep them separate from Zend core updates.

The next step is to tell Zend_View to look in the custom helper directory as well as the default Zend helper directory. This just requires adding the new helper path to the Zend_View object I created in the public_html/index.php file:

$view = new Zend_View;
$view->addHelperPath('MyProject/View/Helper');

Cautionary Note (* see update below)

The above is actually a bit of a fiddle to get working if you decide like I did to use a relative path to your helper files. I had set…

set_include_path( /home/exciting_zfw_site/library/ );

…pointing to the main Zend library directory, however, Zend_View_Abstract:: _loadClass() uses is_readable() as a check before loading any helper or filter files like so…

if (is_readable($dir . $file)) {
    include $dir . $file;

    if (! class_exists($class, false)) {
        $msg = "$type '$name' loaded 
                        but class '$class' not found within";
        throw new Zend_View_Exception($msg);
    }

    return $class;
}

…and since is_readable just ignores include paths, your new helper files won’t be found. This is currently listed as a bug but for the moment I simply changed…

if (is_readable($dir . $file)) {
    include $dir . $file;

…to…

if (include $dir . $file) {

…and it worked fine. Portability was the reason I wanted to keep the paths relative as I move files from a development server to the live server. It’s much easier to keep as few path configuration settings as possible.

The next step is pretty well documented in the manual but for the sake of completeness I’ll keep going. Create a new helper file:

class Zend_View_Helper_DoStuff {

    public function doStuff()
    {
        return 'Hello to you all';
    }
}

Another Cautionary Note

Something that caught me out was that the new helper class must be called Zend_View_Helper_YourNameHere rather than MyProject_View_Helper_YourNameHere which seems a little odd considering it’s position in the directory structure I mentioned before. While logically it is a Zend_View helper class, it will be kept with other subclassed files with your own “namespaced” class names under the MyProject directory so it seems to break a convention.

Ready to use

After saving the new helper file in MyProject/View/Helper/DoStuff.php it should be available to use in your view scripts like so:

<?php echo $this->doStuff(); ?>

When writing helper classes the key points to initially getting them to work are the naming conventions as illustrated by my doStuff example:

  1. Class name must be Zend_View_Helper_DoStuff
  2. The class must contain a public function doStuff()
  3. The file must be save as DoStuff.php

As mentioned in my post on getting to know Zend_View elements of the above may well change as development continues.

Further Reading

View Helpers in the Zend Framework Manual

* Update

Forget the above hack…

if (include $dir . $file) {

…as it will produce warnings as Zend_View_Abstract::_LoadClass() attempts to include the doStuff file from any other path in the _path stack. Instead the only solution I’ve found to currently work is to specify a relative path like so:

$view->addHelperPath('../MyProject/UW/View/Helper');

File browsing in Vim

Wednesday, June 21st, 2006

Well-heeled Vim users will no doubt see the following as being pretty obvious. For anyone else like me fumbling around with Vim to the point of giving up, I hope this at least saves you the time I spent until the small hours of the morning!

The way I used to think

Coming from working with text editors like jEdit which, like others, has a file browser in a split pane, I had been trying to reproduce this in Vim.

Vim split into 4 panes

However, since upgrading to Vim 7, this had been causing irritations, like this routine to open a file:

  • Select a file in the left pane.
  • Click in a window in the right pane to indicate that was the one to open it in.
  • Go back to the file in the left pane and Shift-p to open it.

Forgetting to select the window to open it in meant it would open in the left pane instead, which was supposed to be my file browsing pane.

Not only that but for whatever reason I was getting an odd refresh when I moved to another application and back to Vim. This refresh was annoying enough to have me spend time reinstalling netrw, attempting to compile Vim for myself (which failed) and even taking time to try out Textmate.

All in all I was getting pretty fed up and was even converting the Euro to Aussie Dollar to see if I had enough pocket money to buy Textmate. Luckily, the stubbornness of anyone who has put the time into learning Vim wouldn’t go away and I stopped to have a look at the new tabs in Vim 7. It was then that I realised I’d been thinking about this all wrong…

Vim is about modes

My mistake was to think of any window in Vim as having a specific role and ignoring vim’s modal nature. I realised that file browsing was always there in the background as I edited a file and I didn’t need to have windows specifically assigned to file browsing.

The joy of :Ex (very poor, I know!)

The magic lies in the fact that the file browsing functionality of netrw is following you around as you go. For example, if I open …/Sites/zend_framework/library/Zend.php in a window…

Vim split horizontally with files

…and then hit :Ex I will be in that files directory…

Vim split horizontally with netrw in top

However, if I open a file from another directory in another window hitting :Ex for that window will bring up it’s directory. This then allows me to have a contextual file browser available at any time without having to move my hands from the keyboard.

Admittedly this is not exactly a nirvana attaining moment of enlightenment, but it’s certainly one of those “Aha!” moments that reinforces your faith in your tools and the time spent learning them.

Further Reading

Beginner’s guide to Vi Improved (vim)

Cheap rounded corners

Thursday, June 15th, 2006

I like the fact that Jon Hicks, who is well known for designing, amongst other things, the logo for the Firefox web browser, talks about using a cheap rounded corner punch on his business cards in his New Business Cards are here! journal entry.

I’d ruled out rounded corners as being cost prohibitive but this is an obvious and simple workaround. Searching locally (in a brief Google Australia search) I’ve so far come up with ones like Fiskars’ photo corner punch which is not quite what I’m after. I’ll keep looking…

Getting to know Zend_View

Saturday, June 10th, 2006

Like many other PHP developers I’m keeping an eye on the progress of the Zend Framework. It’s currently still in the very early stages of development but is nonetheless worth “getting to know”. These are some notes from a play around with the current View functionality.

I generally use a nested layout template file with PHP embedded in HTML. Variables are assigned by a controller file so a layout template may look like this “main_layout.php” file:

<body>
    <?php include 'modules/header.php'; ?>
    <?php include $page; ?>
    <?php include 'modules/footer.php'; ?>
</body>

After some much appreciated help from Paul M Jones and Simon Mundy on the Zend Framework General List, I now have the following three methods of doing the same in the Zend Framework.

Use Zend_View::_script()

Include the additional views directly in the layout using the Zend_View::_script() method:

<body>
    <?php include $this->_script('/modules/header.php') ?>
    <?php include $this->_script( $this->content ); ?>
    <?php include $this->_script('/modules/footer.php') ?>
</body>

Use assigned variables

Assign the additional views in the controller file and then use the variables in the layout:

In the view controller:

$view->header = $view->render('modules/header.php')
$view->content = $view->render('page.php')
$view->footer = $view->render('modules/footer.php')

In the view script:

<body>
    <?php echo $this->header; ?>
    <?php echo $this->content; ?>
    <?php echo $this->footer; ?>
</body>

Use Zend_View::render()

This seems to be the “proper” solution as it makes full use of the _file stack in render().

Call Zend_View::render() from within the view script:

<body>
    <?php $this->render('modules/header.php') ?>
    <?php $this->render( $this->content ) ?>
    <?php $this->render('modules/footer.php') ?>
</body>

The above three solutions all require a final call to render the whole layout in the view controller file, e.g.:

echo $view->render( 'layouts/main_layout.php' );

Cautionary Note

Since the framework is currently in preview release stage it’s possible that the above may change soon after posting this (though I suspect probably not much if at all).

Update (8th November)

As of the latest SVN checkouts Zend_View::render() does not echo the output so you will need to use…

<?php echo $this->render( $this->content ) ?>

Ranking on Yahoo! Australia

Thursday, June 1st, 2006

Further to my Google, PageRank, search results placing post and yet again for the sake of posterity and curiosity I have to record a further oddity in our search engine rankings.

We are currently second place for “ingredients australia” in Yahoo! Search, Australia and NZ and since the addition of this relatively minimal amount of text…

Web Design and Development

Projects we are and have been working on include; underwater.com.au, Byron Bay Dive Centre, Whale Watching Byron Bay, Marine and Coastal Community Network, Marine Passions, PacMab, Melaleuca House, Byron Bay Accom (In conjunction with Nextwave Media).

While there is not much here at the moment you’re welcome to take a look at Sandra’s or Nick’s notes.

Contact Ingredients Australia, PO Box 1437, Byron Bay, NSW 2481, Australia | contact@ingredients.com.au

…we have moved up to 3rd place in Google for the same search.

Once again it is not especially significant that we get the rankings for what may be an obscure search term (Although we have already had hits from searches like “ingredients in australia”). It is however an indication that the idea of aiming for some kind of niche has validity at least for search engine placement. If you try and search for “web design and development australia” I doubt we’d appear after thirty pages of results.

Almost as soon as we connected up the wiring for ingredients.com.au we began receiving mistaken emails from food and general ingredients suppliers. All that was based simply on our using the keyword “ingredients”.

Anyway, for now I’m just keeping an eye on the changes and clearing up the inevitable junk email being sent to our newly popular contact@ email address!