New Zend_Auth tutorial

26th July 2010

After too many months of neglect, I have completely rewritten my Zend_Auth tutorial so that it is compatible with Zend Framework 1.10!

As an experiment, I have written it directly in HTML, rather than PDF as before and cover the login form along with the login controller code required to authenticate a user using a database table. For good measure, I've included logging out and a view helper to show how to access the logged in user's details.

The full source code is also available, if you don't want to type it in :)

I hope you find it useful.

Akrabat_Db_Schema_Manager: table prefix support

20th June 2010

I've updated Akrabat_Db_Schema_Manager so that it now supports table prefixes.

It uses the application.ini key of resources.db.table_prefix as I couldn't think of a better one :) and then uses that for the schema_version table's name and also makes it available in your change objects.

For example, if application.ini contains resources.db.table_prefix = "myapp", then the manager will create the table myapp_schema_version to store the current version of the schema. In your change classes, you can then do this:

001-Users.php:


 class Users extends Akrabat_Db_Schema_AbstractChange 
 {
     function up()
     {
         $tableName $this->_tablePrefix 'users';
         $sql "
             CREATE TABLE IF NOT EXISTS $tableName (
               id int(11) NOT NULL AUTO_INCREMENT,
               username varchar(50) NOT NULL,
               password varchar(75) NOT NULL,
               role varchar(200) NOT NULL DEFAULT 'user',
               PRIMARY KEY (id)
             ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
         $this->_db->query($sql);

         $data = array();
         $data['username'] = 'admin';
         $data['password'] = sha1('password');
         $data['role'] = 'admin';
         $this->_db->insert($tableName$data);
     }

     function down()
     {
         $tableName $this->_tablePrefix 'users';
         $sql"DROP TABLE IF EXISTS $tableName";
         $this->_db->query($sql);
     }

 }

which will create a table called myapp_users. Note that you are responsible for using the prefix property as the change classes cannot enforce what you do within the up() and down() methods. It also follows that you'll have to ensure that your models also use the correct prefix.

I have also made a change to the provider (Akrabat_Tool_DatabaseSchemaProvider) so that it loads the correct application.ini file based on the data in the project's profile. This shouldn't affect anyone using Akrabat_Db_Schema_Manager, except that we no longer define APPLICATION_ENV and APPLICATION_PATH for you.

Enjoy!

The Dutch PHP conference 2010

16th June 2010

This year I was invited to speak at DPC 2010 which was a great conference. I've published to Flickr, my complete set of photos from DPC 10.

Arriving on Wednesday, the day before the conference, I managed to get to meet up with my friend Juliette, along with a some of the other speakers for a barbeque which was a lot of fun. We ate, we drank (lots) and possibly this pose by Chris was the most surreal picture I took that evening!

I cannot even begin to think of a caption

On tutorial day, I gave a Zend Framework tutorial with Matthew Weier O'Phinney which seemed to go down quite well. We took a different approach this year to the previous ones that Matthew has given in that we talked about different application patterns and components that you can use in your ZF application; rather going through building an application from scratch. This had the benefit that we could talk about stuff that we wouldn't have got to normally. There were some other excellent tutorials that I was sorry to miss; I'm not quite sure how the attendees were able to make up their minds!

The conference was opened by Lorna and then Kevlin gave the opening keynote speaking about 97 things every programmer should know. This was an excellent keynote which fired us up for the day. In the morning, I gave my presentation on Zend_Form which I didn't feel came across quite as well as I could have done. I should probably revisit the content and pack some other bits in. This talk clearly showed the difficulties of aiming a presentation at the audience's level as I had some people there who had never used Zend_Form and others who knew it and were looking for more nitty-gritty details. Maybe I didn't set their expectations correctly at the start.

There were many other excellent presentations on the first day an I managed to catch Johannes' talk, 'Under PHP's hood' about what goes on within the PHP engine. An excellent talk with content that I highly recommend every PHP developer learns. I finished the day listening to Cal talk about Flex and whilst he hasn't convinced me to go that route, I know actually know a little about what it actually is!

In the evening, I had dinner with the other speakers and then we went to the conference social hosted by Ibuildings and github. This was very well attended and I had several good conversations with people.

Social

The second day of the conference started with a keynote by Chris Shifflet about Security patterns. I had already seen this talk and it was just as fascinating seeing it again. Definitely lots to think about. I gave my last talk of the conference immediately after the keynote and spoke on Deployment. I felt that this talk went well and that most of the audience got something out of it.

In a break from technical content, I went to see Elizabeth's talk on technical writing. Whilst I consider myself competent, I learnt lots and managed to not embarrass myself too much during the interactive section when I was volunteered (thanks Chris!) to go up and help Elizabeth illustrate a point. I also managed to drop in on the uncon and see Juozas and Ben talk about Doctrine 2, which seems to be considerably better than D1. The conference ended with a panel of leading lights in the PHP world talking about PHP and where it's headed.

Closing keynote panel

After conference ended, I went with a number of other people to a pancake restaurant and had an excellent meal, followed by a drink (or two!) with friends in the hotel bar. I had joked earlier in the evening that the bar bill would end up being paid by whomever was left standing at closing time... mdgm and myself had that honour :)

