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.

Data Model Questions

onBeforeWrite called multiple times


Go to End
Reply

9 Posts   3023 Views

Avatar
Nathan Cox

9 May 2009 at 3:43pm Community Member, 99 Posts

Hi, I'm making a site in 2.3.1 and trying to put some code in Page::onBeforeWrite().
The problem is, onBeforeWrite always gets called multiple times - twice if I just click "save", four times if I click "save and publish".

Is this the normal behaviour? What can I do to just get it to run some code once?

Avatar
UncleCheese

10 May 2009 at 6:24am 4085 Posts

Yes! I made a post about this a while back, as well. Annoying, isn't it? My solution was really crude. I set a static class variable to choke the onBeforeWrite() after the first execution.

static $has_written = false;

public function onBeforeWrite()
{
if(!self::$has_written) {
// do stuff
self::$has_written = true;
}
parent::onBeforeWrite();
}

I'd really like more information about it, though, cause as you can see, it's a total hack and should not be necessary.

Avatar
Nathan Cox

10 May 2009 at 3:14pm Community Member, 99 Posts

Yeah this is making no sense to me at all...unfortunately your method doesn't entirely work for me since if I only make a change on one of the iterations it seems to get overwritten by later ones.
For example, I tried just adding "-test" to the URLSegment in onBeforeWrite, but if I use a static var to only do it once the change shows up in the sitetree table/cms but it it doesn't add -test to sitetree_live, so doesn't show up on the frontend. Without the static var filter I end up with things like -test-test on my URLSegment.

I did a dump of $this and compared all four times it ran. I'm wondering if it runs for every table attached to the object? The first one doesn't show the newly posted data or have any of the class-specific $db fields. It makes a new version number every time, though. The status attribute goes Published -> Saved (update) -> Published -> Published, and each time the changed and original arrays do or don't have different attributes but I'm not seeing a pattern.

So in short I don't know why it does this but it's stuffing up the probably-way-too complicated bit of hacking I was trying to do here :/

Avatar
Ingo

11 May 2009 at 8:44pm Forum Moderator, 801 Posts

Have a look in LeftAndMain->save() - if you hit "Save and Publish" in the CMS, these four lines cause the record to be written:
$record->writeWithoutVersion();
$record = $record->newClassInstance( $newClass );
$record->write();
$record->doPublish();

There's no easy way around this, as far as I can see we need to write at least twice. In case of the "-test-test" problem, you'll have that as well if the record persists a bit longer in memory than you think in different cases. The easiest solid way is to make sure you didn't add "-test" already I guess? You can also use getChangedFields() to detect if any fields have changed (which gets reset after each write call). So in case of the URL, you could just react in your onBeforeWrite() if the URL has actually changed.

Avatar
Fuzz10

11 June 2009 at 8:42pm Community Member, 787 Posts

;-)

Just bumped into this myself just now. Interesting bug.

Someone made a ticket for this already ?

Avatar
Ben Gribaudo

12 June 2009 at 3:40am Community Member, 181 Posts

It would be nice for this issue to be fixed!

Avatar
Harley

2 November 2009 at 11:37am Community Member, 153 Posts

I'm also having this trouble, would be good if there was a fix. Any updates?

Regards

Harley

Avatar
dalesaurus

6 November 2009 at 10:41am Community Member, 283 Posts

Just ran into this and am successfully using UncleCheese's hack. Effective!

Go to Top