Note:
This article is up to date through revision 7136. No promises after that - but I will try to stay up to date.
Now that we've got a good base down for how widgets and validators work, we're going to extend our application. Today's work will be to add articles for our author, and we'll see lot's more new widgets and validators. Let's review the original schema.
propel:
author:
_attributes: { phpName: Author }
id:
first_name: varchar(30)
last_name: varchar(30)
email: varchar(75)
website: varchar(100)
birthday: date
years_experience: integer
bio: longvarchar
article:
_attributes: { phpName: Article }
id:
author_id:
body: longvarchar
file_attachment: varchar(255)
We've handled the author, now onto the articles. Currently, after we add an author, we clear the form so the user can add another author. Let's change that behavior; when a user creates an author, let's forward him/her to a new form where she can add articles for that author.
public function executeEditAuthor()
{
$this->form = new AuthorForm();
if ($this->getRequest()->isMethod('post'))
{
$this->form->bind($this->getRequestParameter('author'));
if ($this->form->isValid())
{
$this->form->updateObject();
$this->form->save();
$this->getUser()->setFlash('message', 'author saved successfully');
$this->redirect('/articles/editArticle?id='.$this->form->getObject()->getId());
}
}
}
Here's our new action to handle the articles:
public function executeEditArticle()
{
$this->form = new ArticleForm();
if ($this->getRequest()->isMethod('post'))
{
$this->form->bind($this->getRequestParameter('article'));
if ($this->form->isValid())
{
$this->form->updateObject();
$this->form->save();
$this->getUser()->setFlash('message', 'article saved successfully');
$this->form = new ArticleForm();
}
} else {
$this->author = AuthorPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forwardUnless($this->author, 'articles', 'editAuthor');
// Let's set the author_id field to be the given author by default
$this->form->setDefault('author_id', $this->author->getId());
}
}
In the template editArticleSuccess:
hasFlash('message')): ?>
= $sf_user->getFlash('message'); ?>
What have we done? The exact same thing as before. In fact, it's so repetitive that I might consider having a form partial or even consolidating the work in the action. If you try to load your form, you will get an error, there's one more piece we're missing:
In the model class Author:
getFirstName().' '.$this->getLastName();
}
...
}
The relationship select field echoes the object itself to get it's text for the select options. To handle this, we can simply add our __toString() method.
So this time around, setting up a new form was pretty easy. And that's the beauty of the new system. Our form still needs some work, but that won't take long either. Browse to the ArticleForm.class.php file so we can tidy up our form.
public function configure()
{
$this->widgetSchema['file_attachment'] = new sfWidgetFormInputFile();
$this->validatorSchema['body']->setOption('required',true);
$this->validatorSchema['file_attachment'] = new sfValidatorFile();
$this->validatorSchema['file_attachment']->setOption('mime_types', array('application/pdf'));
$this->validatorSchema['file_attachment']->setOption('max_size', 1024);
}
This does several things. First, we change our file_attachment field from a text input to a file input. Remember, now that we're manually printing out the form tag, we'll need to add the multipart enctype also:
...