views:

312

answers:

3

Hi,

I've been looking at this event-listeners page http://www.doctrine-project.org/documentation/manual/1_1/pl/event-listeners and I'm not sure which is the listener I have to use to make a change after the doSave() method in the BaseModelForm.class.php.

// PlaceForm.class.php
protected function doSave ( $con = null )
{
  ...
  parent::doSave($con);
  ....

  // Only for new forms, insert place into the tree
  if($this->object->level == null){

    $parent = Place::getPlace($this->getValue('parent'), Language::getLang());
    ...
    $node = $this->object->getNode();
    $method = ($node->isValidNode() ? 'move' : 'insert') . 'AsFirstChildOf';
    $node->$method($parent); //calls $this->object->save internally
  }

  return;
}

What I want to do is to make a custom slug with the ancestors' name of that new place. So if I inserting "San Francisco", the slug would be "usa-california-san-francisco"

public function postXXXXXX($event)
{
  ...
  $event->getInvoker()->slug = $slug;
}

The problem is that I'm inserting a new object with no reference to its parent. After it's saved, I insert it to the tree. So I can't change the slug until then.

I think a Transaction listener could work, but I'm use there is a better way I'm not seeing right now.

thanks!

A: 

Firstly, I'd put this into the model rather than the form - that way if the object is ever edited/updated the behaviour would still happen.

In the form though, I'd use updateObject:

function updateObject($values = array()) {
  parent::updateObject($values);
  // do your stuff
}

In the model (looks like you are using doctrine ...) I'd put this into the postSave() method. As I say, I think its better there than the form.

benlumley
i can't use any of the two solutions. I'm inserting a new object so I can't use updateObject(). About the postSave() method, the problem is that my model is I18N so how I can save the slug after the object, its translation and the doSave() are done?
fesja
updateObject is called when a form updates the object with the data from the form. its called for new and updated objects, the word update doesn't refer to updating the database in this case.And the postSave method is called after save ... hence the name!
benlumley
+1  A: 

You are looking at the wrong piece of code. As stated by benlumley, you should manage your slug directly in the model, not in the form. To achieve what you want (a recursive slug) is quite easy using doctrine's Sluggable behavior. You need to implement a getUniqueSlug() into your model so that it gets called by the behavior (it's automatic) and handle your slug specifities in there:

public function getUniqueSlug()
{
  $slug = '';                                                                                                                                                                       
  $parent = $this->getParent();
  if ($parent->exists())
  {   
    $slug = $this->getParent()->getUniqueSlug().'-';
  }   
  return $slug.$this->getName();
}

What we do here is basically traverse all the ancestors of the current object and append the slugs on the go (replace the getParent() by whatever method you use to retrieve an object's parent.

Geoffrey Bachelet
A: 

Hi,

I had the same problems, and the Doctrine_Record::postInsert(Doctrine_Event $event) method did not work for me. Indeed the node aren't hydrated yet.

I had to overwrite the sfFormObject::doSave method like this:

protected function doSave($con = null)
{
    $is_new = $this->isNew();
    parent::doSave($con);
    $this->doSaveNestedSet($con);

    $service = $this->getObject();
    if( $is_new and ! $service->getClientId() and $parent = $service->getParent())
    {
        $service->setClient($parent->getClient());
        $service->save();
    }
}
Florian