Using Vagrant with WMware Fusion: vagrant-vmware-fusion

0 comments

Posted on 12th May 2014 by Bart McLeod in Web development

This is part 1 of my series on Ansible provisioning for Vagrant running VMware.

In this post I will describe how things are supposed to work first time right when you run a VMware virtual machine using Vagrant. If you are interested in what could go wrong, or if you encounter errors yourself, you are advised to read [todo: I will follow up with a post on what went wrong].

Please note that Vagrant is most widely used with VirtualBox. If you are using Vagrant with VirtualBox and you are happy with that, there is no reason why you should try VMware.

The plugin: vagrant-vmware-fusion

While Vagrant works with VirtualBox by default, you need a plugin for it to work with VMware. There are two VMware providers available, one for VMware Fusion (used on the Mac) and one for WMware Workstation (used on Windows and Linux). The provider plugin that I will be using is called vagrant-vmware-fusion.

VMware and the vagrant-vmware-fusion plugin both are not free, unlike VirtualBox.

My software environment

If you made it till here you might be interested in actually following along, so I might as well tell you what software I am using: I’m on Mac OS X Mavericks (version 10.9.2). My Vagrant is at 1.5.4 and my vagrant-vmware-fusion plugin is version 2.4.0. My VMware Fusion installation is at version 6.0.3.

In case you haven’t got Vagrant installed, you must install it using the packaged installer, which you can find here: http://www.vagrantup.com/downloads.html

VMware Fusion can be downloaded here: http://www.vmware.com/products/fusion/

The vagrant-vmware-fusion plugin can be purchased here (there is no trial version): http://www.vagrantup.com/vmware

Installation

The software installations are straightforward, except for the plugin. It is done on the command line, after you have installed both Vagrant and VMware Fusion. Make sure you have the vagrant command by typing

vagrant --version

In my case, this outputs:

Vagrant 1.5.4

Because there is no trial version of the plugin, you have to purchase a license before you can continue. Although there is no trial period, purchasing the license is risk-free. Should you not be satisfied with your purchase, a single e-mail to its vendors will suffice to get your money back and have the license revoked.

All you will download after purchasing the license is a license file. Next, you may proceed installing the plugin by following the installation instructions. Make sure that you keep the license file somewhere and make notes of it.

To verify if the plugin is installed, type:

vagrant plugin list

In my case that yields:

vagrant-login (1.0.1, system)
vagrant-share (1.0.1, system)
vagrant-vmware-fusion (2.4.0)

Adding and starting your VM

Now that you are all set, you will need a virtual machine to bring up using the famous vagrant up command. The good news is you can download a base box from the vagrant website: I downloaded the Ubuntu precise64 VMware box base box for vmware.

Place the base box somewhere on your file system and cd into that directory on the command line. Your next step is to add the box to Vagrant:

vagrant box add --name=precise64_vmware  --provider=vmware_fusion ./precise64_vmware.box

This should give you the following output (except for the directory where you have placed the base box):

==> box: Adding box 'precise64_vmware' (v0) for provider: vmware_fusion
    box: Downloading: file:///Users/bartmcleod/vagrant-vmware-fusion/blog/precise64_vmware.box
==> box: Successfully added box 'precise64_vmware' (v0) for 'vmware_fusion'!

And then:

vagrant init

[Edit: July 12, 2014] I received feedback from Jim Preston, that as of Vagrant 1.6.8 you need to include the box name with the init command, like so:

vagrant init precise64_vmware

I haven’t yet tried this myself, but I thought it would be wise to include it here, since otherwise you might get stuck on this bit.[/Edit]

[Edit: July 20, 2014]I installed Vagrant 1.6.3 and verified whether the name of the box was needed with the init command and in my case it wasn’t needed.[/Edit]

Which results in:

A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.

And finally:

vagrant up --provider=vmware_fusion

Do not forget the –provider flag. You may omit it later, but the first time you bring up your box, you need it. The above command will yield the following output if everything went ok:

Bringing machine 'default' up with 'vmware_fusion' provider...
==> default: Cloning VMware VM: 'base'. This can take some time...
==> default: Verifying vmnet devices are healthy...
==> default: Preparing network adapters...
==> default: Starting the VMware VM...
==> default: Waiting for the VM to finish booting...
==> default: The machine is booted and ready!
==> default: Forwarding ports...
    default: -- 22 => 2222
==> default: Configuring network adapters within the VM...
==> default: Waiting for HGFS kernel module to load...
==> default: Enabling and configuring shared folders...
    default: -- /Users/bartmcleod/vagrant-vmware-fusion/blog: /vagrant

When you’re done:

vagrant halt

That’s it! Now you know how to use Vagrant and VMware together. If you would like to know how to provision your new box using Ansible, then please read my next post [todo].

Ansible provisioning for Vagrant running VMware

0 comments

Posted on 9th May 2014 by Bart McLeod in Web development

Introduction

This is the beginning of a series of posts about using Vagrant with WMware virtualization and Ansible provisioning. That’s three technologies in one sentence. Combining technologies is always challenging, especially if you have little to no experience with some of them. This means that things will go wrong many times during my research and it will be far from a smooth experience. Although I would have loved to describe my adventure in chronological order, this would be annoying, as you would most certainly lose track of how things are supposed to work.

So instead of mixing how things went wrong with how things should have worked the first time, I will present you with posts describing my project as if everything went right the first time. For those interested in my personal struggle, the amount of effort involved and especially those encountering errors themselves, I will post about what went wrong separately.

The idea and the technologies

Let me start with a brief explanation of each technology and my project.

Vagrant

Vagrant is a technology that allows you to script the installation and configuration of a virtual machine. Because it’s scripted, it’s repeatable, distributable and it can be kept under version control. The major benefits are experienced in development, where you can keep multiple development environments on a single host machine (your development laptop or whatever you use). You can share these environments with your team and use version control to keep them in sync between you and your team mates. Of course, you will build your vagrant setup so that it resembles your production environment as close as possible. A machine is built from a base box, which is installed and configured using a provisioner. This can be repeated over and over again, but once provisioned there is no need to do it all again: Vagrant will notice if you made any changes to your provisioning script. Vagrant is most widely used with VirtualBox, which is a free (as in beer) virtualization tool. Base boxes can be obtained as downloads from the vagrant website and other sources you might decide to trust.

VMware

VMware is a virtualization brand, like VirtualBox.  Virtualization allows you to run a computer (the guest) inside another computer (the host). Virtualization allows you to have as many machines on your host machine as you have room for in terms of disk space. You run them when you need them and shut them down or suspend them when you’re done. You may run multiple virtual machines at the same time, as long as physical memory is available. While virtualization by itself allows you to have multiple different development environments on the same machine, it is not so easily shared and distributed as when combined with Vagrant. With Vagrant, you only need to share the scripts, not the machines. Also, you cannot keep virtual machines under version control, as they are mostly binary representations of disk states.

VMware is a drop-in replacement for VirtualBox and it’s not free. On windows and linux, you use WMware Workstation, while on the Mac, you use VMware Fusion. Vagrant uses a plugin, vagrant-vmware-fusion, to work with VMware on Mac OSX. The vagrant-vmware-fusion plugin is also not free.

Ansible

The most commonly know provisioners for Vagrant are shell, Chef and Puppet. Shell means just basic shell commands that you would type yourself if you are doing manual installation and configuration. The other two are sophisticated provisioning systems with quite a learning curve. Ansible is a provisioning tool like the latter two, but it is simple and powerful at the same time.

My project

There is a lot of buzz around Vagrant. The first time I saw someone use it was during MidwestPHP in March 2013, where Chris Tankersly used it in his presentation. Like everyone else mentioning Vagrant he talked about it rather casually, saying that ‘vagrant up’ gives you a complete development environment with almost no effort. Whenever I hear someone talk about a new technology in such a way, I get suspicious. In my experience, good things rarely come with ‘almost no effort’. I was quite convinced, that if at that moment I would type ‘vagrant up’ in some terminal window on my machine, it would give me absolutely nothing. Every tool needs the right context to work: More about that later in this series.

Why VMWare?

