Symfony 1.2 - using sfForm with jquery validation plugin - part 2

New jQuery 1.3 and its user interface have a lot of great features. But if we want to use our jQuery validation plugin with 1.3 version we need to upgrade plugin version to 1.5.1 (or higher), which is still compatible with 1.2.6. New Validate Plugin version (1.5.2) came up with some nice features like integration with UI Tabs. The following example shows a real implementation of user profile form divided in three sections.

In my example i will use sfGuardPlugin + one table for user profile.

First, we need to generate new project, new application and setup database configuration:


<?php

    symfomy generate:project sfTest
    symfomy generate:app frontend
    symfomy configure:database "mysql:host=localhost;dbname=sf_test" user pass

?>

Next step is to install sfGuardPlugin:


    symfony plugin:install sfGuardPlugin

and enable it according to its documentation.

Now we can put profile table structure into schema.yml file:


propel:
  sf_guard_profile:
    id: ~
    user_id: { type: integer, foreignTable: sf_guard_user, foreignReference: id, required: true, onDelete: cascade }
    email: { type: varchar(128), index:unique, required: true }
    name: { type: varchar(128), required: true }
    surname: { type: varchar(128), required: true }
    education: longvarchar
    company: varchar(128)
    position: varchar(128)
    phone_number: { type: varchar(30), required: true }
    fax: varchar(25)
    comunicator: varchar(30)
    country: { type: varchar(128), required: true }
    city: { type: varchar(128), required: true }
    province: { type: varchar(128), required: true }
    address: { type: varchar(255), required: true }
    zipcode: varchar(15)

Remember to set profile configuration into app.yml:


all:
  sf_guard_plugin:
    profile_class: SfGuardProfile
    profile_field_name: user_id

Then:


    symfony propel:build-all

and create module for our example:


    symfony generate:module frontend user

Now we need to download all neccessary JavaScript files:

  • jquery-1.3.2.js
  • jquery-ui-1.7.1.js
  • jquery.validate-1.5.2.js

As i did in the previous post , after downloading new jquery validation plugin we need to make some changes in jquery.validation.js file, so it could work properly with Symfony sfForm (conversion form “name” to “id”). You can find corrected file here.

We can put our bussiness logic to executeProfile action into actions.class.php but earlier we have to create our ProfileForm.class.php - we can put that file into global lib/form/ directory or lib/form of current module.
ProfileForm.class.php:


<?php

class ProfileForm extends sfGuardUserAdminForm {

  public function configure() {

  	parent::configure();

	$this->unsetAllExcept(array(
		'username',
		'email',
		'name',
		'surname',
		'education',
		'company',
		'position',
		'phone_number',
		'phone_number_2',
		'fax',
		'communicator',
		'country',
		'city',
		'province',
		'zipcode',
		'address',
		'address_2'
	));
	 # Edit default validators schema

	$this->validatorSchema['email'] = new sfValidatorEmail();

    $this->widgetSchema->setNameFormat('profile[%s]');
  }

	protected function doSave($con = null){

	    if (is_null($con)) {

	      $con = $this->getConnection();
	    }

	    $this->updateObject();

	    $this->object->save($con);
	}
}
?>

The unsetAllExcept method was presented in this post.

actions.class.php:


<?php 

class userActions extends sfActions {

  public function executeIndex(sfWebRequest $request) {

  	$this->forward('user', 'profile');
  }

  public function executeProfile($request) {

  	$user = $this->getUser()->getGuardUser();

  	$this->form = new ProfileForm($user);

  	if ($request->isMethod('post') && $request->hasParameter('profile')) {

  		$this->form->bind($request->getParameter('profile'));

  		if ($this->form->isValid()) {

  			$this->form->save();

  			$this->getUser()->setFlash('msg', 'Your profile has been successfully updated');
  		} else {

  			$this->getUser()->setFlash('msg', 'Sorry, there are some errors listed below. ');
  		}
  	}
  }
}

?>

Nothing special so far, but now we need to take care of our view file.
In profile template we have to split form into for example three sections: identity, experience and location. Then we can add jquery tabs and validation:

profileSuccess.php:


	<h1> Update user profile</h1>

	<?php if ($sf_user->hasFlash('msg')): ?>

	  <div class="message"><?php echo $sf_user->getFlash('msg') ?></div>

	<?php endif; ?>

	<form action="<?php echo url_for('user/profile') ?>" id="profileForm" method="post" >

	<div id="tabs">

	    <ul>
	        <li><a href="#identity"><span>Identity data</span></a></li>
	        <li><a href="#experience"><span>Experience/Job information</span></a></li>
	        <li><a href="#location"><span>Location</span></a></li>
	    </ul>

	    <div id="identity">

			<table>

				<?php echo $form['username']->renderRow() ?>
				<?php echo $form['email']->renderRow() ?>
				<?php echo $form['name']->renderRow() ?>
				<?php echo $form['surname']->renderRow() ?>

			</table>
		</div>

		<div id="experience">

			<table>

				<?php echo $form['education']->renderRow() ?>
				<?php echo $form['company']->renderRow() ?>
				<?php echo $form['position']->renderRow() ?>
				<?php echo $form['phone_number']->renderRow() ?>
				<?php echo $form['fax']->renderRow() ?>

			</table>

		</div>

		<div id="location">

			<table>

				<?php echo $form['country']->renderRow() ?>
				<?php echo $form['province']->renderRow() ?>
				<?php echo $form['city']->renderRow() ?>
				<?php echo $form['address']->renderRow() ?>
				<?php echo $form['zipcode']->renderRow() ?>
			</table>
		</div>

	</div>

		<input type="submit" value="Update profile" />

	</form> 

	<?php javascript_tag(); ?>

		$(document).ready(function(){

    		var tabs = $("#tabs").tabs();

			var validator = $("#profileForm").validate({
				rules: {
					profile_username: "required",
					profile_email: {
						required: true,
						email: true
					},
					profile_name: "required",
					profile_surname: "required",
					profile_phone_number: {
						required: true,
						number: true
					},
					profile_country: "required",
					profile_province: "required",
					profile_city: "required",
					profile_address: "required"
				},
				errorPlacement: function(label, element) {

						label.insertAfter(element);
				}

			});

			validator.focusInvalid = function() {
				if( this.settings.focusInvalid ) {
					try {
						var focused = $(this.findLastActive() || this.errorList.length &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; this.errorList[0].element || []).filter(":hidden");

						tabs.tabs("select", tabs.find(">div").index(focused.parents('div:first')));
						focused.focus();

					} catch(e) {
						// ignore IE throwing errors when focusing hidden elements
					}
				}
			};

		});

	<?php end_javascript_tag(); ?>

Putting it together with server side validation provided by Symfony forms, we have nice, simple and complex forms validation system that should look like this:

2 Responses to “Symfony 1.2 - using sfForm with jquery validation plugin - part 2”


  1. 1 John

    Awesome! Would it be possible to extract the validation rules from the symfony form class straight to the JS?

  2. 2 Kamil Adryjanek

    Yes, it is possible. There are many ways. You can do that for example as Ahmed proposed in last comment: http://blog.adryjanek.eu/2009/01/15/symfony-12-using-sfform-with-jquery-validate-plugin/#comment-522

Leave a Reply

PodglÄ…d komentarza:




About me:

  • PHP programmer
  • Symfony developer
  • Zend framework developer

Categories: