Simple Symfony Login Form Example

Tuesday, 18 November 2008

There are times when I just need a simple login form that checks for a certain username and password combination in order to lockdown a backend administration interface. The new sfForm sub-framework in Symfony 1.1/1.2 makes it really easy to reuse a Form class for this. If you’re unfamiliar with the new sfForm sub-framework, you should probably start with the Forms Book. Here’s an example form (placed in lib/form):

<?php

class LoginForm extends sfForm
{
  public function configure()
  {
    $this->setWidgets(array(
      'username' => new sfWidgetFormInput(), 
      'password' => new sfWidgetFormInputPassword() 
    ));

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

    $this->setValidators(array(
      'username' => new sfValidatorChoice(array('required' => true, 'choices' => array('admin'))), 
      'password' => new sfValidatorChoice(array('required' => true, 'choices' => array('some_password')))
    ));
  }
}

The key here is using sfValidatorChoice to ensure that the input matches some predefined keys (“admin” and “some_password” in this case).

For completeness, here’s the action file:

<?php

class authActions extends sfActions
{
  public function executeLogin(sfWebRequest $request)
  {
    $this->form = new LoginForm();
 
    if ($request->isMethod('post'))
    {
      $this->form->bind($request->getParameter('login'));
      if ($this->form->isValid())
      {
        // authenticate user and redirect them
        $this->getUser()->setAuthenticated(true);
        $this->getUser()->addCredential('user');
        $this->redirect('home/index');
      }
    }
  }
  
  public function executeLogout()
  {
    $this->getUser()->clearCredentials();
    $this->getUser()->setAuthenticated(false);
    $this->redirect('@homepage');
  }
}

And the template file loginSuccess.php:

<form action="<?php echo url_for('auth/login') ?>" method="POST">
  <table>
    <?php echo $form ?>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

And of course, you’ll want to turn on security for the application in security.yml:

default:
  is_secure: on
  credentials: user

Leveraging the OnChange Event of Inputs with jQuery

Tuesday, 18 November 2008

This may be obvious, but it’s something that’s easily overlooked. Text inputs, like select fields, have an onChange handler that can be leveraged to detect when a field has been (you guessed it…) changed. This may not seem like a big deal, but it really helps when, for example, you’re trying to keep track of which text fields on a page have been updated so you can save them to a database via ajax.

Here’s a nice, simple method to easily detect (and save) inputs that have been modified by leveraging the onChange method of inputs via jQuery:

$(":input").change(function() {
    // save the field's new value
    $.post("save_data.php", { field: $(this).attr('id'), value: $(this).val() });
    }
);

… the nice thing about this method is that you don’t have to track previous and new values since this method will only get triggered if the data has been altered in the textbox. Obviously, this is just an example, but it should serve as a good primer for what’s possible.

(Via Ben Nadel)


Rescuing Under-Appreciated Blogs

Sunday, 16 November 2008

Chuck Westbrook has an interesting idea to end the “tragedy of under-appreciated blogs”:

  1. Gather some nice bloggers who believe in helping good content rise. The more the merrier. This becomes our group for the project.
  2. A good, lesser-known blog is chosen. Everyone in the group will read that blog for two weeks.
  3. At the end of the two weeks, the group moves to another blog to read.

With scores of bloggers focused on a particular blog, the author should see many nice things happen over those two weeks, especially if the blog really is a hidden gem. This includes discussions, traffic, constructive criticism, encouragement, and connecting to some of the bloggers in the group. That author then joins the group and we move along and do it again.

Sounds like an interesting idea, but with the sheer volume of blogs out there, will this really help? There’s also an inherent problem with this approach: many blogs cater to very niche interest groups (like for example, this blog). It would be hard to appreciate a good blog where you’re unfamiliar with the subject matter.

Regardless, sounds like a great idea for some blogs to get the exposure they need.


Dynamically Adding and Removing TinyMCE Instances to a Page

Thursday, 13 November 2008

TinyMCE is a pretty neat tool for adding some WYSIWYG editing features to standard HTML textarea and div tags. Out of the box it’s pretty easy to install and use, but I ran into some trouble trying to dynamically load and unload editor instances to a textarea that was injected into the DOM via Ajax. Turns out that I was trying to instantiate the editor instance before the textarea tag had been unhidden which caused TinyMCE to choke and die for some reason.

What follows is a quick overview on how to instantiate TinyMCE dynamically.

Once you’ve installed TinyMCE, in your main template you’ll want to create a base configuration for the TinyMCE instances you’ll be using:

<script type="text/javascript" charset="utf-8">
    tinyMCE.init({
        mode : "none",
        theme : "simple"
    });
</script>

You’ll notice that we’re using the mode “none” here. This basically sets up TinyMCE without actually transforming any of the text fields on the page. This is the only thing that’s really important. You can of course use the advanced theme, but I’m using the simple theme for brevity.

At this point, you can do whatever you need to do in the DOM to add and remove text areas dynamically. To attach an instance of TinyMCE to a (dynamically loaded) text area, just do this after the insertion:

tinyMCE.execCommand('mceAddControl', false, 'the_textareas_id_here');

… and if you’re going to remove that text area dynamically, do this before removing it:

tinyMCE.execCommand('mceFocus', false, 'the_textareas_id_here');                    
tinyMCE.execCommand('mceRemoveControl', false, 'the_textareas_id_here');

