Archive for December, 2007

15
Dec

Setting up a Symfony project on Media Temple’s Grid Service, Part 1

Media Temple’s Grid-Service is a great, low-cost solution for developing and deploying Symfony applications. This article will walk you through setting up a Grid-Server Subversion repository for use with a Symfony project. The main point here is being able to create and use a symfony project hosted on a Grid Server without having to have symfony pre-installed at all locally.

Setting Up Subversion

Symfony is designed to be used with version management software like Subversion. If you’ve never used versioning software, you should read about the benefits right from the Subversion book itself, but in general, it tends to make life easier for developing and maintaining large code bases as it tracks revisions between files and authors. Subversion is already installed in the Grid-Service environment, so all we have to do is set up a new repository. Media Temple has a knowledge base article describing the basic steps, but we’ll be tailoring things a bit to Symfony.

Be sure that you’ve enabled SSH access on your account. Personally, I like creating the repository using the serveradmin user, and then I’ll make commits using a local user on whichever domain I’ll be using. Let’s get started.

Once you’ve logged in via SSH as serveradmin, move into the data directory. This is where we’ll be creating the repository:

cd data

Then, create the base repository like so (substituting your own repository name for mirthlab):

svnadmin create --fs-type fsfs mirthlab

I tend to use separate repositories for each domain. This allows me to use a structure of the form:

mirthlab/
    project1/
        trunk/
        tags/
        branches/
    project2/
        trunk/
        tags/
        branches/
some_other_domain/
    project3/
        trunk/
        tags/
        branches/

… so I can effectively have as many projects related to each domain in version control as I need.

Now that we’ve created the repository, let’s create the base folder for the Symfony project. While still in the data directory, we’ll create a few new folders:

mkdir project1
mkdir project1/trunk
mkdir project1/tags
mkdir project1/branches

… where project1 is the name of your symfony project. This might all look familiar if you’re read through the Subversion documentation, but we’re going to add a couple of folders:

mkdir project1/trunk/lib
mkdir project1/trunk/lib/vendor

It’ll become clear in a moment why we’re doing this, but the short of it is that we’re going to link the Symfony libraries directly to the project itself using the lib/vendor folder. Once you’re done, commit the contents of your project folder to the repo like so:

svn import project1 file:///home/<site_number>/data/mirthlab/project1 --message "Creating initial repo."

Be sure to change <site_number>, mirthlab and project1 appropriately, so that they match your setup. Please note that this assumes you’re starting with a fresh Symfony project. If there’s an existing project you have that you want to import into the repository, these steps would vary slightly since you wouldn’t have to set up a lib folder.

The folder structure was imported into the repository, so you can safely delete the project folder skeleton we made from the data folder:

rm -rf project1

Set Up Additional SVN Users

This step is optional, but would be helpful if you’re going to allow multiple users to work on this repo. There’s also a Media Temple KB article for this if you’re curious. Log in to your Media Temple Account Center for your domain. Click on the “Email Users” button and add some local users.

Email Users Button

I created a user “mark” for my domain. Also, be sure to check the “Enable SSH access?” checkbox:

image here

Now, in order to allow other users to use the new repo, we have to give group access to the directory. From within the data directory run this command as serveradmin:

chmod -R g+w mirthlab

Again, being sure to substitute your own repository name for mirthlab.

Setting Up Symfony

Now that you have your base folder structure, it’s time to get the Symfony project initialized. Connect to your Subversion repository and download the trunk of our project by running the following commands locally. I’m on a Mac OS X box, so I’ll use the terminal to do a checkout of my project to the ~/Sites folder:

cd ~/Sites
svn checkout svn+ssh://your_user%your_domain.com@your_domain.com/home/<site_number>/data/mirthlab/project1/trunk project1

Note: svn checkout svn+ssh... should all be on one line. This creates a project1 folder in my Sites folder, which is just what I want. Now let’s get our Symfony project structure set up by linking the Symfony libraries to our lib/vendor folder with a subversion externals link.

cd project1
svn propedit svn:externals lib/vendor/

This should bring up your favorite text editor. Simply paste this line into the file, save and close it:

symfony http://svn.symfony-project.com/branches/1.0

This effectively links lib/vendor/symfony to the stable 1.0 branch of Symfony. Only security and bug fixes go into this branch, so there’s no need to worry about it breaking your app when running an svn up. Now, commit your changes back to the repository:

svn commit --message "Linking Symfony libraries to lib/vendor"

And when that’s done, update the local working copy to get the libraries:

svn up

Since we now have a local copy of symfony, we can use the symfony binary to execute pake tasks. Let’s flesh out our project by creating the initial structure using the init-project task.

lib/vendor/symfony/data/bin/symfony init-project project1

… where project1 is the name of our project. This doesn’t necessarily have to match the name of your repository project, but that’s usually what I use. This project name is used to set up defaults in files like propel.ini and properties.ini.

Also, be sure to change the path for the symfony libraries in config/config.php:

$sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/vendor/symfony/lib';
$sf_symfony_data_dir = dirname(__FILE__).'/../lib/vendor/symfony/data';