On my Mac, with OSX Mavericks installed, I use VMware Fusion for virtualization. Because I come from a Windows history, I keep a Windows 7 VM, so that I can still run applications that I purchased for Windows. At the time when I started using virtualization I was still working on Windows and used VMware Workstation. When I moved to OSX, VMware Fusion was the promoted choice and I didn’t know of the existence of VirtualBox in the first place. In addition, when I started using Vagrant about half a year ago, I wasn’t completely satisfied with how VirtualBox worked. This was mostly due to unfamiliarity with it’s UI and some usability issues I was experiencing with it, like not being able to cancel a dialog. For my daily work however, I do work with VirtualBox, because my team uses it and I want to be able to share their Vagrant configuration and base box. Also, I did not have the time to become familiar with using the vagrant-vmware-fusion plugin when the project started at a fast pace. In spite of the fact that by now, VirtualBox is doing a good job in virtualizing my two different development environments, I still want Vagrant to work with VMware fusion. I bought all the licenses, I like the UI and the overall stability of VMware, so now I want to work with it.

With Ansible, we get to the most interesting part of this series. With Ansible, I have no experience at all. It is a configuration management system that you can use to spin up machines in the cloud, or spin up your own local virtualized development environment. As such, you can use it with Vagrant. Ansible allows me to skip learning supposedly more complicated systems like Chef and Puppet, while at the same getting to understand a sophisticated tool. I fell in love with Ansible during a presentation by Jeremy Coates at PHP Benelux 2014. His enthusiasm was as obvious as contagious.

So, because Vagrant is a cool technology that everybody uses for good reasons and because I like VMware and because I am interested in learning Ansible, I decided I wanted to use them all three together. While there is excellent documentation available on each of these technologies, it’s not easy to find a step by step guide on how to use them together, so I decided to fill that gap with a series of posts. Keep an eye on this blog over the next month to read them all.

To start with using Vagrant and VMware together, read part 1 of this series: Using Vagrant with WMware Fusion: vagrant-vmware-fusion

Setup logging in application.ini for Zend Framework 1

0 comments

Posted on 10th December 2012 by Bart McLeod in Web development |Zend Framework

Today I had to look it up again: how to quickly setup logging for a Zend Framework 1 application. To make it easy for myself to find it again, should I ever need it, I will post it here.

A log is a resource that ZF 1 can load using a predefined resource plugin. That means that we can be lazy: If we setup a logger as a resource called ‘log’ in application.ini, we can use it.

But then, when I started writing this, I stumbled on this blog post, that does exactly the same thing, so just read it here:

http://blog.niklasottosson.com/?p=1158

What this post doesn’t show you is how to add logging to firePHP in the same go:

 resources.log.firebug.writerName = "Firebug"
 resources.log.firebug.filterName = "Priority"
 resources.log.firebug.filterParams.priority = 7

Logging with FirePHP in ZF2

9 comments

Posted on 10th October 2012 by Bart McLeod in Zend Framework |ZF 2

Yesterday I wanted to set up logging to FirePHP in CuddleFish (my pet project business framework). I thought it would be easy, and looking back, it is very easy. Before I figured out how to set it up, it was not so easy, so I’d better blog about it to remind myself of how it’s done.

First of all, you have to set up FirePHP. You can download it from the FirePHP website or install it using pear:

pear channel-discover pear.firephp.org
pear install firephp/FirePHPCore

Next, in the Module.php file of your module, you can add a service that provides the configured logger:

// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;
use \Zend\Log\Writer\FirePhp\FirePhpBridge;

// Note that I place FirePHPCore in vendor
require_once 'vendor/FirePHPCore/FirePHP.class.php';

// further down
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                // [..] other factories for other serivces left out
                'log' => function($sm) {
                    $log = new Logger();
                    $writer = new FirePhpWriter(new FirePhpBridge(new \FirePHP()));
                    $log->addWriter($writer);
                    return $log;
                },
            ),
        );
    }

Simplifying it

In fact, since we require_once the core FirePHP class, there is no need to pass it to the constructor of the writer using the bridge. I only came to realize this while writing this post. When the FirePHP class exists, it will be used automatically by the writer. So the simplified code becomes:

// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;

// Note that I place FirePHPCore in vendor
require_once 'vendor/FirePHPCore/FirePHP.class.php';

// further down
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                // [..] other factories for other serivces left out
                'log' => function($sm) {
                    $log = new Logger();
                    $writer = new FirePhpWriter();
                    $log->addWriter($writer);
                    return $log;
                },
            ),
        );
    }

Now if you need the log somewhere, say in a controller, you can pass it in using the factory for the controller and call:

