Magento has solved so many problems in the ecommerce world and it is great software out-of-the-box. However, it presents some interesting challenges when trying to make it work in a team environment. In fact, because of things like the "base url" stored in the database and the "var" directory that holds the cache and other meta data, using something like SVN requires some changes "under the hood". I faced this issue, did some research and found an excellent post by Jools Wills that helped a bit - found here. His solution is straight-forward and effective, except that it's two years old at the time of writing. Magento has changed a bit, as well as the methods he overrides. Here is my updated solution based on his initial outline.

The first problem to overcome is that the "base url" is stored in the database. For most team development environments the database is shared and the files are pulled down using SVN or some other version control software and the developers each run their own instance locally. Since changing the base url in the database would only enable one instance of Magento to work at a time, we need to dive under the hood and make some changes. We are going to use a server variable provided to us by PHP to establish the base url instead of pulling it from the database.

Making the Base URL Dynamic

First we need our own custom module. There are many good resources available that explain how to do this. But for now, we won't cover that in detail. We use "LB" as our namespace and "Core" as our module. You can replace those with whatever you choose, as long as you are consistent. Any time you see "LB" put your namespace in. You should use "Core" for your module since we are overriding one portion of the Magento "Core" module. The first file registers our namespace and module with Magento.

Here is the first file: app/etc/modules/LB_All.xml

<?xml version="1.0"?><config> <modules> <LB_Core> <active>true</active> <codePool>local</codePool> </LB_Core> </modules></config>Now that we've registered our module for use in Magento we need to override the important method, that being "Mage_Core_Model_Store->getBaseUrl()". The following XML file does just that. Note that you'll have to create some directories here. Make sure that if you are using something besides "LB" you create a directory with that name instead of "LB".

File: app/code/local/LB/Core/etc/config.xml

<?xml version="1.0"?><config> <global> <models> <core> <rewrite> <store>LB_Core_Model_Store</store> </rewrite> </core> </models> </global></config>That takes care of configuration. We are now ready to dive into some PHP code. We have already told Magento to override the "Mage_Core_Model_Store" class in the configuration, now we just need to add our class.

File: app/code/local/LB/Core/Model/Store.php

<?php/** * We are overriding functionality in Mage_Core_Model_Store * * @author Life Blue */

class LB_Core_Model_Store extends Mage_Core_Model_Store { const USE_DEV_URL = true; protected function getDevelopmentUrl($secure) { $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure; if ($secure) { $url = "http://" . $_SERVER['HTTP_HOST'] . "/"; } else { $url = "http://" . $_SERVER['HTTP_HOST'] . "/"; } return $url; }

public function getBaseUrl($type=self::URL_TYPE_LINK, $secure=null) { $store_code = $this->getCode(); if (self::USE_DEV_URL != true) { $url = parent::getBaseUrl($type, $secure); } $cacheKey = $type . '/' . (is_null($secure) ? 'null' : ($secure ? 'true' : 'false')); if (!isset($this->_baseUrlCache[$cacheKey])) { switch ($type) { case self::URL_TYPE_WEB: $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure; $url = $this->getDevelopmentUrl($secure); break; case self::URL_TYPE_LINK: $secure = (bool) $secure; $url = $this->getDevelopmentUrl($secure); $url = $this->_updatePathUseRewrites($url); $url = $this->_updatePathUseStoreView($url); break;

case self::URL_TYPE_DIRECT_LINK: $secure = (bool) $secure; $url = $this->getDevelopmentUrl($secure); $url = $this->_updatePathUseRewrites($url); break;

case self::URL_TYPE_SKIN: case self::URL_TYPE_JS: $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure; $url = $this->getDevelopmentUrl($secure) . $type . "/"; break;

case self::URL_TYPE_MEDIA: $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure; $secureStringFlag = $secure ? 'secure' : 'unsecure'; $url = $this->getDevelopmentUrl($secure) . $type . "/"; if (!$this->getConfig(self::XML_PATH_USE_REWRITES) && Mage::helper('core/file_storage_database')->checkDbUsage()) { $url = $this->getDevelopmentUrl($secure); $url = str_replace($urlStart, $urlStart . self::MEDIA_REWRITE_SCRIPT, $url); } break;

default: throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid base url type')); } $this->_baseUrlCache[$cacheKey] = rtrim($url, '/') . '/'; } return $this->_baseUrlCache[$cacheKey]; }}

If you look at the "getBaseUrl" method you may notice that it starts out with an "if" statement that indicates that we need to use dynamic base urls. For a production environment all you need to do is set "self::USE_DEV_URL" constant to "false" and the original "getBaseUrl" method is called. That takes care of the "base url" portion of the problem. Now we need to address the "var" directory.

Cache and the "var" DIrectory

We will do this by allowing it to be checked out initially, but then ignoring it after that. We are only going to cover how to do this with Tortoise SVN. You'll have to research other versioning systems and please post comments for other solutions you find!

First you need to push your whole Magento implementation into your repository. Don't exclude the "var" directory. Other people will need to pull that down for Magento to work properly. If you want, you can clear out the sub-directories within "var" to make things a bit more clean. If you choose to do so, make sure you know what you are doing. You can cause things to stop working. You have been warned.

Once you have done your initial push to SVN it's time to set the "svn:ignore" property on the "var" directory. You can do this the hard way and set it using the "properties" utility Tortoise provides, or you can take one or two extra steps that simplifies things as well as making them a bit more but not completely "fool proof".

  1. Export the "var" directory to itself. In Tortoise, right click the "var" folder and select "TortoiseSVN > Export .".
  2. You will be presented a dialog asking you where you want to export to.
  3. Navigate right back to where the "var" directory lives, such as "C:\xampp\htdocs\magento\var" and export.
  4. When it asks you if you want to unversion these files select "Yes".
  5. Now right click the "var" again and select "TortoiseSVN > Export > Add to ignore list > var".
Now the "var" directory will not commit for two reasons. First, it is not versioned and will need to be added back in to run a commit. Second, "var" is set to be ignored when a commit is run. That means it shouldn't ask you if you want to add them.

As I said earlier, this is relatively fool proof. However, you still have to pay attention to make sure the "var" directory does not get included in a commit. Software such as Netbeans may not respect the "svn:ignore" property like you expect. However, if you are careful you can just run an update on the whole instance of Magento without fear of getting someone elses "var" contents and goofing up your working copy.

I hope that helps you with your Magento development. If you have any questions or have some additional suggestions leave some comments