Again, DPC 2010 was a great conference and I want to thank Lorna and the DPC crew again for inviting me.

Community Review Team for Zend Framework

9th June 2010

On the ZF mailing lists, there's been a discussion on creating a community team with a follow-up by Matthew.

I was going to write up a little about it as I'm one of the volunteers on the team. However, Pádraic beat me to it and I don't think I could have written it any better, so go and read his write-up instead!

The CR Team at the moment is:

  • Rob Allen (Akrabat)
  • Pádraic Brady (PadraicB)
  • Steven Brown
  • Shaun Farrell (farrelley)
  • Pieter Kokx (kokx)
  • Dolf Schimmel (Freeaqingme)
  • Ben Scholzen (DASPRiD)

(alphabetical order has always suited me!)

We all accept email and can be found on irc in #zftalk.dev (freenode). Most are on Twitter too. Feel free to contact any of us about anything to do with contributing to Zend Framework and we'll find someone to help you!

MongoDB on OS X with the stock PHP installation

5th June 2010

MongoDB was mentioned a few times at tek and I said that I wanted to have a look at.

Travis' article, MongoDB: A first look, came out a few days ago and piqued my interest further. Then Matthew sent me some source code that requires it. The stage was set for getting MongoDB working on my Mac.

MongoDB

I use homebrew as a package manager for installing open source bits and bobs like couchdb, git, and hg. Installing MongoDB was simply a case of:

brew install mongodb

Once, installed there's a convenient LaunchAgent plist supplied so that mongodb starts with the computer:

cp /usr/local/Cellar/mongodb/1.4.3-x86_64/org.mongodb.mongod.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/org.mongodb.mongod.plist

And at this point, MongoDB is installed on your Mac and Travis' article and the tutorial work!

The Mongo PHP extension

If you've been following along here for a while, then you'll know that I use the stock PHP that comes with Mac OS X. I've been very happy with it so far and installed Xdebug was easy enough using pecl, so I was hopeful that the mongo extension would be equally simple.

Turns out that it is!

pecl install mongo

Compiles the extension with no problems.

To add it to your PHP install, edit php.ini and add:

extension=mongo.so

A quick sudo apachectl restart and phpinfo() shows this:

MongoDB in phpinfo

All done! You can now get at MongoDB from your PHP scripts.

Tek.X recap

1st June 2010

TekX (pronounced Tek-Ten) has finished and we've all gone back to our respective daily lives. I had a blast and learnt a thing or two as well... I've also been a little busy, which is why this post is "late".

The week started on Saturday when I flew to Chicago from Manchester. Rather helpfully, tek was held at a hotel close enough to the airport, that the hotel had a free shuttle. As a tip for next year, you need to phone the hotel to come and collect you if you don't land at the terminal next to the train station.

On Sunday, Lorna, Derick and myself went to Chicago city centre; apparently, this is known as "downtown". We were intending to do a river boat trip, however that was all booked up, so we ended up grabbing lunch; having a look around Millennium Park and then doing a walking tour with the Chicago Architecture Foundation. This turned out to be an excellent tour. The lady was extremely knowledgeable and shared her knowledge freely. it was a very enjoyable afternoon and I feel that I know much more about Chicago's history now.