$this->info('It works');

Alternatively you can call getServiceLocator() inside the controller to get the ServiceManager and get the log instance:

$this->getServiceLocator()->get('log')->info('Will work equally well');

There is however a downside to this: If you have a lot of calls to the log, it is more code to type than just calling $this->log->info(‘something’);

If you have an initalizer in your controller, you can set the log there:

// inside initializer
$this->log = $this->getServiceLocator()->get('log');

If you use a factory to create your controller, you can add a method setLog() to your controller:

public function setLog($log)
{
    $this->log = $log;
}

The factory can be a closure in the controller configuration, like we did for the log:

    public function getControllerConfig()
    {
        return array(
            'factories' => array(
                'index' => function($controllers) {
                    $sm = $controllers->getServiceLocator();
                    $controller = new Controller\IndexController();
                    $controller->setLog($sm->get('log'));
                    return $controller;
                },
            ),
        );
    }

Now the log is available as $this->log right after instantiation of the controller.

 

Unit testing Zend Framework 1.x with PHPStorm

0 comments

Posted on 15th April 2012 by Bart McLeod in Web development |Zend Framework

, , , ,

In case I ever forget, to easisly install the latest phpunit, follow the manual blindly, which means to:

go-pear
pear update pear

At the moment of writing, the above yields an error, complaining about Strutures\Graph.php. The solution is to get the Structures_Graph tar by typing:

pear install Structures_Graph

This will yield an error once more, but you can see where the tar file is downloaded to. You can extract it manually and then copy the Structures directory into your PEAR directory (at the same level as the ‘Console’ directory). After that, you can

pear update pear

Once pear is up to date, configure it to auto discover channels. This is really important! And the next step is install phpunit.

pear config-set auto_discover 1
pear install --alldeps phpunit/PHPUnit

NOTE that for ZF 1.x you still need to specify the correct version of phpunit:

pear install --alldeps phpunit/PHPUnit-3.5.15
PHPStorm context menu detail

Run option in PHPStorm context menu

Last night I wanted to run a unit test for Zend Framework 1.11. I only recently switched from ZendStudio to PHPStorm and I didn’t yet run any PHPUnit unit tests from inside PHPStorm. I always liked running unit tests in ZendStudio, although this wasn’t always easy to setup, so I feared the new learning curve ahead of me. This wasn’t quite as hard as I imagined: like anything else in PHPStorm, it is easy to find and easy to setup. Just in case I forget how it all works, I write this down.

First of all, there are some differences in how PHPStorm and ZendStudio approach unit testing. In ZendStudio, you have to select ‘run as PHPUnit test’ from the context menu. The context menu is what you see when you click your right mouse button on the code you are editing and that is also the file that contains the unit test that you want to run. In PHPStorm, you just choose ‘Run’ from the context menu (see image).

Another option in the PHPStorm context menu is to setup a run configuration for the file. Once it is setup,  you will be able to select the run configuration from the menu bar and you get the opportunity to edit it as well. When setting up a run configuration, you can define the scope: Directory, Class,  Method or As Defined in the Configuration File, which is absolutely a great feature.

One of the things that will go wrong in ZendStudio is that you forget to include PHPUnit on the include path of your project, in which case ZendStudio cannot find the PHPUnit library. It will not tell you, it will just not run. PHPStorm will tell you it could not connect a testreporter if it can’t find PHPUnit. This is the exact error message: “Unable to attach test reporter to test framework or test framework quit unexpectedly”. In that case, you don’t have installed PHPUnit for the php version PHPStorm is using. In case you have several versions of php available on your system, you can configure which one PHPStorm should use. This is much the same as it is in ZendStudio. See the next image for how it is done in PHPStorm. In the same dialog, you can add entries to the include path for your php version. Make sure you add the path where PHPUnit lives (in my case that is “/Applications/MAMP/bin/php/php5.3.6/lib”).

Setting the php version in PHPStorm

Setting the php version in PHPStorm

One nifty little feature here is the little ‘i’ button, that brings up all ini settings if you click it. These are editable, but I did not check if that actually takes effect. To change the interpreter, you click the button with the three dots to select the path to your php. By clicking the ‘+’ button you can add entries to the include path.

Setting up PHPUnit

