Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Customising the CMS /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

dynamically adding items to $db


Go to End


13 Posts   6517 Views

Avatar
Carbon Crayon

Community Member, 598 Posts

15 January 2009 at 11:28am

Ok so here it is, pretty simple in the end...

EnviromentExtention.php

<?php
   class EnviromentExtention extends DataObjectDecorator {
   	
	function augmentSQL(SQLQuery &$query) {}
	
	function SanitizeString($String) {
		
   		$tmp = preg_replace('/\s+/', '_', $String); // compress internal whitespace and replace with _
 		$reserved = preg_quote('\/:*?!&"<>|', '/');//characters that are  illegal
 		 //replaces all characters up through space and all past ~ along with the above reserved characters
  		return preg_replace("/([\\x00-\\x20\\x7f-\\xff{$reserved}])/e", "", $tmp);

	}
	
	public function extraDBFields(){
		
		$db = array();
		if($Enviroments = DataObject::get("EnviromentPage")){
		
			foreach($Enviroments as $Enviroment)
			{
				$key = $this->SanitizeString($Enviroment->Title);
				$db[$key."_CategoryLink"] = "Varchar(255)";
			}		
		}
		return array('db' => $db);
	}	
	
	public function getCMSFields(){	
		 $this->extend('updateCMSFields', $fields);
	  	 return $fields;
	} 	

	public function updateCMSFields(FieldSet &$f) {
		
		if($Enviroments = DataObject::get("EnviromentPage")){
			
			foreach($Enviroments as $Enviroment)
			{
				$key = $this->SanitizeString($Enviroment->Title);
				$f->addFieldToTab("Root.Content.Environments", new TextField($key."_CategoryLink"));
			}		
		}
	}

}
?>

Then in my _config.php I have this line:
Object::add_extension('CategorytPage', 'EnviromentExtention');

So now each time I add a new EnviromentPage and flush the DB, the Catagory page gets a new text field under the Enviroments tab called something like ebay_Catagorylink.

Man I love SS :D

Avatar
UncleCheese

Forum Moderator, 4102 Posts

15 January 2009 at 3:55pm

Nice job. The only thing I'd change is you have your SanitizeString method as a dynamic function. There's nothing dynamic about it -- its a simple input/output "factory" function as they're sometimes called. So cast it as static, and call it with self::SanitizeString()

A lot of times for big projects I'll create a whole static class called Strings with all sorts of functions like that.

Just a good practice, that's all.

Avatar
mrguits

Community Member, 2 Posts

16 September 2014 at 12:57am

Edited: 16/09/2014 6:07pm

I used this solution on a 3.0 installation, but after upgrade to 3.1, extraStatics/extraDBFields are deprecated.

Now I do not understand how to dynamically add items to $db

Avatar
martimiz

Forum Moderator, 1391 Posts

16 September 2014 at 7:41am

Edited: 16/09/2014 6:08pm

In Silverstripe 3.x in a Dataextension you can use the same private static $db = array(...) setup you would use in a DataObject

Avatar
ntd

Community Member, 9 Posts

17 July 2016 at 9:10am

Edited: 17/07/2016 9:12am

I had a similar issue: I needed to dynamically augment the database fields by computing in runtime the values of an enum in SilverStripe 3.4. It was not easy but maybe I just missed a more linear way to address this problem.

class MyDataObject extends DataObject
{
    private static $db = array(
        'MyEnum' => 'Enum()',
    );

    private static $dynamised = false;


    // Directly accessing the cache is hacky and prone to errors but I did not find another way
    private static function addDynamicFields() {
        // Refresh the fields cache
        self::custom_database_fields(__CLASS__);
        $cache =& self::$_cache_custom_database_fields[__CLASS__];

        // Augment the fields cache with the dynamically generated enums
        $cache['MyEnum'] = 'Enum("' . implode(',', enumValues() . '")';

        // Update @config $db
        $db = Config::inst()->get(__CLASS__, 'db');
        $db['MyEnum'] = $cache['MyEnum'];
        Config::inst()->update(__CLASS__, 'db', $db);
    }

    public function __construct($record = null, $is_singleton = false, $model = null)
    {
        parent::__construct($record, $is_singleton, $model);

        if (! self::$dynamised) {
            self::addDynamicFields();
            self::$dynamised = true;
        }
    }
}

I don't think this approach would be feasible without directly touching the DataObject code.

Go to Top