Chicago's skyline reflected in 'The Bean'

I ended up working much more than I expected over the week, however, I did manage to make nearly all the sessions I wanted to. Due to a scheduling conflict, I missed Kristina's tutorial on MongoDB as I was giving a Zend Framework tutorial at the same time! My tutorial seemed to be appreciated and I hope that those attending learnt something new. It was an introduction to Zend Framework, starting from first principles; in Amsterdam next week, at the Dutch PHP Conference, Matthew and I will be doing an all-day tutorial covering the next level of Zend Framework usage.

Josh Holmes opened the conference proper with his Simplicity keynote. I've had the privilege of seeing this at PHPUK earlier this year, however, a second listen was appreciated. Josh showed us his theatre background when the mic failed by continuing to talk and projecting his voice all the way to the back of the room. I gave my talk on Zend_Form next, which also seemed to help people learn a little more about the component. As there's probably more confusion over decorators than anything else, I concentrated on them, which may have made them clearer for those who saw it.

I don't want to provide a run down of all the talks as exploring the joind.in page will tell you more than I could here. I do want to highlight a few though. Lorna's talk on Subversion and DVCSs was the most objective and balanced discussion on an emotive topic. I had seen an earlier version at my local user group and Lorna really pulled out all the stops at Tek to give the best session I've seen her give. Having missed her tutorial, I made sure that I went to Kristina's talk on MongoDB. I've heard some rumblings in the Twitter stream about Mongo, but didn't actually know anything about it before her talk. It is always a pleasure to listen to an expert who is passionate about her subject. Talking about passionate, Elizabeth's talk on cross-platform PHP was a study in how you don't need many slides if (a) you are angry and (b) slightly hungover and so are prepared to rant! I thought I knew all the pitfalls of developing PHP sites for both nix and Windows, but Liz managed to point out a few more to think about.

Liz gets angry during her talk!

Tek is a very community oriented conference and it did feel that there was an open atmosphere where talking to each other was encouraged. This is known as the "hallway track" and I found it very beneficial, managing to get some useful conversations with people who know far more than I do. This definitely increased my knowledge and hopefully those who talked to me also gained. I also managed to get some time with Chris "phpdeveloper" Cornutt who helped me get the joind.in source code working on my computer so that I can help the project by fixing the bits that annoy me the most :)

Potbelly sandwiches

Finally, I'd like to thank Marco, Cal, Keith, Arbi and Beth for hosting an excellent conference and inviting me to speak at it. Hopefully, I'll be able to go next year too!

Meet the TEK·X speakers

23rd April 2010

I mentioned back in January that I'll be speaking at TEK.X in Chicago next month. Since then I've fleshed out the talks that I'll be giving and think they should be quite interesting. It turns out that Zend_Form is such a large topic that I could probably speak for 3 hours on it! As a result, I've concentrated on providing a overview of the component and how to use it followed by a look at how to change the text of error messages and how decoration works.

The main reason for this post though is that Cal Evans has been doing some 5 minute interviews with some of the speakers at TEK this year. I recommend that you have a listen and find out a little about the people who are worth paying attention to.

As you can see on the schedule, I'm speaking in some very august company in Chicago this year, so highly recommend that you badger your boss and get a ticket to be there with us.

Using PDT with Zend Framework Projects

1st April 2010

I original wrote this as a comment on Victor Nicollet's blog, but I thought I should document it here too so that I can refer other people to the information.

These are some tips and tricks when using PDT with Zend Framework that make my life easier:

Autocompletion for dynamic properties

Zend_Db_Table_Row_Abstract uses __get() and __set() magic in order to map to the underlying database table row in question. This means that you can use property autocompletion on an instance of it. You can however tell your your table class which class to use for the row objects:

class Application_Model_Users extends Zend_Db_Table_Abstract
{
    protected $_name 'users'// database table name
    protected $_rowClass 'Application_Model_User'// row class to use
}

With your row class, you can take advantage of the @property docblock element to document the fields in the class:

/**
 * @property string $user_id
 * @property string $username
 * @property string $password
 */
class Application_Model_User extends Zend_Db_Table_Row_Abstact
{
}

Autocomplete on instances of Application_Model_User will now work.