PHPUnit can be easily installed using PEAR. I once had this setup, but because I alwasy used ZendStudio, I had no need to keep it up and running an my installation had been broken by installing MAMP Pro over MAMP. I remembered that installing PHPUnit was a pain, because the pear installer that had shipped with MAMP was to old for the PHPUnit installation. Luckily, that problem did not re-occur.  I could easily install phpunit with pear, but I did no longer have the pear command. I broke that along with the same MAMP Pro installation.

Setup the pear command

To get the pear command back, the directory where it is located must be on your computers PATH. This is not the php include_path, but the PATH environment variable of your system. The PATH variable is set in your .profile file, that is located in your home directory. In my case, the home directory is /Users/bartmcleod. To edit the profile file, just open up terminal and type:

$s sudo vim /Users/bartmcleod/.profile

Inside .profile you will see something like:

 12 export PATH=/opt/local/bin:/opt/local/sbin:$PATH

I changed that to:

 12 export PATH=/opt/local/bin:/opt/local/sbin:/Applications/MAMP/bin/php/php5.3.6/bin:$PATH

to include the location where pear installs it’s commands. Once you have done this, you can proceed to install PHPUnit and you will also have the phpunit command available, since that goes into the same directory.

Installing PHPUnit for Zend Framework 1.x

You will think that installing PHPUnit with PEAR is easy: something along the lines of ‘sudo pear install phpunit’. Of course I tried that first and it executes and everything looks fine, except it didn’t really work for me. Then I found I had to type ‘sudo pear install phpunit/PHPUnit’. That worked, but it didn’t work with Zend Framework 1.x unit tests. They do not support PHPUnit 3.6. I found that the most recent version they support is PHPUnit 3.5.15. So I tried to uninstall phpunit and subsequently install that specific version, using the instructions I found here: http://stackoverflow.com/questions/1569012/how-to-install-an-older-version-of-phpunit-through-pear

In the same article however, it is specifically stated that to install 3.5.15, you have to uninstall separate phpunit components one by one, before installing the specific older version. If you don’t, pear will automatically detect that these components need the latest version and install that instead of the requested older version. This is annoying and hard to believe when you see it happen on the commandline. I had to try several times before I actually believed what was going on.

Because I did not want to type all the commands or paste them one by one, I just created two batch scripts. One to uninstall the latest versions and one to install the 3.5.15 versions.

Uninstall:

sudo pear uninstall phpunit/PHPUnit
sudo pear uninstall phpunit/DbUnit
sudo pear uninstall phpunit/PHP_CodeCoverage
sudo pear uninstall phpunit/File_Iterator
sudo pear uninstall phpunit/PHPUnit_MockObject
sudo pear uninstall phpunit/Text_Template
sudo pear uninstall phpunit/PHP_Timer
sudo pear uninstall phpunit/PHPUnit_Selenium
sudo pear uninstall pear.symfony-project.com/YAML

Re-install 3.5.15:

sudo pear install pear.symfony-project.com/YAML-1.0.2
sudo pear install phpunit/PHPUnit_Selenium-1.0.1
sudo pear install phpunit/Text_Template-1.0.0
sudo pear install phpunit/PHPUnit_MockObject-1.0.3
sudo pear install phpunit/PHP_Timer-1.0.0
sudo pear install phpunit/File_Iterator-1.2.3
sudo pear install phpunit/PHP_CodeCoverage-1.0.2
sudo pear install phpunit/DbUnit-1.0.0
sudo pear install phpunit/PHPUnit-3.5.15

The stackoverlow article from the above url gives more details and use cases that might apply to your particular situation, so if this set of commands doesn’t work for you, make sure you check the original post.

If unit testing with PHPUnit still doesn’t work from inside  PHPStorm

I upgraded to PHPStorm 4 and I tried to repeat the above procedure, and it didn’t work immediately. I kept getting the “Unable to attach test reporter to test framework or test framework quit unexpectedly” error message. I had to change the interpreter from php 5.4 (that ships with PHPStorm apparently) to php 5.3 local, like I had it set up before. I verified that the correct phpunit version is still installed, but with no luck. While trying again and again I found it seems to matter where you click inside the code. Clicking on a single test function will allow you to test only that function, while clicking on the class name will allow you to run the entire test class.

