symfony: creating individual modular sites with a base configuration.. by Daniel Graetzer May 22nd, 2007
Ok, so a current project i’m working on is rolling out potentially hundreds of sites..
All of these sites are using the same base, but have different configuration, design and data for each one..
A problem has been how to roll all these sites out, while keeping them easy to update with bug fixes and modifications..
Here’s my solution..
Firstly we start with the config files.. app.yml and view.yml are very site individual, so what do you do if you want some site specific settings?
Well, in your app/config folder, create an app_local.yml and a view_local.yml - these will be your local config files, while the app.yml and view.yml contain settings that are the same for all of your sites…
Here’s an example of how the app.yml and app_local.yml would work from my sites..
all:
#parameters for the gallery and avatar directories and sizes
galleries:
size_limit: 30
limit: 20
gallery_count: 25
upload_dir: /images/media/galleries/uploads
allowed_image_types: [image/jpeg, image/jpg, image/pjpeg, image/gif, image/png, image/bmp, image/tiff]
allowed_video_types: [video/mov, movie/quicktime, video/mpeg, video/x-ms-asf, video/x-msvideo, video/x-ms-wmv]
And here’s my app_local.yml
prod:
#MUST EDIT THESE PARAMETERS - FOR PRODUCTION ONLY
site_name: Skeleton Site
cookie: skeleton
site_domain: skeleton.com
site_support_email: support@
merchant:
id: 4
pass: password
all:
#SHOULD EDIT THESE PARAMETERS
#the selected attributes for the member profiles - eg, what profile questions to ask.. refer to db
member:
attributes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
swf:
heading_font: DeliciousHeavy
Ok.. so hopefully the division is starting to make sense…
Now we need to configure the handlers… This part requires some small hacks of the symfony core files..
lets start with app.yml (note the paths are my personal nix paths.. im presuming you know where your symfony core files are)
open up /usr/local/lib/php/symfony/symfony.php and at around line 97, add this in:
if ($file = $configCache->checkConfig($sf_app_config_dir_name.'/app_local.yml', true))
{
include($file);
}
ok, now we move on to the view_local.yml…
Open up /usr/local/lib/php/symfony/view/sfPHPView.class.php
At about line 151, add in the following (NOTE: THIS HAS BEEN UPDATED TO INCLUDE VALIDATION)
$viewConfigFile = $this->moduleName.'/'.sfConfig::get('sf_app_module_config_dir_name').'/view_local.yml';
if($file = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$viewConfigFile, true))
{
require $file;
}
now we need to add in the handlers for both files..
Open up /usr/local/lib/php/data/symfony/config/config_handlers.yml
Add in there, basically anywhere, the following:
modules/*/config/view_local.yml:
class: sfViewConfigHandler
config/app_local.yml:
class: sfDefineEnvironmentConfigHandler
param:
prefix: app_
Ok.. that takes care of your config files!!!
Now what i do for the css is have a site.css file, which is the only thing i change for each site… When i have conflicting css classes I can get lazy and just add !important to the end of the attribute.. But deal with this as you like..
Each site also has it’s own main app template. If you’ve designed the site in lovely css design, you shouldnt have too many problems changing the look and feel for each site individually.
As a final touch, with the help of the polymorph, here’s a sexy perl script that handles the rollout…
#!/usr/bin/perl
$SITELIST = "sitelist.live";
$SRCDIR = "/opt/***/skeleton";
$EXCLUDE = "/opt/***/rsync.live";
$TARGETDIR = "/opt/***/";
$RSYNC = "rsync";
$USER = "***";
$SERVER = "target_ip";
$RM = "/bin/rm";
########################## 8< No User Servicable Parts Beyond This Point 8< ##########################
my $sitecount = 0;
open CONFFILE, $SITELIST or die "Can't open $SITELIST to read!";
while ()
{
chomp($_);
$sites[$sitecount++] = $_;
}
print “—————————————————————————\n”;
print “A: Upload all sites.\n”;
for (my $j = 0; $j < $sitecount; $j++)
{
print "$j: Upload $sites[$j]\n";
}
print "---------------------------------------------------------------------------\n";
chomp($uploadSite = );
$uploadSite =~ s/[A-Z]/[a-z]/g;
if ($uploadSite eq ‘a’)
{
$start = 0;
$end = $sitecount;
}
elsif (($uploadSite !~ /[a-z]/) && ($uploadSite < $sitecount))
{
$start = $uploadSite;
$end = $uploadSite + 1;
}
else
{
die "Invalid site selected.\n";
}
# print "Removing cache and logs ...\n";
# $CMD = "$RM -rf $SRCDIR/cache/* $SRCDIR/log/*";
# `$CMD`;
for ($i = $start; $i < $end; $i++)
{
print "Removing Cache & Logs ...\n";
$CMD = "$RM -rf $TARGETDIR$sites[$i]/cache/* $TARGETDIR$sites[$i]/log/*";
`$CMD`;
print "Uploading site $sites[$i]\n";
#print $EXCLUDE."\n";
$CMD = "cd $sites[$i]; $RSYNC --delete -avz --exclude-from=$EXCLUDE . $USER\@$SERVER:$TARGETDIR$sites[$i]";
$RESULT = `$CMD`;
print $RESULT;
print "\n\n";
}
print "\n\nCOMPLETE!\n";
I really hope this made sense, if not, please ask any questions.
Enjoy!






August 10th, 2007 at 1:49 am
A better way to include the configuration automatically (at least as of symfony 1.1) is to edit your /apps/%application_name%/config/config.php file and add a line like this:
include(sfConfigCache::getInstance()->checkConfig(sfConfig::get(’sf_app_config_dir_name’).’/memcache.yml’));
memcached.yml is the configuration file I’m trying to add.
Now all your changes are in your application directory and not the symfony core.
August 10th, 2007 at 3:41 pm
thanks for the tip!
im very interested to hear how you’ve integrated memcache into symfony..? I am looking at doing the same thing in the near future
January 24th, 2008 at 6:57 am
[...] symfony: creating individual modular sites with a base configuration [...]
January 24th, 2008 at 8:57 am
No need something particular with 1.1, everything is here: http://trac.symfony-project.com/browser/branches/1.1/lib/cache/sfMemcacheCache.class.php
Thi one can be easily rewritten for particular needs, eg. session handling using memcached.