Made Media Ltd. 105 Carver Street, Birmingham B1 3AP

hello@mademedia.co.uk +44 (0)121 200 2627

Made Media Ltd

Posted in news,projects,technology by Made Media Ltd on October 19th, 2006

Introducing Jobs Board Digest

jobs_board_digest.jpg

We’re delighted to announce the launch of Jobs Board Digest. The Jobs Board Digest is a small side project that we think some people may find useful.It provides aggregated listings from three of the best new jobs boards that have recently been springing up.

Specifically, we are combining the latest advertised jobs from 37 Signals, Joel on Software and Vitamin. You can view the latest job postings online or via a combined RSS feed.

This is a completely free service and we’re not aiming to profit from this at all. The advertisers pay the board owners directly, we’re just helping distribute the information. Let us know what you think.

Comments Off

Posted in linux,technology by jake on October 9th, 2006

MyActiveRecord – New Release

I've finally got it together to release an update to the MyActiveRecord class.

There's nothing like open-sourcing some code to teach you a few lessons:

  1. Not everyone is using the same version of PHP, MySQL or OS as you
  2. Not everyone is using English as their first language
  3. Whilst you might not be dealing with the kind of databases that trigger out-of-memory errors in your script, some of your users most definitely are...

So after releasing MyActiveRecord via phpclasses last March, I was overwhelmed with the response in both good and bad ways. Almost everyone who wrote said that the class had really helped them speed up a major project they were working on (good!). Also most people really got my motivations for developing the class; Many were quite familiar with Ruby on Rails but for whatever reason were sticking with PHP. Most were after a class they could use to cut down on basic SQL hoop-jumping, but they didn't want to learn an entire framework, and they wanted the flexibility to do things their own way. Many were developing in a PHP4 environment and deploying on PHP5 or vice-versa.

In my update I tried to incorporate bug-fixes, some of the nicer ideas, and stuff that I'd implemented half-heartedly and wanted to do properly. The major new features are:

  1. SQL Logging (handy for debugging)
  2. Query Caching (improves performance)
  3. Single Table Inheritance (allowing you to store a class hierarchy in a single table)

There are also some new, useful methods:

The Prepare() Method allows you to escape SQL parameters in a hassle-free way, using sprintf syntax. Eg:


$condition = MyActiveRecord::Prepare("first_name LIKE '%s' AND age > '%d'", $_GET['first_name'], $_GET['age']); 
$people = MyActiveRecord::FindAll('Person', $condition); 

The FreqDist() Method will provide you with an array containing the distribution of unique values for a given table/field. Eg:


foreach( MyActiveRecord::FreqDist('Person', 'name') as $name=>$total ) { 	print "There are $total people with the name $name"; 
} 

The TableExists() is a utility method to tell you if a table exists in the database or not

 if(MyActiveRecord::TableExists('person')) print '`person` table exists!'; 

The add_child() method provides a convenient way of creating new child objects:

 $comment = $post->add_child('Comment', $_POST); $comment->save(); 

The validadate_uniqueness_of() method allows you to check whether a field value is unique before attempting to save it in the database:

 $person->validate_uniqueness_of('username', 'username is already in use'); 

Most of the changes are under the hood. One you do need to know about is the way MyActiveRecord maps classes to tables. Originally classes were supposed to be named identically to the table in your database. So a Person class would map to a Person table. Unfortunately a bug in PHP4's get_class method meant that this could not be sustained. The get_class function always returns a lowercase string in PHP4. The only reason this didn't cause problems for most users is that most combinations of OS & MySQL effectively give you case-insensitive table-names. However this wasn't true for everyone. The only way to get 100% compatibility for all cases is to mandate that table-names are specified in lowercase. So a Person class will map to a person database table. It's one of those classic PHP frustrations, and it annoyed me no end, but you could say that this whole project was born out of a desire to circumvent PHP's foibles

What didn't make it.