… this just sets them up to use a relative path, instead of an absolute one (which we’ll need when we push this code to the production server).

We can now add the rest of the project to source control:

svn add *
svn commit --message "Added initial symfony project structure."

Subversion might complain that the lib folder is already under version control, but that’s ok.

Next Steps

Additional general info on Symfony and Subversion can be gleaned from Dave Dash’s excellent article: Tips for Symfony and Subversion. Read and follow the directions in that article to complete your setup by ignoring files in cache and log as well as other auto-generated files like the model files Propel generates.

Conclusion

With this setup, we now have a Symfony project under source control on a Media Temple Grid-Service account. We also now have symfony installed locally and which we can use by calling simply ./symfony from within our project directory. In the next article, we’ll take a look at getting our local development environment set up for editing on a Mac OS X box.

11
Dec

Custom Propel Criteria Tips

Here’s a quick Propel tip. While working on a site recently, I had to figure out a way to randomly pull some records from a database using Propel from within a Symfony application. This is a bit of a hack as it will only work if you’re using MySQL, but it’s an elegant way (considering the alternatives) to get some random results. I assume you can use this method with another database. You’d just have to figure out what functions to call instead of the MySQL specific ones like RAND() and DAYOFWEEK().

From within an action, you can do something like this:

$c = new Criteria();
$c->addAscendingOrderByColumn('RAND()');
$c->setLimit(20);
$this->photos = PhotoPeer::doSelect($c);

… which will get you a set of 20 random photo objects.

Something a bit more interesting is using a custom criteria. This basically lets you use any MySQL specific function from within propel without resorting to building a query completely from scratch. Take this example:

$c->add(PodcastPeer::DATE, 'DAYOFWEEK('.PodcastPeer::DATE.')='.$this->filters['day_of_week'], Criteria::CUSTOM);

Basically, I wanted to be able to use a symfony-type filter (just like the ones that are generated automatically by the propel admin generators) to filter podcasts by certain days of the week. So someone could, for example, choose only to listen to those podcasts that were released on Wednesdays. This snippet of code basically allows me to run this sql query:

SELECT * FROM podcast WHERE DAYOFWEEK(podcast.DATE)=1

… where 1 = Sunday, 2 = Monday, etc.

06
Dec

Making a Custom Apache Install Start at Boot on Mac OS X

A Bit Of Background

I do all of my web-development on a Mac OS X machine (a MacBook Pro, to be exact) using a local install of Apache, PHP and MySQL. I’m using a custom built Apache 2 install and configuration (for various reasons) so the default Web Sharing control panel does not control the starting and stopping of my webserver. In general, my setup works really well and has led to a really integrated workflow that I can use and develop with even while offline. One thing that had always frustrated me about my custom setup though, is that after a restart, apache had to be manually started before I could get back to work. This is one of those little things that can be annoying, but not really annoying enough to do anything about. Well, I finally decided to fix it.

Mac OS X has a system startup program called launchd which allows us to start the apache webserver automatically on each system boot. You can read more about launchd at the official apple page.

Making Our Own launchd File

To create the launchd plist file, I used Lingon which is an open source graphical front-end for creating these types of files (version 2.0.2 as of this writing). You can use this article as a reference for creating your own, or simply download the apache2 launchd plist file, unzip it, and place the file into /Library/LaunchDaemons/. This file assumes that you have apache2 installed in /usr/local/apache2/.

Once Lingon is launched, you’ll be presented with a window that’ll show you an overview of all of your currently installed launchd files. Click the “new” button to create a new file. You’ll want a Daemon file since apache needs to run at startup and as root:

Screenshot of step 1

Once you’ve got a new file ready for editing, fill out the “Name” field. I’ll be using “com.mirthlab.launchd.apache2”:

Screenshot of step 2

Next, fill out the “What” field. This will be the command we want to run at startup and I’ll be using “/usr/local/apache2/bin/apachectl start” but this may differ if you have Apache installed in a different location:

Screenshot of step 3

And finally, fill out the “When” field. For Apache, I checked the box that says “Run it when it is loaded by the system (at startup or login)”:

Screenshot of step 4

Wrapping It All Up

Click “Save” and enter your password when prompted. This is a root level launchd daemon which is why Lingon needs your password.

Restart and you should have Apache ready to go!

NOTE: If you simply downloaded the plist file, you’ll probably have to change this file’s ownership as files in /Library/LaunchDaemons/ must be owned by root.

To change the file’s owner to root, in the terminal, type:

sudo chown root:wheel /Library/LaunchDaemons/com.mirthlab.launchd.apache2.plist

… all on one line.

You can also see this macosxhints.com hint for a tip on using the Sharing Control Panel to start and stop your custom Apache install.

05
Dec

Welcome to the New MirthLab

Well, here we go. It’s about time, too. This blog has been a long time coming and I hope to make it a useful resource for all things PHP, Symfony, JavaScript, CSS, Mac, Unix and the like. Most likely it’ll be more of an online reference than anything (documenting things I come across while hacking away on some web-development project) so I hope you find these posts to be a useful resource.