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.

Data Model Questions /

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

inherit dataobject ( or something)


Go to End


17 Posts   6985 Views

Avatar
Stefdv

Community Member, 110 Posts

22 February 2011 at 6:49am

Hello World,

I'm building a site for a dogbreeder and all is going fine, but...

I manage my Dog in ModelAdmin ( DogAdmin)

Every dog has one Pedigree ( DataObject) and many Showresults ( DataObjects)

I've created a Tab for Pedigree and one for Showresults.

How do i 'tell' these tabs that they belong to the dog i'm working on?

Right now the user have to fill in, in each tab, to what dog the pedigree or showresult belongs. So i need some field in those two that will be filled as soon as i create a dog.

any help ?

Avatar
swaiba

Forum Moderator, 1899 Posts

23 February 2011 at 10:32pm

This should all be done automatically - you shouldn't need to create the tabs - ModelAdmin will scaffold them if your database is setup correctly. Check that your "dog has_many Pedigree" is reciprocated with "Pedigree has_one dog". If this doesn't help - it might be best to post code to work out what is going on...

oh and make sure you've read all the docs on ModelAdmin (http://silverstripe.org/data-model-questions/show/15923#post299457) and on the DataModel (http://doc.silverstripe.org/sapphire/en/topics/datamodel)

Avatar
Stefdv

Community Member, 110 Posts

24 February 2011 at 5:25am

Thank u for your reply,

I understand that modeladmin scaffolds them, and that does work. The problem is that when i don't create tabs there is to much information when i open up a Dog ( that sounds nasty) . Everything is in one screen and i cannot scroll down. I tryed that with my first try ( called 'OwnPug' ) i post that below as first code.

When i do create tabs, it seems that the info on the tabs don't seem to be automaticaly linked to the Dog on the Main tab.

I post my code below, if you feel like going thru it.

Mops = Dog
Stamboom = Pedigree
Showresultaat = Showresults

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

This is the code for my first try, i don't use this dataobject anymore. It's just to show what will come out if i use this with modeladmin, i don't think it's very client friendly) I use the FieldGroups to shorten the form.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class OwnPug extends DataObject
{

static $db = array (
'Kennel' => 'Varchar',
'Land' => 'Varchar(2)',
'KennelNaam' => 'Varchar',
'Titel' => 'Varchar',
'RoepNaam' => 'Varchar',
'DNA' => 'Boolean',
'Born' => 'Varchar',
'Nummer' => 'Int',
'Patella' => 'Varchar',
'Info' => 'Text'
);

static $has_one = array (
'PugPage' => 'PugPage',
'Stamboom' => 'Stamboom',
'Photo' => 'Image');

static $has_many = array ('Showresultaten' => 'Showresultaat');

//Fields to show in the DOM
static $summary_fields = array(
'Thumb' => 'Photo',
'KennelNaam' => 'KennelNaam',
'RoepNaam' => 'RoepNaam'
);

// static $summary_fields = array ('Kennel','KennelNaam', 'Geslacht');

static $searchable_fields = array(
'Kennel',
'KennelNaam',
'RoepNaam'

);
static $field_labels = array('KennelNaam' => 'KennelNaam');

//static $default_sort = "LastName ASC";

public function getCMSFields()
{
return new FieldSet(
new FieldGroup(
new TextField('Titel','Gewonnen Titel(s)')
),
new FieldGroup(
new TextField('Land', 'Land van herkomst, (A)ust, (C)an, (D)enem, (E)ng, (N)oorw of (NL)')
),
new FieldGroup(
new TextField('Kennel'),
new TextField('KennelNaam',' KennelNaam'),
new TextField('RoepNaam',' RoepNaam')
),

new CheckboxField('DNA','DNA geregistreerd?'),
new FieldGroup(
new TextField('Born','Geboren'),
new NumericField('Nummer',' Nummer'),
new TextField('Patella',' Patella')
),
new TextAreaField('Info'),
new ImageUploadField('Photo'),
new HasOneDataObjectManager(
$this,
'Stamboom',
'Stamboom'
),
new HasManyDataObjectManager(
$this,
'Showresultaten',
'Showresultaat'
)
);
}
//Needed for sidebar to work
function canView()
{
return true;
}

//Return the Title as a menu title
public function MenuTitle(){
return $this->KennelNaam;
}

//Generate our thumbnail for the DOM
public function getThumb()
{
if($this->PhotoID && $this->Photo())
return $this->Photo()->CMSThumbnail();
else
return '(No Image)';
}

//Return the link to view this Pug
public function Link()
{
if($PugPage = $this->PugPage())
{
return $PugPage->Link('show/') . $this->ID;
}
}

public function LinkingMode()
{
//Check that we have a controller to work with and that it is a PugPage
if($Controller = Controller::CurrentPage() && Controller::CurrentPage()->ClassName == 'PugPage')
{
//check that the action is 'show' and that we have a Pug to work with
if(Controller::CurrentPage()->getAction() == 'show' && $OwnPug = Controller::CurrentPage()->getOwnPug())
{
//If the current Pug is the same as this, return 'current' class
return ($OwnPug->ID == $this->ID) ? 'current' : 'link';
}
}
}

}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

