Category: How-To

  • Symfony Has a Swift Plugin for Sending Gmail

    It’s easy to send emails using your gmail account with the Swift Plugin.
    Here’s some sample code below

    
    $to          = 'somebody@example.com';
    
    $htmlMessage = "OH HAI!";
    $textMessage = "*OH HAI!*";
    
    $connection = new Swift_Connection_SMTP(
      sfConfig::get('app_email_smtp_server'),
      sfConfig::get('app_email_smtp_port'), 
      Swift_Connection_SMTP::ENC_SSL
    );
    
    $connection->setUsername(sfConfig::get('app_email_username')); # gmail email
    $connection->setPassword(sfConfig::get('app_email_password')); # gmail password
    
    $mailer = new Swift($connection);
    $message = new Swift_Message("Your subject goes here. OH HAI!");
     
    $message->attach(new Swift_Message_Part($htmlMessage, 'text/html'));
    $message->attach(new Swift_Message_Part($textMessage, 'text/plain'));
     
    // Send,
    // try and catch
    try {
      if (!$mailer->send($message, $to, sfConfig::get('app_email_username'))) {
        throw new Exception('mailer error');
      }
    } catch (Exception $e) {
        sfContext::getInstance()->getLogger()->info(
          "Caught swift send error exception:\n" .  
          $e->getMessage(). " ".
          $e->getFile() . ": Line ".
          $e->getLine() . "\n", $e->getTraceAsString(), "\n"
      );
    }
              
    $mailer->disconnect();  
    
  • sfGuardPlugin: The Extra Documentation

    Hey Folks,

    The Symfony project has a section called sfGuardPlugin Extra Documentation.

    It’s worth a read, especially the part about using the sfGuardUserProfile calls.

    The docs haven’t been updated since March, so if something isn’t working, please refer to my previous blog post on installing the sfGuardPlugin.

    I’d like to state that personally, there isn’t really the right way to do this. Sometimes you already have a table that has a username and password. You can skip using the sfGuardAuth password tables by doing the following:

      sf_guard_plugin:
        algorithm_callable: md5
        success_signin_url: @homepage
        profile_class: sfGuardUserProfile
        profile_field_name: account_id
        check_password_callable: [Account, checkPassword]
    

    The important line here is check_password_callable, where you are telling symfony to use the Account table and to use your own checkPassword method.

  • Weening Myself Off of Eclipse PDT

    I really just want to stick with Vim, and Vim is really making that sort of commitment easy because of technology I talked about in my last post, as well as learning how to use subversion just from the command-line.

    Today I learned how to:

    • create folds in Vim with a split view so that I can get perspectives similar to Eclipse’s object explorer. (There’s a great folds tutorialon Linux.com.)
    • merge by just using subversion on the command-line

    Tomorrow I’m gonna learn about:

    • Using ant at the command-line
    • Being more adept at file version comparisons, e.g. (svn diff)

    Have you weened yourself off of an IDE? And if so, what do you now use for text editing?

  • Ctags and Code Completion in Vim 7.2

    At work we switched the whole dev team over to using Eclipse. I still haven’t gotten used to all the point and click crap on it, but really admire the use of code completion and ctags.

    When I saw that Vim had these, I’ve upgraded and now use ctags and code completion from Vim.

    To get code completion, I type out the little bit I know and then type ctrl-o and ctrl-x:

    pic of code completion in vim

    To get ctags working, I installed it using sudo apt-get install ctags and then at the root of all my php files I typed:

    ctags -R .

    This generated a tags file.

    Now when I open any file and have the cursor over a function or class, I just type ctrl-] and the file containing the class or function opens up.

  • The HTTP Status 122 Error in IE7 in Ajax Apps

    Summary: Don’t use the GET method in Ajax Apps, if you can void it, because IE7 craps out with more than 2032 characters in a get string.

    Here’s the page that craps out at 2033 characters with IE7:
    http://www.codebelay.com/status122/?i_limit=2033

    You won’t see the error with other browsers.

    Here’s the page that’s okay:
    http://www.codebelay.com/status122/?i_limit=2000

    What’s going on here?

    picture of http status 122
    Sometimes you’ll write a piece of Javascript that uses prototype and looks like this:

      var url = '/status122/listener/?stuff=' + encodeURIComponent($('js_stuff').innerHTML);
    
      // This is where we send our raw ratings for parsing
      var ajax = new Ajax.Updater(
    	 'jskitdecoded',
    	 url,
    	 {
    		method: 'get',
    		onComplete: showResponse
    	 }
      );
    
    

    If you print http.status you get an HTTP Status of 122. WTF?

    What’s going on here is that IE7 sets a limit of 2032 characters on GET strings, so you have to do a POST instead like so:

      var getvar = encodeURIComponent($('js_stuff').innerHTML);
      var url = '/status122/listener/';
    
      // This is where we send our raw data for parsing
      // If we use method: 'get', IE7 will return a 122, but
      // b/c Firefox is RFC2616 compliant and realizes that
      // there is no minimum length for a URI, we get success.
      // Here we use method: 'post' b/c IE7 is lame.
      var ajax = new Ajax.Updater(
    	 'jskitdecoded',
    	 url,
    	 {
    		method: 'post',
    		postBody: 'stuff=' + getvar,
    		onComplete: showResponse
    	 }
      );
    

    I hope this helps.

    What Ajax quirks have you run into?

  • The Rails Console Makes Test Object Creation and Debugging Easy

    I really like how the Rails console solves the problems of test object creation and debugging.

    Usually, a web developer will push code to the webserver and hit shift-reload on the web browser. With the Rails console, you can avoid all that shift-reload madness.

    If I wanted to create 10000 blog posts for testing, I could do something like this:

    script/console
    10000.times
    { |i| Post.create(:title => “post number: ” + i.to_s, :body => “autogen Booyah!”) }

    Through the console I can also do debugging pretty easily:

    >> p = Post.find 888

    And get this as output:

    => #

    A lot of problems in Rails are just solved by running script/console and checking the values of certain variables that are pretty hard to get at through a web browser.

    There is pretty much no limit to what can be done through the Rails console. Konstantin Gredeskoul, web developer and songwriter, has found a way to load session data through the console.

  • Installing Swift in symfony 1.1 — The missing manual

    There’s one little gotcha with installing Swift in symfony 1.1. The directions are correct but do not mention how to get around the error that outputs:


    Fatal error: Class ‘Swift_Connection_SMTP’ not found

    The solution is quite simple and involves creating an autoload.yml file in your project’s config directory. Here it is:

    autoload:
      swift_mailer_classes:
        name: swift classes
        ext:  .php
        path: %SF_PLUGINS_DIR%/swift
        recursive: on
    
    

    What I really like about Swift is how you can use your gmail account to send messages.

  • Installing sfGuardPlugin in symfony 1.1 — A Guide for the Perplexed

    Like the verbally creative barfly, who is a dead ringer for a 21+ Juno, that you picked up during last call on a Friday night, symfony 1.1 starts to grow on you. Nevermind your friends, who found Erlang in some higher-scale, hipster, hippy hang out. They tell you it’s time to leave symfony 1.1. You’re perversely drawn to this framework and don’t mind racking up the future therapy bills.

    God is dead, and so everything is permitted, unless you can install something like symfony 1.1’s sfGuardPlugin to add logins and login protection to web pages. Like the initiation rites into the Eleusinian mysteries or the Freemasons, not everything is articulated on how to do the install. But below, for the first time, it is.

    Note: I use psymfony as an alias which really just means ‘php symfony’.

    • psymfony generate:app backend

    Now you can start following the guide written on the symfony website. Below is just from my shell’s history log:

    • psymfony plugin:install sfGuardPlugin
    • psymfony propel:build-model
    • psymfony propel:build-sql
    • psymfony propel:insert-sql — this didn’t work for me so I ended up just doing: mysql -uusername -p < data/sql/plugins.sfGuardPlugin.lib.model.schema.sql
    • follow the instructions in the guide above for fixtures
    • psymfony propel:data-load frontend
    • psymfony propel:data-load backend
    • vim apps/frontend/config/settings.yml
    • vim apps/backend/config/settings.yml
    • psymfony cc

    But you’re not done yet. Are you running into a propel connection error? Then you might have to edit some yaml files based on this blog post.

    In my case, I ended up having to edit config/databases.yaml by adding the following below:

       propel:
         class:          sfPropelDatabase
         param:
           phptype: mysql
           host: localhost
           database: dev_starster
           username: writes
           password: some_wicked_sick_password
           dsn:          mysql://writes@localhost/dev_starster
           datasource: propel
    

    Are we out of the woods yet?

    Unfortunately, symfony 1.1 has a signout bug, where sessions are not entirely cleared. Thanks to this blog post, I was able to hack something together.

    In apps/yourapp/modules/sfGuardAuth/actions/actions.class.php write:

    public function executeSignout()
    {
    if (sfConfig::get('sf_environment') != 'test')
    {
    session_destroy();
    session_write_close();
    session_regenerate_id();
    }
    parent::executeSignout();
    }

    You might have to link the sf_guard_user table to an account table, if you want the account table to do the authorization instead. If so edit apps/modulename/config/app.yml by adding something that looks like this:

      sf_guard_plugin:
        algorithm_callable: md5
        success_signin_url: @homepage
        profile_class: sfGuardUserProfile
        profile_field_name: account_id
        check_password_callable: [Account, checkPassword]
    

    In the lib/model/Account.php you should add code that looks like this:

      public static function checkPassword($username, $password) {
      	$c = new Criteria();
      	$c->add(AccountPeer::EMAIL, $username);
      	$c->add(AccountPeer::PASSWORD, md5($password));
      	$rac = AccountPeer::doSelect($c);
      	//print_r($rac) ; die();
      	if ($rac == TRUE) {
      		return TRUE;
      	} else {
      		return FALSE;
      	}
      }
    

    Here is a list of links that made getting the plugin working possible:

  • Symfony 1.1 Validation — Gotchas

    1. sfValidatorAnd requires a patch to work with Propel.

    Get the patch here.

    Read the trac ticket for more details.

    2. A huge difference between 1.0 and 1.1 in form validation deals with error handling.

    1.0 puts the error handling right in the action. In 1.1 you use code in a lib/forms file that looks like this for validation / error handling and corresponds usually to the object being validated. In the example below the code is in lib/forms/AccountForm.class.php

    $this->setValidators(array(
        'username' => new sfValidatorString(array('max_length' => 30))
    ));
    

    3. sfForm::setDefaults doesn’t work quite right with CSRF values.
    you’ll need to patch up code based on this google groups post.

    The documentation right now for 1.1 isn’t updated. E.G. The chapter on forms for the 1.1 documentation as of 12 August 2008 will lead you down the wrong path.

    To keep up to date on what’s going on with symfony, I totally consider doing the following mandatory and not optional:

    • Join the google group, symfony-users
    • Join the irc channel in irc.freenode.net #symfony any time you’ve got a question that needs asking
    • Since the docs might be off, it’s best to just read the source.
  • Fun With GDB, Gnu’s Debugger

    Here’s a pretty compact version of strcmp:

    int bstrcmp(char *s1,char *s2) {
       while(*s1 == *s2++) {
          if(*s1++ == 0){ return 0; }
       }
       return (*(unsigned char *)s1 - *(unsigned char*)--s2);
    }
    

    The source that I used for compiling and calling this version of strcmp is here.

    Compile that code using:
    gcc -o strcmp -g strcmp.c

    Fire up the debugger using:
    gdb strcmp

    You’ll get the gdb prompt:
    (gdb)

    Set a break point at the start:
    b main

    The debugger will echo something like:
    Breakpoint 1 at 0x80483d5: file strcmp.c, line 6.
    (gdb)

    Then run the program:
    run

    The debugger will print out something like:
    Starting program: /home/somedude/bin/strcmp

    Breakpoint 1, main () at strcmp.c:6
    6 {
    (gdb)

    If you type n a few times, you’ll eventually get to some variable assignments.

    (gdb) n
    8	char s1[] = "better";
    (gdb) n
    9	char s2[] = "better than"; /* than this";*/
    (gdb) n
    11	int i_result = 0;
    (gdb) n
    13	i_result = bstrcmp(s1,s2);
    

    If you want to the values of these variables type:
    p i_result

    You get back:
    (gdb) p i_result
    $1 = 0

    To step into a function, type s:

    (gdb) s
    bstrcmp (s1=0xbf86b469 "better", s2=0xbf86b474 "better than") at strcmp.c:26
    26		while(*s1 == *s2++) { 
    (gdb) n
    27			if(*s1++ == 0){ return 0; } 
    (gdb) n
    26		while(*s1 == *s2++) { 
    (gdb) n
    27			if(*s1++ == 0){ return 0; } 
    (gdb) n
    26		while(*s1 == *s2++) { 
    (gdb) 
    

    At this point you can type things like:
    p s1
    p *s1
    p s2
    p *s2

    And you’ll get back the value of the pointers and what’s in memory.

    Next time we’ll go over how to do this with PHP running single threaded on debug mode on Apache.