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.

Customising the CMS /

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

dynamically adding items to $db


Go to End
Reply


13 Posts   3245 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, 1304 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, 7 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