This is the code i do use !! ( i haven't figured out how to use the fieldgroups in the tabs )
-------------------------------------------------------------------------------------------------------------------

class Mops extends DataObject
{
static $db = array(
'RoepNaam' => 'Varchar',
'KennelNaam'=> 'Varchar',
'StamBoomNaam' => 'Varchar',
'Geboren' => 'Date',
'DNA'=>'Boolean',
'Patella'=>'Varchar(10)',
'NHSB' =>'Int',
'Beschrijving' => 'HTMLText',
'URLSegment' => 'Varchar(255)',
'MetaTitle' => 'Varchar(255)'
);

//Set our defaults
static $defaults = array(
'RoepNaam' => 'New Mops',
'URLSegment' => 'new-mops'
);

static $has_one = array(
'Image' => 'Image',
'Stamboom' => 'Stamboom'
);

static $has_many = array(
'Showresultaten'=>'Showresultaat');

//Relatie met de Mopsen Paginas
static $belongs_many_many = array(
'MopsenPaginas' => 'MopsenPagina'
);

//Fields to show in ModelAdmin table
static $summary_fields = array(
'RoepNaam' => 'RoepNaam',
'URLSegment' => 'URLSegment',
'Price' => 'Price (£)'
);

//Add an SQL index for the URLSegment
static $indexes = array(
"URLSegment" => true
);

//Fields to search in ModelAdmin
static $searchable_fields = array (
'RoepNaam',
'URLSegment',
'Beschrijving',
'MopsenPaginas.ID' => array(
'title' => 'MopsenPagina'
)
);

function getCMSFields()
{
$fields = parent::getCMSFields();

//Main Tab

$fields->addFieldToTab("Root.Main", new TextField('RoepNaam', 'RoepNaam'));
$fields->addFieldToTab("Root.Main", new TextField('KennelNaam', 'KennelNaam'));
$fields->addFieldToTab("Root.Main", new TextField('StamBoomNaam', 'StamBoomNaam'));
$fields->addFieldToTab("Root.Main", new DatePickerField('Geboren', 'Geboren'));
$fields->addFieldToTab("Root.Main", new CheckboxField('DNA','DNA geregistreerd?'));
$fields->addFieldToTab("Root.Main", new TextField('Patella'));
$fields->addFieldToTab("Root.Main", new NumericField('NHSB'));
$fields->addFieldToTab("Root.Main", new TextField('URLSegment', 'URL Segment'));
$fields->addFieldToTab("Root.Main", new TextField('MetaTitle', 'Meta Title'));
$fields->addFieldToTab("Root.Main", new HTMLEditorField('Beschrijving'));

//MopsenPaginas
$MopsenPaginas = DataObject::get('MopsenPagina');
$fields->addFieldToTab("Root.MopsenPaginas", new CheckboxsetField('MopsenPaginas', 'MopsenPaginas', $MopsenPaginas));

//Images
$fields->addFieldToTab("Root.Images", new ImageField('Image', 'Image', Null, Null, Null, 'Uploads/mopsenpagina_banners'));

//Stamboom
$fields->addFieldToTab("Root.Stamboom", new HasOneDataObjectManager(
$this,
'Stamboom',
'Stamboom'
)
);
//Showresultaten
$fields->addFieldToTab("Root.Showresultaten", new HasManyDataObjectManager(
$this,
'Showresultaten',
'Showresultaat'
)
);

return $fields;
}

//Set URLSegment to be unique on write
function onBeforeWrite()
{
// If there is no URLSegment set, generate one from RoepNaam
if((!$this->URLSegment || $this->URLSegment == 'new-mops') && $this->RoepNaam != 'New Mops')
{
$this->URLSegment = SiteTree::generateURLSegment($this->RoepNaam);
}
else if($this->isChanged('URLSegment'))
{
// Make sure the URLSegment is valid for use in a URL
$segment = preg_replace('/[^A-Za-z0-9]+/','-',$this->URLSegment);
$segment = preg_replace('/-+/','-',$segment);

// If after sanitising there is no URLSegment, give it a reasonable default
if(!$segment) {
$segment = "mops-$this->ID";
}
$this->URLSegment = $segment;
}

// Ensure that this object has a non-conflicting URLSegment value.
$count = 2;
while($this->LookForExistingURLSegment($this->URLSegment))
{
$this->URLSegment = preg_replace('/-[0-9]+$/', null, $this->URLSegment) . '-' . $count;
$count++;
}

parent::onBeforeWrite();
}

//Test whether the URLSegment exists already on another Mops
function LookForExistingURLSegment($URLSegment)
{
return (DataObject::get_one('Mops', "URLSegment = '" . $URLSegment ."' AND ID != " . $this->ID));
}

//Generate the link for this Mops
function Link()
{
//if we are on a mopsen page return that
if(Director::CurrentPage()->ClassName == 'MopsenPagina')
{
$MopsenPagina = Director::CurrentPage();
}
//Otherwise just grab the first mopsenpagina this Mops is in
else
{
$MopsenPagina = $this->MopsenPaginas()->First();
}
//Check we have a mopsenpagina then return the link
if($MopsenPagina)
{
return $MopsenPagina->absoluteLink() . 'show/' . $this->URLSegment;
}
}

}
----------------------------------------------------------------------------------------------------------------------------
class MopsenPagina extends Page
{

static $has_one = array(
'MopsenPageBanner' => 'Image'
);

static $many_many = array(
'Mopsen' => 'Mops'
);

static $allowed_children = array(
'none' => 'none'
);

function getCMSFields()
{
$fields = parent::getCMSFields();

//Banner Images
$fields->addFieldToTab("Root.Content.Banner", new ImageField('MopsenPageBanner', 'Banner', Null, Null, Null, 'Uploads/mopsenpagina_banners'));

return $fields;
}
}

class MopsenPagina_Controller extends Page_Controller
{

static $allowed_actions = array(
'show'
);

//Return the list of mopsen for this mopsenpagina
public function getMopsenList()
{
return $this->Mopsen(Null, 'RoepNaam ASC');
}

//Get's the current mops from the URL, if any
public function getCurrentMops()
{
$Params = $this->getURLParams();
$URLSegment = Convert::raw2sql($Params['ID']);

if($URLSegment && $Mops = DataObject::get_one('Mops', "URLSegment = '" . $URLSegment . "'"))
{
return $Mops;
}
}

//Shows the Mops detail page
function show()
{
//Get the Mops
if($Mops = $this->getCurrentMops())
{
$Data = array(
'Mops' => $Mops,
'MetaTitle' => $Mops->MetaTitle
);

//return our $Data array to use, rendering with the MopsPage.ss template
return $this->customise($Data)->renderWith(array('MopsPage', 'Page'));
}
else //Mops not found
{
return $this->httpError(404, 'Sorry that mops could not be found');
}
}

//Generate out custom breadcrumbs
public function Breadcrumbs() {

//Get the default breadcrumbs
$Breadcrumbs = parent::Breadcrumbs();

if($Mops = $this->getCurrentMops())
{
//Explode them into their individual parts
$Parts = explode(SiteTree::$breadcrumbs_delimiter, $Breadcrumbs);

//Count the parts
$NumOfParts = count($Parts);

//Change the last item to a link instead of just text
$Parts[$NumOfParts-1] = ('<a href="' . $this->Link() . '">' . $Parts[$NumOfParts-1] . '</a>');

//Add our extra piece on the end
$Parts[$NumOfParts] = $Mops->RoepNaam;

//Return the imploded array
$Breadcrumbs = implode(SiteTree::$breadcrumbs_delimiter, $Parts);
}

return $Breadcrumbs;
}
}
-----------------------------------------------------------------------------------------------------------------------------
class MopsAdmin extends ModelAdmin {

public static $managed_models = array(
'Mops'
);

static $url_segment = 'mopsen';
static $menu_title = 'Mopsen';

}
----------------------------------------------------------------------------------------------------------------------------

class Showresultaat extends DataObject
{

static $db = array (
'Dog' => 'Varchar',
'Plaats' => 'Varchar',
'Datum' => 'Date',
'Klasse' => 'Varchar',
'Resultaat' => 'Varchar'
);

static $has_one= array ('Keurmeester'=>'Keurmeester',
'OwnPug' => 'OwnPug',
'Mops'=> 'Mops');

//Fields to show in the DOM
static $summary_fields = array(
// 'MopsID'=>'Mops',
// 'Dog' => 'Mops',
'Plaats' => 'Plaats',
'Datum' => 'Datum',
'Klasse' => 'Klasse',
'Resultaat' => 'Resultaat'
);

public function getCMSFields()
{

return new FieldSet(

new FieldGroup(
new DropdownField(
'MopsID',
'Selecteer Mops',
Dataobject::get("Mops")->map("ID", "RoepNaam", "Kies de juiste Mops")
)
),

new FieldGroup(
new DatePickerField('Datum')
),
new FieldGroup(
new TextField('Plaats'),
new TextField('Klasse'),
new TextField('Resultaat')
),
new HasOneDataObjectManager(
$this,
'Keurmeester',
'Keurmeester')

);
}
}
---------------------------------------------------------------------------------------------------------------------------

class Keurmeester extends DataObject
{

static $db = array (
'Titel' => 'Varchar(10)',
'Naam' => 'Varchar(30)',
'Land' => 'Varchar(20)'
);

static $has_many= array ('Showresultaten'=>'Showresultaat');

//Fields to show in the DOM
static $summary_fields = array(
'Titel' => 'Aanspreektitel',
'Naam' => 'Naam',
'Land' => 'Land'
);

public function getCMSFields()
{
return new FieldSet(
new TextField('Titel'),
new TextField('Naam'),
new TextField('Land','(NL) (SWE) (DTL) (IRE) (BLG) (NOR) (ZWI) (ESP) (UK) (ITA)') //todo: make it a dropdownfield
);
}
}

Avatar
swaiba

Forum Moderator, 1899 Posts

24 February 2011 at 5:33am

Edited: 24/02/2011 5:34am

Hi Stefdv,

When I use ModelAdmin and I want to change things I don't start with a completely new fieldset...

function getCMSFields() {
	//I start with...
	$fields = parent::getCMSFields();

	//then I'd create a tab if required
	$tab = $fields->findOrMakeTab('Root.Images');
	//and remove the current field and move it to the new tab...
	$fields->removeByName('ImageURL');
	$tab->push(new ImageField('ImageURL'));

	return $fields;
}

I also replace fields if I want to change them... I find it's much nice to use the fieldset provided than to create it from scratch each time... might this help?

Avatar
Stefdv

Community Member, 110 Posts

24 February 2011 at 5:46am

Hi Swaiba,

"Might this help ?" Well absolutely, that's a nice solution ( so much to learn, guess i really need to read the docs ).

Still got the issue with the FieldGroup. With them i can place more fields on one line. For some ( the most ) fields i don't need the whole screen. Lets say for a textfield with varchar(10) i only need an input field of 10 char. not the whole screenwith.

And with the showresults) ...how do i only show the related showresults and not the whole list of all the showresults of all dogs?

TX again.

Avatar
swaiba

Forum Moderator, 1899 Posts

24 February 2011 at 5:53am

re:grouping fields...

http://www.silverstripe.org/customising-the-cms/show/15655

re:relatedshowresults

could you screen print and annotate to describe it?

Avatar
Stefdv

Community Member, 110 Posts

24 February 2011 at 5:55am

Swaiba, get right on it

tx you so much for your time

Avatar
Stefdv

Community Member, 110 Posts

24 February 2011 at 6:28am

Swaiba,

I have 3 screens attached.
Step 1 ; Here i choose the dog i need to edit.
Step 2 ; Here you see the Main Tab. As you can see the Fields are to big, but i'll get to that later.
Step 3; The 'Showresults'. I only need the results for the dog i selected in step 1. And when i add a result i need it to 'know' that it belongs to that dog.

Attached Files
Go to Top