I use the “mceFocus” command before removing the instance because I’ve read that without it IE will sometimes fail. Also, you can do something like this if you want to make sure the TinyMCE instance exists before trying to remove it:

if (tinyMCE.getInstanceById('the_textareas_id_here'))
{
    tinyMCE.execCommand('mceFocus', false, 'the_textareas_id_here');                    
    tinyMCE.execCommand('mceRemoveControl', false, 'the_textareas_id_here');
}

Since TinyMCE doesn’t actually use the original textarea to do it’s magic, you’ll have to trigger a command to repopulate the original textarea tag with the modified contents before further manipulating the data:

tinyMCE.triggerSave();

If it’s not completely obvious, the reason you have to jump through all these hoops is because TinyMCE does some interesting things in the background in order to make it look and feel like you’re using a real text editor. This involves some intricate DOM manipulation and hackery.

All in all, I’ve found that this method works very well in practice. Again, just be sure that the element you’re adding the TinyMCE instance to isn’t hidden in the DOM. For some reason this’ll kill TinyMCE and you’ll end up with a blank editor that doesn’t work. In FireFox this was often seen as the dreaded t.win.document is null error.


Cocoa Toolkits and Resources

Thursday, 13 November 2008

I’ve been fooling around with Cocoa development over the last few months and I’m beginning to really love Objective-C. The syntax was a bit daunting at first, but the language seems really elegant once you figure it out. As my understanding of Cocoa and Objective-C increases I’ve been trying to compile a list of resources. There’s a wealth of really great example code out there if you know where to look.

A couple of new Cocoa Development toolkits have recently emerged which aim to ease development of common Cocoa development tasks:

KTUIKit:

The goal of the project is to provide solutions to three important issues in any Mac UI project:

  • Layout
  • Styling
  • The MVC design pattern (specifically the V & C parts)

And also BWToolkit:

BWToolkit is a BSD licensed plugin for Interface Builder 3 that contains commonly used UI elements and other useful objects. Using these objects is as simple as dragging them from the library to your canvas or document window.

Both toolkits come with an Interface Builder plugin to ease integration with your own projects.

Also, Matt Gemmell has an excellent library of Cocoa Source code online that you are free to use in your own projects.


Macworld Reviews Things for iPhone

Thursday, 13 November 2008

Jason Snell reviews Things for iPhone:

I’ve got to get my life under control. So much to do, so little time. I’ve tried lots of different ways to track to-dos, but none of them really stuck before I started using Cultured Code’s $10 Things.

As I’ve written previously, my experience has been much the same. I actually enjoy using Things instead of simply seeing it as a necessary evil that keeps me organized. It’s there when you need it and disappears when you don’t. My only minor peeve is that I often forget to sync my iPhone version of Things before leaving the house. This can be a little irritating, but hasn’t affected me too much as I tend to us the iPhone version to add new ToDo items to my inbox for later review. And if I’m expecting to use Things on the road, I tend to remember to sync right before I leave the house. It’s only those unexpected times that really make me wish Things did over-the-air syncing.

Overall though, I’m much happier with Things Desktop and Things Touch than I was using OmniFocus. Since, you know, I actually use it.


Coda Updated to Version 1.6

Tuesday, 11 November 2008

Coda 1.6 has been released. For a point release update to Panic’s “One-Window Web Development” tool, they sure packed in a lot of punch.

Check the release notes for what’s new and improved, but the new plugin architecture is by far the most impressive thing on that list.

I’ve tried to use Coda several times but I just can’t get into the overall feel of the program. It feels like just too much all crammed in to one program, but I tend to keep a watchful eye on its progress since I know the guys at Panic really sweat the details. The new plugin architecture is really impressive and I think it owes a lot to TextMate for inspiration at some basic level. Here’s hoping this helps gently nudge TextMate 2 out the door…

(Via Daring Fireball.)


Parallels 4.0 Released

Tuesday, 11 November 2008

Currently I use (and love) VMWare’s Fusion with a Windows guest OS to test Windows specific browser quirks. I used to use Parallels before purchasing Fusion and I still own a license for both. For me it was just a matter of preference… it just seemed like Fusion was more responsive and a little less buggy than Parallels at the time, so I stuck with it. Perhaps it’s time to revisit Parallels since they’re claiming that Parallels 4 promises a significant performance boost:

This new version of the award-winning Parallels Desktop for Mac improves OS integration, performs up to 50% faster and incorporates a range of security, backup and power saving features to give Mac users a truly easy, fast and powerful desktop computing solution.

(Via MacRumors.)


Symfony 1.2 Beta 2 Released

Monday, 10 November 2008

The second Beta of Symfony 1.2 has been released and adds support for the Doctrine Admin Generator:

We are very happy to announce the symfony 1.2 beta 2 release, which now supports the admin generators for both Doctrine and Propel. No need to use Propel for sexy admin generator anymore.

This will also be the final Beta release before Symfony 1.2 stable is released.


sfTaskExtraPlugin Released

Saturday, 08 November 2008

Kris Wallsmith just released a new plugin that should aid the task of creating and bundling Symfony plugins:

The sfTaskExtraPlugin is a plugin maintained by the symfony core team. It adds a number of useful tasks to your symfony command line to help streamline your workflow. This plugin is relatively young, so I will just be discussing those tasks that we’ll be using for today’s Plugin Developers Day. I should also note this plugin requires symfony 1.2.