Os Minnee


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Os Minnee

  1. 1. Ending Rails Envy in PHP5 __call for fun and profit! Slides with notes at http://www.siverstripe.com/rails-envy/ Who am I? Oooh, a white slide! Sam Minnée CTO SilverStripe Limited http://www.silverstripe.com The concepts discussed today have been used extensively in our BSD-licensed CMS, in production use on around 100 sites. SilverStripe is a BSD-licensed CMS focused on providing a productive development framework on top of a CMS that it aimed squarely at content authors, not developers. http://www.silverstripe.com It’s relatively new (first open-sourced November 2006) but our developer community is growing well and we’re always looking for new developers.
  2. 2. Why the Envy? PHP Rails Productive development Gets the job done, mostly platform with lots of cool stuff The language people love to hate Very trendy A variety of hosting options Harder to Host Good NZ government Too new for government acceptance (They like OSS!) Rails was one of the main options I considered when developing SilverStripe. However, there were other advantages to PHP that trumped it - in short, Rails would cut down our user-base too much. What to do? • Use PHP5 • Build frameworks to make it productive, and maybe even trendy. We decided to use PHP, but focus on building a productive development framework, a similar goal to the Rails team.
  3. 3. DISCLAIMER THIS IS NOT A LANGUAGE WAR I know very little about the details of Rails vs. what is presented today, in fact, I’m pretty sure that my understanding of the benefits of using Rails is pretty naïve. I just thought the title would be edgy. Forgive me. (besides, I still envy Rails. Just a little.) __call() The possiblities are endless with this handy little method... It lets us create “magic methods” are are implicitly defined. The __call() method of a class will handle any unrecognised method call. Similar methods for properties, __get() and __set(), can be used to create “magic properties” too.
  4. 4. Object-Relational Models The first use-case The way that I want it to be: An ORM is a great way of wrapping access to a database into a nice package. We wanted to add relationship information to our data classes, and have these accessible by set classes that implement Iterator, but need more The code shown in the presentation is criminally oversimplified. In particular, in a real implementation we would want to use For a more complete implementation, the SilverStripe codebase is a good place to look. First Approach Here we have defined a __call() method on the DataObject that
  5. 5. Problems • __call contains a lot of program-specific information. • The if / elseif construct lower performance as it grows • Won’t scale well to more kinds of magic functions. Second Approach Map of method handlers Define methods makes a number of calls to $this->addWrapperMethod(). This is how you define your magic methods.
  6. 6. Second Approach __call() implemented in Object The addWrapperMethod() method, and the __call() handler, are defined in a generic Object class. * addWrapperMethod() adds to Object::$extraMethods * __call() interrogates Object::$extraMethods to know what to do. Calling defineMethods Once per class, not once per object, for performance. Calling defineMethods() for every object can get really slow. You typically have to instanciate a large number of DataObjects to generate a single page.
  7. 7. Aggregation Adding Versioning to DataObject Note: Criminally Oversimplified This is a very simple illustration of how aggregation might be used to help implement versioning & staging. In this case, we’ve just used it to add publish() and rollback(). In a real implementation, you need a way of modifying the code for reading/writing DataObjects to actually change the data model. But that is beyond the scope of this talk. What can defineMethods do? • addWrapperMethod(‘Products’, ‘getComponents’); • addMethodsFrom(‘extensions’, ‘Versioned’); • Other possible • BUT: the more we have, the slower things get... So be careful! In addition to addWrapperMethod(), it’s worth adding addMethodsFrom() Performance in the __call() method is crucial because it will be used so often by your application.
  8. 8. Adding addMethodsFrom Step 1: Implement addMethodsFrom() that will be called by defineMethod(). It should add more stu! to Object::$extraMethods Adding addMethodsFrom Step 2: Update __call() to handle the new data that we’ve put into Object::$extraMethods Note: this isn’t a particularly well optimised sample. Improving on it is left as an exercise for the reader ;-)
  9. 9. Implementing Aggregation We can now use the addMethodsFrom() methods to implement aggregation, by updating defineMethods() in the Object class. Why Bother? • I’m Lazy • I’m Picky • (I like over-engineering?)
  10. 10. More Information http://www.silverstripe.com/rails-envy/ • Copy of the slides • Sample code • More notes • Or, email me on sam@silverstripe.com Thank you for listening!