Making SiteTree Fields Longer in SilverStripe 3.X

Aside: In my ongoing internal battle to try to write regularly on my blog, I have decided to try blogging about little things that I do in my day-to-day programming (and other tech endeavors) that may be helpful to others – especially things that seem like they are searched for a lot, but lack adequate answers. Here’s my first attempt at this new style of blogging:

I have been using SilverStripe 2.4.x for about eighteen months now on a couple of projects. As part of what the client wanted, I needed to make the SiteTree MenuTitle field longer. If I remember correctly I first tried just redefining this field in the $db array of my Page class since that extends SiteTree, and that didn’t work. So, I resorted to a bit of a hack in the _config.php file to override the static variable value:

SiteTree::$db['MenuTitle'] = 'VARCHAR(255)';

In SilverStripe 3.0 or 3.1 (I can’t remember off the top of my head), all of those static class variables that SilverStripe uses to define configuration of a class (like $db and others) have become private. So, the hack I previously had didn’t work. However, SilverStripe now has a very nice configuration system that is used all over the place. Of note for this post is that all those static variables are basically read into the config system and then the values in configuration are what’s used instead of accessing those static variables directly. This means that in our _config.php we can now do the following hack/workaround to make a field longer:

$fields = Config::inst()->get('SiteTree', 'db', Config::UNINHERITED);
$fields['MenuTitle'] = 'VARCHAR(255)';
Config::inst()->update('SiteTree', 'db', $fields);

This is also notable because in the 3.x line of SilverStripe they have started storing URL segments (the SiteTree.URLSegment field) in URL-encoded form. In 2.4.x they tried stripping non-ASCII characters out of the URLs, so it didn’t really support multi-byte characters, etc, out of the box. I had overridden it to do so where I was using it since we needed to support multiple languages. But now since it is built into SilverStripe, we can get this out of the box if we simply URL encode those UTF8 strings that we have stored in the SiteTree.URLSegment column. However, that means the data could easily be truncated. For instance, SilverStripe defines the URLSegment column as VARCHAR(255). That’s 255 characters – not bytes. So, in a worst-case scenario – where all the characters were three-byte characters, you would end up with 255 characters * 3 bytes each * 3 characters (because each byte will be %HH where HH is a hexdecimal representation of that byte), which means your column would now need to be VARCHAR(2295)! Although you are unlikely to really want a single URL segment that long, you may need to use the tip above to make your URLSegment field longer. It would simply look like this:

// in _config.php
$fields = Config::inst()->get('SiteTree', 'db', Config::UNINHERITED);
$fields['URLSegment'] = 'VARCHAR(1024)';
Config::inst()->update('SiteTree', 'db', $fields);

There may be a much better way of handling this. You might also be able to override these values in a YAML file, but I haven’t tried it. If you find a nicer (less hack-ish) way of doing this, please comment below and let us know!

Be Sociable, Share!

2 thoughts on “Making SiteTree Fields Longer in SilverStripe 3.X

  1. You should be able to do it in YML by creating a file (config.yml or something) in the mysite/_config with something like the following:

    Name: appconfig
    After: ‘framework/*’,'cms/*’

    URLSegment: ‘VARCHAR(1024)’

    I’ve never tried it for db but I’ve used it for other similar things. You’ll need to ?flush=1 before it will pick up the change.

  2. Sorry, looks like the indentation in that yml got squashed. Should be:

    ____URLSegment: ‘VARCHAR(1024)’

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>