display_errors should be on (obviously)

While that is a nice feature, it doesn’t cover all the cases where unit testing doesn’t work. In one case for example, I had display_errors set to ‘off’ (accidentally) and if you do, you get the same error message  (“Unable to attach test reporter to test framework or test framework quit unexpectedly”) while you see nothing else that could help you detect the error.

Mind your slashes!

In yet another case with the same error message, I found I included the test superclass using windows (back)slashes as directory separators. Apparently, I had been developing those tests on a windows box and didn’t use forward slashes. The error message you get in that case is “Warning: require_once(PHPUnit\Framework\TestCase.php): failed to open stream: No such file or directory in …”. You might not notice immediately that the wrong  slashes are used if you run the tests on *nix or a Mac.

Zend Framework 2.0 patterns

0 comments

Posted on 27th July 2011 by Bart McLeod in Zend Framework

Today I came across a presentation by Matthew Weier O’Phinney on slideshare, that I just do not want to forget about. Because bookmarks tend to disappear when I switch browsers and because I create bookmarks but rarely look at them a second time (using 10+ different browser installations and having bookmarks spread all over) I decided to embed the presentation on my blog, so that it sticks. So here it comes:

I have to remember to try this Depency Injection phenomenon I hear so much about lately.

Zend_Tool and Model generation

0 comments

Posted on 12th July 2011 by Bart McLeod in Zend Framework

Zend_Tool is a command line tool that helps you setup a Zend Framework MVC application. You can also use it after you have set up your application to add controllers, actions, views, configuration and models. Since I use Zend Studio for development, I am used to the integrated version of Zend_Tool. This means that if you set up a Zend Framework MVC application as a new Zend Studio project, you will have menus available that let you add things like controllers and actions.

This is really nice of course, but the nature of the tool, that is command-line by birth, makes that I would like to be able to use it from the command-line too. (more…)

Enabling syntax highlighting

3 comments

Posted on 15th June 2011 by Bart McLeod in Web development |WordPress

, , , ,

UPDATE

There is a newer version of the plugin that I wrote about in this post. It’s functionality is available by default to wordpress.com users. The new plugin is called SyntaxHighlighter Evolved.

SyntaxHighlighter Evolved is compatible with Syntax HighLighter for WordPress, my blog uses SyntaxHighlighter Evolved now. Everything in this post also applies to SyntaxHighlighter Evolved.

I would like to know what happens if I enter some php code. Does the syntax get highlighted by default in WordPress? Is it going to be stripped out? Will it be forbidden? Let me just type “echo ‘Hello World!'” and see what happens:

<?php echo ‘Hello World'; ?>

I expect this to show up just as I typed it, nothing special.

Now let me type it into the html editor, and see what I get then:

(You see nothing here, but on the backend, in the editor there is a hidden html comment that contains the php code. On the front-end, without the editor, the comment gets stripped out completely) (more…)

Do not require_once() a directory!

0 comments

Posted on 7th June 2010 by Bart McLeod in Web development

If you see the following error messages on the command line in windows, you know you going to be wasting an uncertain amount of time figuring out the right permissions for the directory D:\ZendFramework:

Warning: require_once(D:\ZendFramework\library\Zend\Loader\Autoloader): failed to open stream: Permission denied in D:\werk7\tiris\loadDocuments.php on line 15

Fatal error: require_once(): Failed opening required ‘Zend/Loader/Autoloader’ (include_path=’.;D:\ZendFramework\library’) in D:\werk7\tiris\loadDocuments.php on line 15

What is happening here? Let me tell you what I was trying to do. I was trying to execute a php script from the command line. (more…)

No more small websites…

0 comments

Posted on 25th May 2010 by Bart McLeod in Services

One of my Zend Framework t-shirts hanging outside to dry after washing (I wash them on a regular basis).

Today I decided to stop developing small websites. This is necessary, because I can no longer find the time to support them. It is not because I do not like developing small websites. In fact, I enjoy developing small websites very much and I wish I had the time to continue doing so.

In the next couple of months I hope to do more Zend Framework development.

Deciding to stop developing small websites followed my decision to no longer develop my own CMS. A logical step was to install somebody  else’s CMS on my website. Hence the WordPress installation. A fun thing could be to design and implement my own theme, but then, when am I going to have time for that?