Creating RSVP in PHP/MySQL w/ Zend Framework

This post is to share the php/zend framework code I used to create an rsvp for my wedding site. I’m not going into all the details since that would take too long ;p but all the code is available if you want to use it. This was created using the zend framework version 1.7.

So I’m getting married in two month and for our wedding my fiancee and I decided to create a website for our guests. The site includes information such as location, time, links to registries, maps, and a section to rsvp. The site was made by my fiancee in html and css. When she was done, I ported it over to zend framework and started creating the rsvp section which I’ll describe next. You can view the finished wedding site here:

RSVP Page

http://www.joeyrivera.com/wedding

The objectives of the rsvp are the following:

  • Allow guest to enter their code
    • each invitation that goes out has a code in it specific to the ‘family’.
  • Validate code from database and load information about that family
    • return the family name and how many seats they have available. Because of seating limitations, we only allow x amounts of seats per family. Ex: A friend could have 2 seats available in case they are coming with a guest.
  • Let guest select if they attending, if so, select how many guests are coming with an optional comments field
  • Submit and save their rsvp in the database and email us with the details

The database structure is very simple, only one table that looks like:

DROP TABLE IF EXISTS `family`;
CREATE TABLE  `family` (
`family_id` int(10) unsigned NOT NULL auto_increment,
`alias` varchar(100) NOT NULL,
`code` smallint(5) unsigned NOT NULL default '0',
`attending` tinyint(1) default NULL,
`available_seats` tinyint(3) unsigned NOT NULL,
`confirmed_seats` tinyint(3) unsigned default NULL,
`comments` varchar(255) default NULL,
`last_access` datetime default NULL,
PRIMARY KEY  (`family_id`),
UNIQUE KEY `Index_2` USING BTREE (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=latin1;

The fields are:

  • Alias is the ‘description or name’ for the family such as Ashley and Joey Rivera or The Rivera’s.
  • Code is the unique code we send out with each invitation.
  • Attending is a boolean that is updated when the guest rsvps.
  • Available seats is the number we set to limit how many people can come from that family.
  • Confirmed seats is the number the guest sets when rsvping.
  • Comments is optional
  • Last access tracks the last time that row was updated

I made code unique because it should be, we don’t want to accidentally assign two codes to the same family. We don’t want to use the family id as the code because we want the code a bit harder to guess if someone feels like fooling around with the system – we are hoping our family members and friends won’t purposely try to break the system though :p.

Here is the code:

<?php

class RsvpController extends Zend_Controller_Action
{
	protected $_redirector = null;

	public function init()
	{
		$this->_redirector = $this->_helper->getHelper('Redirector');
	}

	public function indexAction()
	{
		$this->view->form = $this->rsvpForm();
	}

	public function submit1Action()
	{
		// get and filter code
		$filters = array(
			'*' => 'StringTrim'
		);
		$validators = array(
			'Digits'
		);
		$input = new Zend_Filter_Input($filters, $validators, $this->getRequest()->getParams());
		// verify code was passed
		if(!$input->isValid('code'))
		{
			// go back with error message
			$this->_redirect('/rsvp');
		}
		$code = $input->code;
		// get family from code
		$family = new Family();
		$family_row = $family->fetchRow('code = ' . $code . '');
		// if family doesn't exist, leave
		if(empty($family_row))
		{
			$this->_redirect('/rsvp');
		}
		// track row in session
		$session = new Zend_Session_Namespace('family');
		$session->code = $code;
		$session->row = $family_row;
		// all is good, give view data
		$this->view->family = $family_row;
		$this->view->form = $this->familyForm($family_row);
	}

	public function submit2Action()
	{
		// validate session
		$session = new Zend_Session_Namespace('family');
		if(!isset($session->row))
		{
			$this->_redirect('/');
			return;
		}
		$form = $this->familyForm($session->row);
		// get vars to check
		$attending = $this->getRequest()->getParam('attending');
		$seats = $this->getRequest()->getParam('seats');
		// make sure data is good
		// if attending but seats is 0 then ask them to select how many seats
		// if the seats is greater than available seats error out
		if(($attending && !$seats) || ($attending > $session->row->available_seats))
		{
			// assumed by passing error on element would trigger this but doesn't seem too
			$form->markAsError();
			$seats_element = $form->getElement('seats');
			$seats_element->addError('Please select how many people are coming.');
		}
		//else if
		// if not attending but selected seats, ask them about it
		if(!$attending && $seats)
		{
			$form->markAsError();
			$attending_element = $form->getElement('attending');
			$attending_element->addError('You selected you are not coming but set the number
				of seat to a number greater than 0. Did you mean to say you are attending?');
		}
		// if the form has an error, it can still be valid so need to check for both
		if($form->isErrors() || !$form->isValid($_POST))
		{
			$form->populate($_POST); // for some reason have to manually call this or values don't show
			$this->view->form = $form;
			$this->view->family = $session->row;
			$this->render('index');
			return;
		}
		// update family
		$family = new Family();
		$family->update(array(
			'attending' => $form->getValue('attending') ,
			'confirmed_seats' => $form->getValue('seats') ,
			'comments' => $form->getValue('comments') ,
			'last_access' => date('Y-m-d H:i:s')
		), 'code = ' . $session->code . '');

		// email
		$mail = new Zend_Mail();
		$mail->setBodyText('New RSVP submitted.');
		$mail->setBodyHtml('<p>New RSVP submitted:</p>
							<p>' . $session->row->alias . '</p>
							<p>Attending: ' . $form->getValue('attending') . '</p>
							<p>Seats: ' . $form->getValue('seats') . '</p>
							<p>Comments: ' . $form->getValue('comments') . ' </p>');
		$mail->setFrom('joey@joeyrivera.com', 'JoeyRivera.com');
		$mail->addTo('joey1.rivera@gmail.com', 'Joey Rivera');
		$mail->addTo('person@person.com', 'Ashley Fleishel');
		$mail->setSubject('Wedding New RSVP');
		$mail->send();

		$this->_redirect('/rsvp/done');
	}

	public function doneAction()
	{
		// unset session
		$session = new Zend_Session_Namespace('family');
		$session->unsetAll();
	}

	private function rsvpForm()
	{
		$form = new Zend_Form();
		$form->setAction('/rsvp/submit1')->setMethod('post')->setAttrib('id', 'rsvp');
		$form->addElement('text', 'code', array(
			'label' => 'RSVP Code (found on your invitation)' ,
			'validators' => array(
			'digits'
		) , 'required' => true
		));
		$form->addElement('submit', 'submit');
		return $form;
	}

	private function familyForm($family)
	{
		$form = new Zend_Form();
		$form->setAction('/rsvp/submit2')->setMethod('post')->setAttrib('id', 'rsvp');
		$form->addElement('radio', 'attending', array(
			'label' => 'Are you attending?' ,
			'multiOptions' => array(1 => 'Yes' , 0 => 'No') ,
			'validators' => array(
			'Digits'
		) , 'required' => true
		));
		// create array of seats
		$seats = array();
		for($x = 0, $max = $family->available_seats; $x <= $max; $x++)
		{
			$seats[$x] = $x;
		}
		// limit number to available seats from row session
		$form->addElement('select', 'seats', array(
			'label' => 'How many will be attending?' ,
			'multiOptions' => $seats ,
			'required' => true
		));
		$form->addElement('textarea', 'comments', array(
			'label' => 'Comments' , //'validators' => array(
		//	'Alnum'
		//),
		'required' => false , 'width' => 250
		));
		$form->addElement('submit', 'submit');
		return $form;
	}
}

I’ll summarize what I’m doing with the code. I have 4 actions in my RsvpController:

index

  • This action display the rsvpForm in the view which is a input box for the guests to type in their family code.

submit1 (I know, name sucks but I was going for something quick ;p)

  • This action will validate the code submitted by the index action.
  • It then creates an instance of family using a zend db table model and loads the data from the database for the family that matches that code.
  • If it’s a real family, a session var is created with the family data and the form familyForm is displayed. Else, the user is taken back to the index action.

submit2

  • When the familyForm is submitted in submit1, this action validates that there is a family session var.
  • Then it does a few validations more such as making sure that the family seats is a number greater than 0 if they are attending. Or didn’t choose a number of seats greater than 0 if they are not attending (in case they accidentally hit not coming but did want to).
  • Then it validates the submitted form – I put it at the end because it seemed as if it would be less code that way. You can read the comments to see why I did what I did, I had some issues with the way I was expecting the form zend framework class to behave.
  • If all is well, the family row in the database is updated and an email is sent to myself and fiancee.

done

  • Displays a done message and the rsvp process is complete!

That’s about it. A couple quick thoughts or comments about this. The form could be made more secure but like I said before, for this project I think it’s fine. Also, you’ll see a bunch of css in the views, it’s because I was trying to port the site over quickly and that was the quickest way. If you have any specific questions feel free to ask. Hope you find this useful. Below are some screen shots of the final product and a zip file of the code including the model, the rsvp controller, and the views in the application folder:

RSVP Files

index:

submit1:

done:

24 thoughts on “Creating RSVP in PHP/MySQL w/ Zend Framework”

  1. Hi I was looking for something like this for my friends wedding.

    I was just looking at the files but don’t see a file called submit 2. Is it missing?

    Should I copy and paste the files in the formated folders into my main directory?

    Thanks so much.

  2. Enrique,

    The submit2 action doesn’t have a view file associated with it. It will either renders another view or redirect depending on what happens.

    What do you mean by formated folders? To use this code as is, you will need to be using the Zend Framework (I used 1.7 for this project). You can create a new empty project and then replace your application folder with the files from the zip file provided above.

  3. Thanks Joey for the reply.

    Yeah, just realized that the php structure is a little different with the Zend Framework.

    I’m structuring my friends site using OScommerce. The php is a bit different.

    Now very good with php and sql but I’m going to see if I can play with your code and see if I can make it work somehow.

    Thanks,

  4. Hi Joey, I really like your script and want to put it on our site… though I’m really stuck on how to assemble it in my domain space and php/mysql database. Basically I am a dummy and need to know how to assemble it. Exactly how do I set up Zend Framework on my site and how does it work in compliance to this code/applet?

  5. Wow, this is an amazing script. I’d love to use this on my website for our wedding, but our web hosting doesn’t have zend or a way to modify the php.ini so there goes that idea!

    Good job on the codes though Joey. Congrats also and have a wonderful marriage 🙂

  6. Hi Joey, I really like your script. I’m working on an asp.net wedding website with an RSVP and this is the best example I’ve come across after a 7 hour web trawl (yes; even though it’s php!) Thanks & Congratulations! 🙂

  7. Any suggestions or help on how to do this on a mac? I am creating my site through iWeb, just for the purpose of simplicity, and I am really wanting to use this type of RSVP form.

    Thanks!

  8. Thanks Joey!

    I am actually creating my site on iWeb and hosting it through GoDaddy. I am wanting to create something that my guests can search by their last name, and it will display the people that they can RSVP for. Could you help me write the code for this? I am very lost lol.

    Thanks!

    1. Joel, unfortunately other than what I have posted I’m not sure I can do much more other than try storing all the names in a db or an xml file that you can then search through. Good luck with your project.

  9. Any reason why you chose to use Zend, I’m having trouble wrapping my head around it… I’m trying to do the same thing with just php and mysql. I’ve already set up the database and now I just need to figure out how to query/update via php actions. Dreamhost is my host, and although they provide directions on how to get zend up and running, they say if I break something I’m SOL…

    1. Lee,

      I have been using Zend for some time now and I’m at the point where I think using Zend makes me more efficient and productive and that is why I use Zend for most of my php projects. You can dissect the code from my post and create a couple stand alone php pages that do the same though.

      Joey

      1. Thanks again for the code! I’ve managed to get the zend framework up on my host, but I’ve run into a roadblock. I’d like to drag and drop your files on my host so I can see it all in action and make changes on the fly. Can you point me in the right direction of which file goes where? Do I have to create a separate html file loading the rsvp controller? I’m lost =X … thanks for your help!

        1. Hey Lee, first I would recommend reading the Zend getting started guide: http://framework.zend.com/manual/en/learning.quickstart.intro.html. Next to answer your question, you would want to copy/paste the RsvpController to your controller folder. Then copy the 3 view scripts into your views folder /scrips/rsvp. Now here is the tricky part, this code was written a while ago and the newer versions of the Zend Framework are setup a bit differently. You should have a bootstrap file under application, in that file you’ll want to init your db. Finally copy the Family class into your models folder and I think that should be it.

  10. Hi,
    I need a little help here!
    Can you write step by step how to do it?
    I already have the RSVP Files. What to do next?
    Thanks

    Daniel from Brasil

    1. Daniel,

      Hi, I wrote this blog post a long time ago and I would only use what I have here for theory and ideas on how to build something similar but the code is using a older version of Zend Framework that has changed a lot over time.

      Joey

Leave a Reply to Joey Cancel reply

Your email address will not be published. Required fields are marked *