Zend_View scripts are more complicated as they use $this to access magic properties. You can do however use the @var trick at the top of the .phtml file:

$user $this->user/* @var $user Application_Model_User */
$page $this->page/* @var $user Application_Model_Page */
etc...

You can now autocomplete on $user and $page. This also has the side-effect of documenting which view properties are used in this view script.

Opening an arbitrary method

View helpers are also magic methods on Zend_View's $this within a script file. This means that you can't cmd+click( or press F3) on the view helper's method name to jump directly to the code for that method. You can however take advantage of PDT's Navigation->Open Method feature. Simply select the method name and then press shift+cmd+m. The "Open Method" dialog appears and usually the view helper is selected as the first item. Just press return to go directly to the code for that view helper.

Opening an arbitrary file

For opening up an arbitrary file that's in my project, I find that PDT's Navigation->Open Resource (shift+cmd+r) is handy. For TextMate users, this is similar to the cmd+t feature.

Opening an arbitrary class

Using Navigation->Open Type (shift+cmd+t), you can also jump to classes easily. e.g. I regularly hit shift+cmd+t followed by "*Model_" and I get a list of all my models and can jump to the one I want using the down arrow key and then return.

Finding the current open file in the project tree

Just press cmd+option+w. You have to be careful here as it's very similar keyboard shortcut to close and close all! However if you have an entity file open and you name your files like I do, then the mapper is next to it in the project list, so it's only a couple of keystrokes to open it up.

Conclusion

These tips obviously work with all frameworks and any PHP coding :) Netbeans also has similar features, so I would guess all IDEs do. If you are wedded to vim or such like, then ctags is helpful for jumping around your code.

If you have a favourite tip that I haven't mentioned, let me know in the comments!

Akrabat_Db_Schema_Manager: Zend Framework database migrations

29th March 2010

So, it turns out that I had a need for database migrations within a Zend Framework project that's using Zend_Db_Adapter.

Those of you with long memories may remember that I created a proposal along these lines back in 2006. Nearly four years later, I read it again and implemented the core section. One of the comments, by Wil, asked why it's worth bothering with a DDL to create tables, columns, indexes etc. as sooner or later you'll hit a wall and need to use SQL anyway. He has a point. My original idea was that as I routinely use MySQL and MS SQL Server, it would be handy to have cross-database code. Thinking about it however, there's not that much that isn't cross-database and I could just as easily write the specific SQL for those situations.

If you remove the DDL bit, then the rest is quite easy, so I wrote it and put it up on github into a project I've egotistically called Akrabat.

Migration files

It is intended that any time you want to make a change to your database schema (add columns, tables, indexes, etc), then you create a new migration file. A migration file is stored in ./scripts/migrations and is named like this 001-CreateUsersTable.php. The number defines the order that the migrations should be performed as any given migration will make assumptions about the state of the database before it is run.

The migration file contains a class that extends Akrabat_Db_Schema_AbstractChange and must contain two methods: up() and down(). It follows that up() is called when implementing the changes in this migration and down() is called to put the database back where it was if the change is backed out.

001-CreateUsersTable.php:

class CreateUsersTable extends Akrabat_Db_Schema_AbstractChange 
{
    function up()
    {
        $sql "CREATE TABLE IF NOT EXISTS users (
                  id int(11) NOT NULL AUTO_INCREMENT,
                  username varchar(50) NOT NULL,
                  password varchar(75) NOT NULL,
                  roles varchar(200) NOT NULL DEFAULT 'user',
                  PRIMARY KEY (id)
                )";
        $this->_db->query($sql);
    
        $data = array();
        $data['username'] = 'admin';
        $data['password'] = sha1('password');
        $data['roles'] = 'user,admin';
        $this->_db->insert('users'$data);
        
    }
    
    function down()
    {
        $sql "DROP TABLE IF EXISTS users";
        $this->_db->query($sql);
    }
}

As you can see, this code will create a database table called users and then insert the first user. The backing out code (down()) just drops the table. As you can see, easy enough and uses Zend_Db_Adater so the database calls should be familiar.

For this to work, we need to store the current version of the schema within the database. This is done using a table called schema_version which contains just one column, version, and one row holding the current version number. Akrabat_Db_Schema_Manager will create this table if it does not exist.