A lot of people asked for stuff that seems perfectly reasonable, but that I decided to leave out anyway. Here's what got left out:

  1. Changes to mappingPeople wanted to be able to append stuff to the front of their table names i.e. myapp_person mapping to Person. People wanted to be able to change the name of the field that acted as primary key etc. I've resisted this because whilst on the surface these things seem simple enough to implement, in practice they add complexity and ambiguities at every level of the class. MyActiveRecord wasn't my first attempt at a mapping class, and defining a few simple, solid rules about naming and IDs was what freed me up to finally build a class that I felt had some elegance and integrity. It also allowed me to document and explain the class without constant caveats and exceptions. So I'm not bending on this yet. (Actually, working around the get_class() bug required me to add a Class2Table method, so in theory, adding a prefix to your table names would be easy enough and I might consider it.)
  2. View logic in the mapper classA few people supplied me with some helpful methods for getting HTML out of the class. Pre-formed error lists and the like. Obviously this is evil, I even feel a bit icky about the h() method, but it's just so damn handy and I stole the idea from Ning. Actually, I do have a class that takes a MyActiveRecord object and then uses methods to spit out helpful HTML fragments, but it's not quite ready for production yet...
  3. Event hook methodsSome people supplied rails-esque event-hook methods like before_save(); before_destroy() etc.. After some deliberation I decided not to add these. Why? Because I think you can achieve exactly the same thing by extending the class. That is one of the key advantages of OO after all! For example:
     Class Person extends MyActiveRecord { 	function save() 	{ 		return $this->some_cleanup_or_test_method() ? parent::save() : false; 	} } 
    If someone can make a good argument as to the advantage of putting blank event hook methods into the class I'll look into it again, but for now I'd rather prevent the base class from getting any broader!

  4. Shorter NameSo some people are developing RSI typing the same 14 characters over and over. I admit, the name is ugly and too long, but it has several marketing advantages with regards to describing what the class does, picking up search engines and so on. This one is easily solved anyway:
     Class AR extends MyActiveRecord{} Class Person extends AR{} $people = AR::FindAll('Person'); 
    Actually I really recommend this approach whenever you build a serious application, as this gives you an opportunity to extend all sorts of basic functionality like saving etc.. at your application level. For example, you might decide to extend the save method so that it stores a serialised copy of every object that's ever updated, giving you a complete transactional history of every object in your application. It's easy to do. Plus when you develop some great ideas in your extended classes you can send them to me and I'll have nice cleanly separated code to incorporate into the next version of the base class.

What's next?

Apart from the fact that I'm extremely busy anyway I don't really intend to develop this class a whole lot further. It does a pretty nice job, and it's already a lot bigger than I would really like. There will be bugs in this release, and I will fix any that are reported. Other than that, I intend to improve the general integrity of the class and add some magic field names (datetimes called modified_on and created_on will get time-stamped automatically, stuff like that). I want to deal with the caching and encapsulation of related objects so that - for example - saving a post object will automatically save changes to any child comment objects.

Once those basic features and bug fixes are implemented I'll declare the class at version 1(beta) and after a reasonable time to fix any bugs I'll declare it 1.0.

I'd like to thank Walter Lee Davis, Mark Kaye, Mike Stupak and Mihael Konjevic in particular for their help and feedback to date.

Comments Off

Posted in life,technology by Made Media Ltd on June 27th, 2006

Oh Microsoft, how surprisingly up front you are today

So, I was trying to play with the new Office 2007 Test Drive – apparently it’s a working online preview of the new Office suite. So I clicked through a couple of screens and was presented by a this.

not compatible
click to enlarge

Not entirely suprising but it’s been a long, stressful day so I reacted by typing a rather rude phrase into the search box in the top right corner of the page.

Imagine my surprise when I was presented by the following. Honestly this is real. Here’s the link.

http://search.microsoft.com/results.aspx?mkt=en-XU&setlang=en-XU&q=pile+of+shit

pile of s**t
click to enlarge

Having spent the day having to work around the [cough] idiosyncrasies of IE6 this really made me chuckle.

2 Comments

Posted in javascript,technology by jake on March 16th, 2006

A Brand New Prototype

With all the chaos over separation of style (CSS) and content (XHTML) as being pushed by luminary bodies such as the The Web Standards Project finally dying down, and AJAX appearing as one of the new standards in web development, Javascript is getting a chance to paint itself a new responsible image. No longer relegated to drifting 'DHTML' snowflakes over holiday periods, it now has some actively developed and highly useful libraries to make the 'net better for the people using it.

All recently used on a large project here at Made, the 'Javascript Trinity' of libraries makes javascript a joy to code:

  • Prototype, the workhorse of the tree, extends the default Javascript functionality available in browsers to provide a standardised and well-structured base for further Javascript development.
  • Built on top of Prototype, script.aculo.us provides effects, drag-and-drop events, sliders and AJAX update-in place fields amongst its many features. Accessible controls exist to make data entry easy (and sometimes even fun), stop relying on a page full of nothing but text boxes.
  • When AJAX was coined, a lot of people dropped the only-recently-celebrated notion of clean markup and and started dumping Javascript into the middle of their otherwise-lovely XHTML. Behavior solves this problem by using CSS-style selectors for attaching events to certain elements.

Prototype is rapidly approaching a new release, adding some brand new features:

Extending elements

One of Prototype's new features is the ability to add additional methods to XHTML element objects. While this has been possible in some circumstances by extending the prototype of an object, the new Element.extend functionality can add methods to individual objects. Whats more, it automatically happens when you call...

... the $() and $$() functions

Handy functions, especially because of their terseness. The $() function in its normal use is mere shorthand for the oft-used and oft-misspelled getElementById() function, but supplied with multile parameters it will return an array of the elements with those ids. Now it will even extend each one.

The $$() is an even more flexible beast, returning all elements for a CSS selector *and* extending them. Powerful stuff, for example:

$$('div#main img.photos').each().hide() // Would hide all photos within the 'main' container element

Others

Many other functions exist in prototype or will appear in the next version to make our lives easier and the users' lives better. The $F() function to get the value of any form field, an each() method for ruby-style loops, $R() for creating iteratable-ranges between specified bounds, all exciting additions to a language on the up.

Comments Off

Posted in design,technology by jake on March 15th, 2006

Comments Off

Posted in technology by jake on March 4th, 2006

ActiveRecord Angst… ReActivated.

Surely the last thing PHP needs is yet another interpretation of Active Record right?

Maybe, but this stuff is such fun to code, and for me all of those valiant copycat attempts still fall short in comparison to the elegant Ruby on Rails version.

The thing I admire most about Rails' ActiveRecord is the total clarity with which sub-classes represent the database table, and instances of those classes represent a row in that table. For well documented reasons, PHP5 still can't pull off this representation, and so most attempts use workarounds that kind of get there in the end, but sacrifice all of the Ruby elegance along the way.

My own hack is to use static methods in the base class to retrieve instances of subclasses, so that you can use:

$person = MyActiveRecord::FindById('Person', 12);

to find an instance of the Person subclass, rather than the preferable, but impossible:

$person = Person::FindById(12);

You can consider the base MyActiveRecord class as a kind of static Object/Relational Mapper whilst instances of its subclasses represent specific table rows.

It's a kludge, but still better than something like:

$dummy = new Person();
$person = $dummy->find_by_id(12);

Which in my view is just plain wrong architecturally, and also more awkward in use.

Here's a proof-of-concept class you can download under a BSD license. It has some limitations but in fact these might be advantages if you're after a quick and convenient ORM class to do your bidding, rather than a full-stack regime to tell you what to do. The double-edged limitations in question are:

No Upfront Declarations

To represent a table as a class you need do the following:

define ('MYACTIVERECORD_CONNECTION_STR', 'mysql://un:pw@yourhost/yourdb');
include 'MyActiveRecord.php';

class Person extends MyActiveRecord {}

And that is all. Obviously this requires some strict schema rules in your database. Each database table is named identically to the class that will represent it (is that really so bad?). Each table must have an auto-incrementing id and foreign keys must be named in the form ForeignTable_id.

The point is that you don't need to make any declarations in a constructor or configuration file. This holds for relationships too. There's no need to declare a one_to_many relationship upfront if you're going to use methods like this:

$articles = $person->find_children('Article');

Of course you might want to add composite properties, validation rules, clean-up routines and so on, but these can be achieved very simply by overloading the methods set_properties(), save() and destroy().

MySQL only

It's LAMP right? Not LAPP, LAOP, LASSP or LADP. Despite the accusations regularly levelled at MySQL, I think that's what most of us use and if you believe in getting everything through your ORM then there's a good argument that you really want your database to play dumb.

Apart from taking out the overhead of a database abstraction layer, knowing that it's MySQL we're connecting to enables us to leverage some vendor-specific retrieval methods, and offload type-conversion to the database server.

PHP 4 Compatible

If anything, the class runs better under PHP5, but PHP4 is still prevalent in most hosting environments including MADE's main web-server and this is intended to be a convenient, simple class rather than a paragon of PHP architecture. For that reason PHP4 compatibility is maintained, but that means

  1. triggering errors rather than exceptions
  2. 'StaticMethods' are implied by naming convention rather than enforced by the static keyword
  3. not leveraging __get(), __set() or __call(), all magic methods that could be really handy in a class like this...

It's quite big

You might easily argue that the class is monolithic and attempts to take on too much of the problem. It might be nicer to abstract the database-connection, table, column, errors and validation-routines into their own classes, but then before you know it you have an ORM framework that requires a book of its own to understand and that's absolutely what I'm NOT trying to do.

Not transactional

It's really not ACID and I'm not sure how I would rework it to make it so. That's actually a really strong argument for looking at a separate Mapper Class/Data Object Class, as the Mapper can also double as a Unit Of Work. This is the approach we take in our own framework StageBlocks...

So if none of the above puts you off, download the class and give it a whirl. I'm not aware of anything that plain doesn't work, but would really welcome any bug-fixes or suggestions for improvement.

1 Comment

Posted in technology by jake on February 15th, 2006

Yahoo JavaScript UI Library

Oooh… look at this! Seems like while everyone switched focus to Google Yahoo’s been making a concerted effort to become cool again. First there were all those Web 2.0 acquisitions, and now they’ve released their box of javascript UI tricks and widgets under a BSD license.

I haven’t had a good enough look to see how this stacks up to industry front-runner and MADE fave prototype, but I’ve always been a fan of Yahoo’s interface work, going back as far as the original Yahoo Directory. Before AJAX became all the rage Yahoo consistently came up with really innovative solutions to tricky UI conundrums using the more traditional fill-and-fire RESTy interface. Even now I think their freebie portal services (mail, calendar etc..) are really well designed. That’s why I’m really looking forward to getting deep into their Design Patterns also published today under a Creative Commons License.

A real example of doing the right thing, a gift to the web development community, and a welcome contrast to Google’s recent backtracking on content censorship in China.

Oh… and that’s the first post.

Comments Off

« Previous Page

categories


archives