Magento Base URLs and dev/staging installations

2009 March 28
by Jools Wills

One of the earlier problems I came across when setting up Magento, was that the Base URLs for the websites/stores are stored in the database. We wanted a scenario where we can have a staging site, and a development site, and transfer the database between them. With the way Magento works, this would require updating the Base URLs each time, and means that we couldn’t easily share a single database between a local development copy and a shared development copy running from our svn.

My first idea to workaround this was to create a small tool, that updated the Base URLs stored in the database, however this didn’t solve the issue of sharing one database between different installs. I looked into the Magento code, and saw that there is a function Mage::getBaseUrl (which in turn calls Mage_Core_Model_Store->getBaseUrl). If I could override this function on the development copies, I could replace the live Base URLs stored in the database with whatever local address we were using.

One of the best places to find development information seems to be on other people’s blogs, and this was one of the reasons why we thought it a good idea to blog our development here. I found http://www.belanur.de/blog/2008/09/05/overriding-core-models-with-a-custom-module/ invaluable when it came to learn how to override classes/function in Magento.

On to the code. The code is split into 4 files. Two XML configurations, and the php with the new getBaseUrl call. The other file is a ini config file for specifying how the Base URLs should map to the development/staging URLs.

Assuming you have a working configured Magento install. The following paths are all referenced relative to the main Magento folder.

File: app/etc/modules/Maglife_All.xml
This file activates our module. Magento merges this xml with its own xml to create a config.

<?xml version="1.0"?>
<config>
    <modules>
      <Maglife_Core>
        <active>true</active>
        <codePool>local</codePool>
      </Maglife_Core>
    </modules>
</config>

File: app/code/local/Maglife/Core/etc/config.xml
This file specifies to Magento what the module does. In this case it says the model / class we want to override and points to the replacement file (the line Maglife_Core_Model_Store translates to the path Maglife/Core/Model/Store.php which contains our code). This is at least my current understanding as I haven’t found any comprehensive documentation on the various xml tags yet.

<?xml version="1.0"?>
<config>
    <global>
        <models>
            <core>
                <rewrite>
                    <store>Maglife_Core_Model_Store</store>
                </rewrite>
            </core>
        </models>
    </global>
</config>

File: app/code/local/Maglife/Core/Model/Store.php
This contains the actual code. We call the parent getBaseUrl function, and then if the ENV variable is set, we replace the base url with a url provided in the urls.ini file (passed in the MAGENTO_DEVURLS variable).

<?php

class Maglife_Core_Model_Store extends Mage_Core_Model_Store
{

    public function getBaseUrl($type=self::URL_TYPE_LINK, $secure=null)
    {
        $store_code = $this->getCode();
        $url = parent::getBaseUrl($type, $secure);
        if ($url_ini = @$_SERVER['MAGENTO_DEVURLS'])
        {
            if ($urls = parse_ini_file($url_ini))
            {
                $host = parse_url($url, PHP_URL_HOST);
                if (isset($urls[$host]))
                {
                    $url = str_replace('://'.$host.'/', '://'.$urls[$host].'/', $url);
                }
            }
        }
        return $url;
    }

}

?>

File: urls.ini (can call this anything you like)

livestore.example.com = staging-livestore.example.com
livestore2.example.com = staging-livestore2.example.com

Then in my apache config on the staging/dev site I have the line

SetEnv MAGENTO_DEVURLS /path/to/urls.ini

and that’s it. I can now copy our live database to the staging server for example, without having to manually alter the Base URL config data in the database. I hope this is some use to others.