Akrabat_Db_Schema_Manager

This is the class that does the work. It's based on the skeleton on the proposal and the code is here. There are two public methods in Akrabat_Db_Schema_Manager :

  • getCurrentSchemaVersion()
  • updateTo($version)<

In order to operate, Akrabat_Db_Schema_Manager needs the directory holding the migration files and a database adapter, so these are passed in via the constructor. The operation of updateTo() is fairly simple:

  1. Find and order migration files from current version to target version
  2. Iterate over migration files and call up() or down() as appropriate
  3. Update the current version number in the database

Obviously, getCurrentSchemaVersion() simply queries the database for the current version number.

Command line

To actually run the schema manager, we hook into Zend_Tool so we can use the zf command line tool. This means that we need a provider, Akrabat_Tool_DatabaseSchemaProvider. A provider is used by Zend_Tool to provide functionality for zf. We create a public method for each operation we want to be available at the command line:

  • updateTo($version, $env='development', $dir='./scripts/migrations')
  • update($env='development', $dir='./scripts/migrations')
  • current($env='development', $dir='./scripts/migrations')

The update() method is simply an alias to updateTo() that ensures that you update to the latest migration script that you have.

They are used like this:

$ zf current database-schema
Current schema version is 0

$ zf update database-schema
Schema updated to version 2

$ zf current database-schema
Current schema version is 2

The update-to operation allows you to roll-back also:

$ zf current database-schema
Current schema version is 2

$ zf update-to database-schema 1
Schema updated to version 1

$ zf current database-schema
Current schema version is 1

It turns out that adding a new provider to Zend_Tool requires a little bit of work. Ralph Schindler is the man who writes it all and Cal Evans is the ZF command line guru that writes it up in a way I can understand. A quick search of his blog helped me work this out. Thanks Cal!

These are the steps that you need to do:

  1. At the command line, run zf --setup storage-directory
    This creates a folder for storing Zend_Tool configuration files. Make a note of which directory it has created.
  2. Run zf --setup config-file
    This creates zf.ini in your storage directory.
  3. Edit zf.ini and change the php.include_path path so that it includes the full path to Akrabat/library in addition to the path to Zend Framework.For my installation, I have placed both Zend Framework and the Akrabat library in /usr/local/include, so I have:
    php.include_path "/usr/local/include/zend-framework/library:/usr/local/include/Akrabat/library/"
    
  4. Finally, we need to tell Zend_Tool about our new provider. This is done using the basicloader.classes key in zf.ini. So add:
    basicloader.classes.0 "Akrabat_Tool_DatabaseSchemaProvider"
    

Once you've done that (and installed Akrabat into /usr/local/include or wherever), then you should now be able to run $ zf ? database-schema and get a result:
Screen shot 2010-03-28 at 11.18.13.png
Everything is now in place. All you need to do is create a script/migrations directory and populate it with migration scripts and you're good to go!

If you come across any bugs, please report any bugs you find (preferably with the fix!)

Update: Table prefixes are now supported.

Photos of Seagulls

27th March 2010

Today was a good day in photography for me as for the first time in absolutely ages, I took some time out to take photos for the sake of taking the picture. My son was at a birthday party and I had about an hour free, so I went down by the river Severn in Worcester.

Worcester has a cathedral and I was lucky enough to have some lowish sun shining on it:

Worcester Cathedral

I don't often take photos of the cathedral as I find it hard to compose a nice picture of it. Also, it's been done to death by photographers with a better eye than me. However, I really like this one. The composition is nice and the colour of the brickwork is pleasing.

As I had a mostly empty memory card, I went down to the river to try and take a photo of a bird in flight. This isn't easy and I took just under 80 shots and had 3 in focus:

Seagull (1)

Seagull (2)

Seagull (3)

I'm pleased with all three as getting a shot of a bird in flight where the bird's eye isn't blurred takes lots and lots of practice. As I haven't practiced, clearly I got lucky! I set my D80 to use the centre auto-focus point, as it's the most sensitive in the camera, then told it to continually focus and I just pressed the button whilst trying to pan with the moving bird. It's remarkably difficult to keep the bird in the view finder, let alone keeping the focus point on the eye!

I think I did okay and I'm keen to try again sometime.