Common refactoring for migrations

The following are some common tasks you might need to carry out in order to adapt your SilverStripe project for SilverStripe Platform compatibility.

Database Credentials

Database parameters are configured outside of your project in the _ss_environment.php file, which is managed by SilverStripe Platform. To ensure a successful deployment your mysite/_config.php file should look similar to the following:

global $project;
$project = 'mysite';

global $database;
$database = ''; // This must be left blank

// This includes _ss_environment.php and configures your application

Scripts to BuildTasks

The correct way to create compatible automated tasks that will work on SilverStripe Platform is to make use of BuildTasks. This is because the infrastructure on SilverStripe Platform is automatically configured and there is no access directly to the terminal of these servers (to setup cronjobs/manually run scripts).

BuildTasks can be accessed through http://yourwebsite/dev/tasks or scheduled to run by setting up a CronTask (see later on in this documentation).

You may already have scripts you have used on past servers that you will have to convert to BuildTasks in order to continue using them.

If your script is php based (a single php procedural file), you should be able to simply copy this code into the BuildTask::run method. In some cases you may have had database connections and SQL calls, if these connect direct to your main SilverStripe CMS you also may wish to refactor these to make use of the ORM or DB classes built into SilverStripe Framework.

For example:

// Old php script
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "SELECT * FROM Member";
$result = $conn->query($sql);
// New BuildTask
class MemberListTask extends BuildTask {
    protected $title = 'MemberList';
    protected $description = 'Fetch a list of Members in the database';
    protected $enabled = true;
    function run($request) {
       $members_orm = Member::get();
       $members_db = DB::query('SELECT * FROM "Member"');

(You would then be able to run the new task through the browser as http://yourwebsite/dev/tasks/MemberListTask)

If your script included the use of command line such as git and other linux commands, you may still be able to execute these using the php exec() and chdir() commands. While the these commands will run on Platform they will only be able to affect files within the web root of the site and can only run the command as the default apache user on the system (this is the ‘www-data’ user).

For example:

. . .
     function run($request) {
        exec('git clone git:// foldername');   
. . .

If you need output from these scripts for debugging you can either log these to the SilverStripe Platform logging tool (Graylog) or look to email yourself the outputs from these build tasks using php’s mail() function or some other method;

If you have any more advanced scripts that are essential to the operation of your website being migrated on to SilverStripe Platform please discuss with our support team to see if it is possible.

Cron jobs to CronTask module

For setting up cronjob like tasks on SilverStripe Platform you’ll need to ensure your project has the mandatory CronTask module installed.

Next, you need to define your CronTask, this uses a combination of the familiar Cronjob style scheduling format alongside a php method that will trigger code once the schedule is met. You can use CronTask to trigger your BuildTasks. For example, continuing our example from above:

class DailyCron implements CronTask {

    public function getSchedule() {
        return "0 1 * * *";

    public function process() {
        $task = new MemberListTask()
        $task->run(null); //run() takes an argument of the current request, use null if there is no expected request data to pass in.
        //You can run other things here too...

SilverStripe Platform Stacks are preconfigured to run CronTasks every minute, these check the schedule you have set up in your CronTask class and if the time of the next run time is met or exceeded (by max of 1 min) the code in the process() method executes (triggering a BuildTask or some other code).

For more information about CronTask visit the CronTask Documentation

Technical note for CronTask: Load balanced SilverStripe Platform Stacks only trigger CronTasks on one (1) server, any file changes made on that server are then synchronised across the remaining servers. Be aware in some cases there can be a short delay while this sync occurs.

CronTask considerations on Stack Share

Any CronTasks that run from multiple websites at the same time, will use up a higher amount of resources to process the task. You may want to review the websites you are running on your Stack Share and their CronTask setups holistically and plan to stagger when the tasks will be run to make best use of the shared Stack resources.

Making use of Solr search

If the website you are migrating makes use of Solr search you can opt to use an optional Solr search server on the SilverStripe Platform. This requires the additional cost of an extra server per SilverStripe Platform environment (UAT and Live for example), please contact the SilverStripe Platform support team about this.

You will also need to ensure you are using the Fulltextsearch and Queuedjobs modules in your project dependancies and have configured the module to make use of specific preconfigured variables.

Add these modules to your composer.json and run composer update:

"silverstripe/fulltextsearch": "*",
"silverstripe/queuedjobs": "*"

These are the variables that will be preset up by the SilverStripe Platform support team if you opt in to Solr search. You would also need to account for these variables if testing Solr on your local development environment.

Example configuration from _ss_environment.php:

define('SOLR_PATH', '/solr');
define('SOLR_REMOTEPATH', '/solr');
define('SOLR_INDEXSTORE_PATH', '/solr/webdav');
define('SOLR_SERVER', 'x.x.x.x');
define('SOLR_PORT', '80');
define('SOLR_MODE', 'webdav');

Use these variables in your Solr config as follows (in your _config.php file):

        'host' => defined('SOLR_SERVER') ? SOLR_SERVER : 'localhost',
        'port' => defined('SOLR_PORT') ? SOLR_PORT : 8983,
        'path' => defined('SOLR_PATH') ? SOLR_PATH : '/solr/',
        'indexstore' => array(
                'mode' => defined('SOLR_MODE') ? SOLR_MODE : 'file',
                'auth' => defined('SOLR_AUTH') ? SOLR_AUTH : NULL,
                'path' => defined('SOLR_INDEXSTORE_PATH') ? SOLR_INDEXSTORE_PATH : BASE_PATH . '/.solr',
                'remotepath' => defined('SOLR_REMOTE_PATH') ? SOLR_REMOTE_PATH : null
        'templatespath' => BASE_PATH . '/mysite/code/search/templates'

Once this is set up you will need to contact SilverStripe Platform support to arrange setting up a custom Cron job for the Queuedjobs module to process and reindex content.

Alternative search options

If you don’t require the power or advanced configuration of Solr search, you may want to consider some other options.

External box or third party service - You could connect your SilverStripe Platform website to an external server or service (such as Google Custom Search)

Internal search - Make use of the built in database powered search (FulltextSearchable::enable();). See

Zend Search Lucene - You could make use of the PHP Zend Framework Lucene port as this will function under PHP on the SilverStripe Platform Stacks. You might write your own implementation or make use of a community module

Moving to Composer to manage your modules

If your SilverStripe project hasn’t made use of the Composer module manager, you’ll need to alter your project setup.

Here is a process you can follow:

  1. Take a stock take of the versions of SilverStripe core and modules you are using. This can be tricky if you haven’t kept a list, but composer will help with this going forward.

  2. In your webroot, create a file named composer.json and add the following (this example uses SilverStripe 3.2.1):

    	"name": "silverstripe/installer",
    	"description": "The SilverStripe Framework Installer",
    	"require": {
    		"php": ">=5.3.3",
    		"silverstripe/cms": "3.2.1",
    		"silverstripe/framework": "3.2.1",
    		"silverstripe/reports": "3.2.1",
    		"silverstripe/siteconfig": "3.2.1"
    	"require-dev": {
    		"phpunit/PHPUnit": "~3.7"
    	"config": {
    		"process-timeout": 600
    	"prefer-stable": true,
    	"minimum-stability": "dev"
  3. Now you have accounted for SilverStripe core in your Composer file, remove the corresponding folders from your webroot (framework, cms, reports and siteconfig), run the command composer update, add the folder to your .gitignore file, then make a git commit to your project. This physically removes this code from the project in favour of a meta data reference to it in Composer.
    Ensure you commit both composer.json and composer.lock files to your project along with the .gitignore file.

  4. For each module you are using, add the module to the composer.json, require section (along with the version number or a simple “*” to have Composer determine the best version to use). Run composer update and then commit the resulting 3 file changes (composer.json, composer.lock & .gitignore).

Question: I customised the code in a module or SilverStripe core, what do I do?

Answer: Ideally, it’s best to leave SilverStripe code and module code as is to allow for easy future upgrades. If you can possibly get back to this state, it’s the best option (by moving your customisations into your project code in “mysite”). Alternatively, you can either continue to keep the module as part of your project code, or move your custom version of the module to it’s own git repository and then reference this in your composer.json file with a custom repository reference.

Question: The module I’m using is not registered with Packagist/doesn’t have a composer.json file what now?

Answer: Use the same approach as above, either continue to include the code in your project repository or reference the module in your composer.json using a custom repository reference (you may need to make a fork/copy of the module and add your own composer.json file for this to work).