22 Responses leave one →
  1. 2009 March 31
    Richard permalink

    Great post, exactly what we are looking for!!

    One note though. In Store.php you terminate the file with php closing tags. Magento complains about headers already being sent if this si the case. Take out the ?> and all is fine!

  2. 2009 March 31

    Hi Richard. Glad you found the article helpful.

    Usually when you get a PHP error about headers having already been sent, it is because there is some trailing whitespace (a space, tab or linebreak) after the closing PHP tags, not because of the tag itself. We’ve certainly encountered no issues with the code as we have it here. Thanks for your comment!

  3. 2009 March 31
    Richard permalink

    Ah, that could well have been the problem.

    Looking forward to reading your future posts.

    Now back to trying to get an iframe injected in the one page checkout!!

  4. 2009 June 9

    Hello Richard! This sounds like a very good thing to be able to do, but I have run into a few problems. As far as I can tell, I followed your instructions exactly.

    First of all, I got the “Cannot send headers” error, which I fixed.

    Now I see that the urls.ini file is in the wrong place. Where exactly should it go? Here’s the message:

    Warning: parse_ini_file() [function.parse-ini-file]: open_basedir restriction in effect. File(/path/to/urls.ini) is not within the allowed path(s): (/var/www/vhosts/ (…blah blah blah…) /httpdocs:/tmp) in /var/www/vhosts/(…blah blah blah…) /httpdocs/magento/app/code/local/Maglife/Core/Model/Store.php on line 12
    Trace:
    #0 [internal function]: mageCoreErrorHandler(2, ‘parse_ini_file(…’, ‘/var/www/vhosts…’, 12, Array)

    And while I have your attention, here’s another problem that is unrelated, but maybe you know the answer. I haven’t been able to access the Admin backend from my staging subdomain. (I noticed this before I tried to implement your code.) Basically, all I did was backup the live site to my hard disk, and then upload it to the staging subdomain. I also set the permissions, and the front end comes up fine, or at least it used to!) but the backend isn’t there.

    Thank you!

    Claire

  5. 2009 June 9

    I see what I did wrong — I added the following line verbatim to the apache config on my server, but didn’t include the actual path. (duh)

    SetEnv MAGENTO_DEVURLS /path/to/urls.ini

    So this seems to work fine, Thanks! But I still can’t get the backend to come up.

    • 2009 June 9
      Jools Wills permalink

      What error are you getting with the backend? Anything logged in the report folder?

  6. 2009 June 9

    I’m getting a 404 Not Found, although the files are there. I also noticed that the frontend isn’t functioning properly. It looks good, but if you click a product you also get a 404 error. I better upload it all again, just to make sure nothing was left behind.

    Also, I have the admin set to run in SSL. Will this url staging reroute apply to https as well?

    Thanks!

    • 2009 June 9
      Jools Wills permalink

      Yeh should work for ssl also. Not sure why you can’t get to the admin panel. I can only think there is a mismatch between the baseurl stored in magento and the reference to it in the ini file ?

      tried accessing it from /index.php/admin ?

      if that works then it might be the rewrite / friendly urls not working on your system.

  7. 2009 June 9

    Jools, Yes! That worked. hmmmm..

    I have mod_rewrite on my server, but haven’t yet enabled it in Magento. If I set Use Web Server Rewrites to “yes,” will it take care of this problem?

    • 2009 June 9
      Jools Wills permalink

      To access the admin panel from /admin you will need to have mod_rewrite running or have some other redirect. once you login magento will take you to index.php/admin anyway.

      You will need mod_rewrite enabled on the webserver to utilise the “web server rewrites” facility of magento (used for frontend catalog etc)

  8. 2009 June 9

    I turned that on and cleared the cache, but it didn’t change anything. I’m running 1.3.1 and need to upgrade the site soon to get that subdomain security bug fix. Although upgrading sounds like a pretty iffy proposition, judging from all the problems people are having — all the more need for a good staging environment!

  9. 2009 November 12

    Jools,

    Thanks much for the code. I ran into an error while using the product custom option file upload on the front end. Magento changes the current working directory and causes an error:

    Warning: parse_ini_file(./urls.ini) [function.parse-ini-file]: failed to open stream: No such file or directory in /Applications/MAMP/htdocs/x/app/code/local/Maglife/Core/Model/Store.php on line 19″;i:1;s:1509:”#0 [internal function]: mageCoreErrorHandler(2, ‘parse_ini_file(…’, ‘/Applications/M…’, 19, Array)
    #1 /Applications/MAMP/htdocs/x/app/code/local/Maglife/Core/Model/Store.php(19): parse_ini_file(‘./urls.ini’)

    So the fix for me was to add in the whole path:

    if ($url_ini = Mage::getBaseDir() . ‘/’ . @$_SERVER['MAGENTO_DEVURLS'])

    I of course removed the period and forward slash from the ./urls.ini in .htaccess as well.

    Thanks!

    -Tony

    • 2009 November 12
      Jools Wills permalink

      I dont keep my urls.ini inside the magento working folder, and use an absolute path to it, so your change isn’t needed in this case. However your change is useful if you want to keep it relative to the magento install folder. Thanks.

  10. 2009 November 12

    Jools,

    Woops! I should have re-read your original post (and remembered that your solution was to use the full path in apache config).

    Thanks again!

    -Tony

  11. 2009 November 18
    Gunnar permalink

    I’ve tried your version, but i get a strange error:

    Can’t retrieve entity config: core/store_group

    I haven’t found any documentation on what it means, there’s two that have similar problem, but no solution anywhere…

    • 2009 November 18
      Jools Wills permalink

      You get this error after applying the dev/staging url changes? removing them makes the store work as normal ? What version of magento are you running ?

  12. 2009 December 4

    Just sharing our thoughts on Magento Installation requirements in localhost

    http://magento.novosoftwares.com/magento-installation/magento-installation-requirements/

    Kind Regards,

    Team Novo

  13. 2009 December 31
    Waheed Khan permalink

    Jools

    You are really well informed and are really talented. I have read the above but I too new to work out what i need to do. I am new to magento and code for that matter. I have installed a working copy of magento but am not sure on how to set up a staging site and run multiple websites from multiple domains with one magento install. Would be grateful for a dummies guide.

  14. 2010 January 5

    Worked like a charm! Thanks!

  15. 2010 January 7
    Bryan permalink

    Hi..

    Regarding the SetEnv MAGENTO_DEVURLS /path/to/urls.ini

    ..dose any one have an idea where the ‘Apache Config’ folder is located?

    My ’staging’ site is located on a subdomain of our web site, hosted with a web hosting company and cPanel is our file manager.

    No where in our ‘home directory’ can we find the ‘Apache’ ‘Config’ folder in which we think we include the … SetEnv MAGENTO_DEVURLS /path/to/urls.ini some where with-in.

    Do we need to create these folders? Where about is the …urls.ini line entered?

    Any help / clarification about this would be grate and very much appreciated.

    Thanks

  16. 2010 January 27

    Works like a charm. Thank you very much. Having multiple databases was a big time sync on our last project.

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS