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.

DataObjectManager Module /

Discuss the DataObjectManager module, and the related ImageGallery module.

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

How/Where to Do Something when altering manymany relation


Go to End


7 Posts   2468 Views

Avatar
silk

Community Member, 18 Posts

7 January 2010 at 7:12am

Hello,

I want to make a module for configuring majordomo mailing list. Configuring, like adding and removing members is done via mail.
I keep track who is currently in the list in a database table. Inserting and removing from the database works. But where do I put the code for sending the mail to the majordomo server?

Example:
For each member new to the database table I have to send a line like
subscribe...

A similar line has to be send when a member has to be removed.
Where to put it? onBeforeWrite()?
My code right now is:

class MailinglistePage extends Page {

static $db = array(
'Description'=>'Text',
'EMail'=>'Text'
);
static $has_one = array('Admin'=>'Member'
);

static $many_many = array('MailUser'=>'Member'
);

public function getCMSFields()
{
$f = parent::getCMSFields();
$f->addFieldToTab('Root.Content.Main', new TextField('Description', 'Description'));
$f->addFieldToTab('Root.Content.Main', new EmailField('Description', 'Description'));
$f->addFieldToTab("Root.Content.Mitglieder", new ManyManyDataObjectManager(
$this,
'MailUser',
'Member',
array('Surname' => 'Surname',
'Firstname'=>'Firstname',
'Email'=>'Email'
),
'getCMSFields'
));
return $f;
}

function onBeforeWrite() {

// CAUTION: You are required to call the parent-function, otherwise sapphire will not execute the request.
parent::onBeforeWrite();
}
}

Avatar
UncleCheese

Forum Moderator, 4102 Posts

7 January 2010 at 7:43am

onBeforeWrite() should work fine, but maybe onAfterWrite() is a safer bet because you know at that point that the record has been written.

Avatar
silk

Community Member, 18 Posts

7 January 2010 at 7:58am

Which is the best way to obtain which Members are in my list?
Is there a way to get only the new members?

Avatar
UncleCheese

Forum Moderator, 4102 Posts

7 January 2010 at 8:32am

I'm not sure what you mean by "new".. what would make someone new? Created in the last day? Week?

You can get all the user records associated with that page by running the relation as a function..

$yourMalinglistePage->MailUser();

Generally you should name your has_many and many_many relations in the plural, since they can return multiple records, but in your case you've named it MailUser, so you have to use that..

Avatar
silk

Community Member, 18 Posts

7 January 2010 at 11:19am

Edited: 07/01/2010 11:26am

Sorry for being so unclear, you understood correctly.

Now I have a problem you also have dealt with according to the forums.

My new code is as follows:

(...)

function onBeforeWrite() {    
       parent::onBeforeWrite();
    
       $this->oldUsers=$this->MailUsers()->getIdList();
       foreach ($this->oldUsers as $user){
           print '// +++++++++++++++++ '.$user.' +++++++++++++ \n';      
       }    
}

function onAfterWrite() {    
       parent::onAfterWrite();    
        
       $nowUsers=$this->MailUsers()->getIdList();    
       foreach ($nowUsers as $user){
           print '// ################# '.$user.' ############# \n';
       }      
}

In my test I have three Members with Id's 5, 6, 7 and I remove two of them. Then I press Save.
Debugging Output is:
// +++++++++++++++++ 6 +++++++++++++ 
// +++++++++++++++++ 5 +++++++++++++ 
// +++++++++++++++++ 7 +++++++++++++ 

// ################# 6 ############# 
// ################# 5 ############# 
// ################# 7 ############# 

// +++++++++++++++++ 7 +++++++++++++ 

// ################# 7 ############# 

This shows:
1. onBefore- and onAfterWrite is called twice. In your old posts about this issue you said it might depend on the number of relations. Same here: Two relations (1 has_one, 1 manymany). Did you find anything out to deal with this?
2. Even more severe: The table seems to change *between* calling onAfterWrite() and the second onBeforeWrite()!
Shouldn't be the point for having those two functions to make clear this does not happen?

Avatar
UncleCheese

Forum Moderator, 4102 Posts

7 January 2010 at 11:35am

A lot of times what I do when you have a really specific onBeforeWrite() handler is to set a static class property to count the number of times onBeforeWrite() has been run. If it is the number that you want, you can run your code, but otherwise save it until everything is the way you want it.

static $write_count = 0;

public function onBeforeWrite() {
self::$write_count++;
parent::onBeforeWrite();
if($write_count == 3)
// do stuff

}

Avatar
silk

Community Member, 18 Posts

7 January 2010 at 10:18pm

I thought about something like this, but what is with the second point?

The changes to the database table do not seem to happen between OnBeforeWrite and OnAfterWrite, but before OnBeforeWrite!

I have removed all but my manymany relation. With newly created database table OnBeforeWrite and OnAfterWrite are executed only once and the database table has already entries in OnBeforeWrite. Next time when hitting 'Save' they are executed twice. Now the changes to the database table happen between the first OnAfterWrite and the second OnBeforeWrite.
This is bad for me, because I want to find out which entries have been added and removed (by comparing before state and after state).