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

How to save relations explicitely?


Go to End


4 Posts   3754 Views

Avatar
zatic

Community Member, 3 Posts

23 March 2009 at 5:36am

Hello,

I am following the tutorial to create a simple site where logged in users can upload PC game replays. Creating registration and the upload form was very easy. But now I am stuck.

I use the objects Replay, ReplayPage, Member. A ReplayPage has 1 Replay and 1 Member (the uploader). See the DataObject code below.

I can take the data from the upload form and save it into the respective database objects without any problem. However, I am not able to save any relations between the objects. After all objects are saved, ReplayPage.ReplayID and ReplayPage.UploaderID are both "0".
I tried setting the relation using setComponent() and by directly setting the ReplayPage->Replay = $replay.

Maybe I am overlooking something very simple - but how can I save a relation to the database?

Note: My Replay objects all have a File object attached after I call $form->saveInto() - so that part works. But how can I set a relation explicitly?

Here is the code from my Upload action:

$replay = new Replay();
		$replayPage = new ReplayPage();
		
		$form->saveInto($replayPage);
		
		$form->saveInto($replay);
		
		Debug::message("Replay: "
			.$replay->write(true, false, false, true));

		$replayPage->setComponent('Replay', $replay);
		
		$loggedIn = Member::currentUser();
		Debug::message("User: ". $loggedIn->getName()); 
		
		$replayPage->setComponent('Uploader', $loggedIn);
		
		Debug::message("ReplayPage: "
			.$replayPage->write(true, false, false, true));
			
		$replay->write();
		$replayPage->write();

Here are the data objects:

<?php
 
class ReplayPage extends Page {
	
	static $db = array(
		'Title' => 'Varchar',
		'Description' => 'Text',
		'UploadDate' => 'Date'
	);
	
	static $has_one = array(
		'Uploader' => 'Member',
		'Replay' => 'Replay'
	);
	
	static $has_many = array(
		'Comments' => 'Comment'
	);	
	
	static $many_many = array(
		'Tags' => 'Tag'
	);  
	
	/**
   	 * @param DataObjectSet
     */
	function addTag($additionalTags) {
  		$existingTags = $this->Tags();
   
	  	foreach($additionalTags as $tag) {
	    	$existingTags->add($tag);
		}
  	}
  	
  	function setReplay($replay) {
  		$this->setComponent('Replay', $replay);
  	}
  	
}

class ReplayPage_Controller extends Page_Controller {
	
}
?>

<?php

class Replay extends DataObject {
	
	static $db = array(
		'Map' => 'Varchar'
	);
	
	static $has_one = array(
		'File' => 'File'
	);	
}
?>

Avatar
Sean

Forum Moderator, 922 Posts

23 March 2009 at 9:15pm

You can set them explicitly, by setting the field directly which is the foreign key. e.g.

$obj->UploaderID = Member::currentUserID();

Alternatively, saveInto() on the Form object will save the relationships if you set the fields to the same name(s) in your form. e.g.

new DropdownField('UploaderID', 'Select an uploader', DataObject::get('Member')->map())

OR, if you want to save the current user logged in:

new HiddenField('UploaderID', '', Member::currentUserID())

Cheers,
Sean

Avatar
zatic

Community Member, 3 Posts

23 March 2009 at 11:49pm

Thank you Sean!

So suppose I have several related objects in memory, but not yet saved, I would have to save them one by one and then update related objects with the IDs?

Or is there also a way to save a cascade of objects similarly to what saveInto() does, but independent of forms?

Avatar
marcius

Community Member, 2 Posts

7 April 2009 at 12:44am