Kris Wallsmith: Symfony2 ESI error: File name too long
kriswallsmith:
We recently came across a strange, intermittent error at OpenSky:
(36)File name too long: Cannot map GET /_internal… HTTP/1.1 to file
We use Varnish to cache large sections of our pages that include
follow/unfollow buttons. If the user is following a certain curator we show
the unfollow…
12:44 pm • 9 May 2012 • 1 note | kriswallsmith
Kris Wallsmith: Hello Spork! (aka "Forking PHP...")
kriswallsmith:
A few months ago I was tasked with speeding up the upload of assets to the OpenSky CDN, which was taking a few minutes each deploy. I ended up dividing the upload into multiple processes using pcntl_fork() and bringing the total time of the upload down to a matter of seconds.
Since then I’ve…
(Source: github.com)
1:31 pm • 10 April 2012 • 1 note | kriswallsmith
Kris Wallsmith: I ♥ Event Delegation
kriswallsmith:
jQuery event delegation is one of the coolest things since way cooler than sliced bread.
This new hotness allows you to listen for an event farther up the DOM than where that event is triggered. If you understand event bubbling, you should be able to grok this fairly quickly.
It starts getting…
(Source: api.jquery.com)
11:21 am • 24 March 2012 • 5 notes | kriswallsmith
“People tend to say things like ‘Git makes more sense when you understand […]’.”
— Required reading of the day: Think like (a) Git.
11:58 am • 7 November 2011 | bobthecow
Changing history, or How to Git pretty
OpenSky’s engineering and product teams have an ongoing lunchtime presentation series called Lunch and Learn. A couple of weeks ago, I gave a talk entitled “Lunch and learn2git”. I just posted an article on my blog based on that presentation. Check it out!
10:07 pm • 4 November 2011 • 1 note | bobthecow
OpenSky moving day!
12:08 pm • 20 October 2011 • 1 note | osky-tech-admin
How we chose Symfony2 as our web framework
As we set out to build the next great social ecommerce platform we were struck with a rare and great opportunity to start with a clean slate. We were able to select each piece of our architecture without any predefined requirements. This let us review the state of the Frameworks in PHP and select the best one for our needs.
First we developed a set of requirements
Brace yourself, it’s a long list.
- ORM
- DB Obj relationships ie: :has_many
- Good db migration mgmt
- Good master slave config for db
- Intelligent db trans support
- Scaffolding
- CRUD friendly
- Business logic kept in model not controller
- Controllers have ability to get heavy
- No heavy loading of controllers
- No race conditions for controllers (ie routing)
- Template engine
- Objects accessible in view
- Widget/component support in view layer
- Good header mgmt
- Good mgmt of js and css files
- All js and css be compressed
- Ability to define explict routes or priorities not based on file system
- Smart SEO urls by default
- XSS & CSRF Protection
- Good Form builders
- Form Validations
- No XML => YML or JSON
- enforcement of coding stds
- Convention and configuration
- Ability to design by contract
- Caching: Support for memcache and sessions
- Configs cached not parsed
- Cloud sensitive
- Good role base ACL support (no global, system base)
- Support for webservices
- Easily loadable support for external libs
- Profiler built in or easy to integrate (timers, number of queries, memory used, etc)
- Localization (currency, dates etc)
- CLI model access
- CLI for testing
- Unit testing
- Actions are unit testable
- Good file handling
- Good exception handling – ie log4j
- Support for multiple environments (dev, test, staging, prod)
Comparing Frameworks
Then we looked at any framework that someone on the team would be willing to evaluate. We ended up with 7 Frameworks to compare.
We only evaluated PHP specific frameworks as our team is primarily a PHP team and that is where our expertise is.
Notice that Zend Framework, Cake, Code Ignitor or X Framework aren’t on the list. There were a good 10 or so popular frameworks that enough of our developers had used before and knew they didn’t meet our requirements, so we decided not to spend time evaluating them further.
Our Analysis
We performed this analysis May 2010. In the past 6 months both Symfony2 and Lithium which are under rapid development would score even better. It’s not my intention to keep this chart up to date as it’s a representation of historical analysis.

Further Analysis
At the end of our week of analysis we had a good overview of each Framework though there wasn’t a clear winner. What was apparent was that a “check” wasn’t equal to another check and some frameworks excelled in certain areas where other’s simply did enough to check the box. This made our analysis quite a bit harder.
Additionally there were some other factors that weighted heavily into our decision. Strength of community, Quality of development and Momentum are the three factors that played the biggest role in our decision making, but are not represented in this feature set analysis.
Ultimately we narrowed it down to 3 frameworks. Lithium, Symfony2 and Zoop2. All 3 were PHP 5.2+ and Next Generation Frameworks. Given the substantial changes accompanying PHP 5.3, we determined that either we went with that now, or had a painful migration in our future. We decided to bite the bullet now which left us to choose between Lithium and Symfony2.
Lithium vs Symfony2
This wasn’t an easy decision. Both are excellent frameworks developed by really smart people. Nate Abele, who started the Lithium project and was the lead developer of CakePHP, is’s a personal friend and an NYC local. He was the person who turned me, and consequently OpenSky, on to MongoDB. Nate is doing innovative things with Lithium and has a true passion for what his work.
Symfony2 is developed by Sensio Labs located primarily in France, on the other side of the world. At the time there were only 3 stateside Symfony team members. Symfony2 uses a bit more conservative approach to framework development, basing it largely on learnings from symfony 1 and established practices and patterns largely from the Java world.
Ultimately we went with Symfony2. It wasn’t a cut and dry decision and in spite of all our diligence still ended up as a bit of a gut call. Symfony boasted a larger developer base and community. This was probably the factor that ultimately pushed us in Symfony2′s direction.
Why Symfony2
Fast forward 9 months. OpenSky has embraced Symfony2 with open arms. We have become the 2nd largest contributors to Symfony2 behind Sensio Labs. We employ Kris Wallsmith and Jon Wage, two core Symfony2 team members. We’ve developed one of the first production applications using Symfony2 and the first ecommerce platform on MongoDB.
More on why you should use Symfony2.
by Steve Francia
11:00 am • 3 February 2011 • 7 notes | osky-tech-admin
Inheritance in PHP, or why you want to use an Interface or an Abstract class…
Every class has an interface, every class can be typehinted as a method argument, typehint lets you specify the collaborator requirements. Not every typehint is the same… Example:
<?php
class PaymentGateway
{
public function charge($amount, BankAccount $account)
{
// make a call to http web service here...
$account->credit($amount)
}
}
<?php
class BankAccount
{
public function debit($amount)
{
//...
}
public function credit($amount)
{
//...
}
}
The example above is fairly straightforward – we have a PaymentGateway class that requires a BankAccount collaborator for crediting amount to be charged in its charge function. Since we call credit() on the second argument – we typehint it to be of type BankAccount, which would prevent us from passing anything other than instances of that class. Let’s add some more requirements to our little example. Say we have checking and savings accounts, and we need to be able to charge both of them:
<?php
class CheckingAccount extends BankAccount
{
}
class SavingAccount extends BankAccount
{
}
Since both accounts are subclasses of BankAccount – the typehint still works fine. However, we have now opened the possibility for abusing the typehint… In case you didn’t know – classes in PHP don’t define a strict interface, and are open to change by subclasses:
<?php
class SomeAccount extends BankAccount
{
public function credit($amount, $someOtherParameter)
{
//...
}
}
NOTE: if you have strict errors enabled, you would get one…
In the above example we changed the credit method signature by adding a second required parameter. We can now pass instances of SomeAccount class everywhere the BankAccount is expected and get nice fatal errors. Only interfaces and abstract classes/methods lock method signatures.
<?php
interface BankAccountInterface
{
function credit($amount);
function debit($amount);
}
class BankAccount implements BankAccountInterface
{
//...
}
For our particular example, we could use an abstract class:
<?php
abstract class BankAccount
{
abstract public function debit($amount);
abstract public function credit($amount);
}
Please note that in the example interface, I don’t specify method visibility. The reason is every method of the interface MUST be public and no explicit visibility means public in PHP.
<?php
class SomeAccount extends BankAccount
{
public function credit($amount, $someOtherParameter)
{
//...
}
}
A class like the one above would cause a fatal error to be thrown: “Declaration of SomeAccount::credit() must be compatible with that of BankAccountInterface::credit()” or “Declaration of SomeAccount::credit() must be compatible with that of BankAccount::credit()”, depending on which approach you chose to use. If someone wanted to implement a BankAccount to be used with our PaymentGateway, they would have to keep the method signatures exactly the same as we defined them.
Happy Coding!
10:38 am • 30 November 2010 | dereko
ZendCon 2010 in Santa Clara, California
Hi everyone, in case you didn’t know – there was a ZendCon last Monday November 1st through Friday November 5th, 2010 in Santa Clara, California and most importantly – I got to attend and OpenSky sponsored my trip.
ZendCon is an annual conference organized by Zend the PHP company and held in California. Its known to be one of the biggest conferences in PHP world with attendees from all over the world varying from developers to top management, all using and interested in PHP. Zend makes PHP announcements – this year among other things, they announced that memory footprint of PHP had been reduced by 35% in the upcoming version – which are then followed up by different session from speakers from all over the world. These sessions vary in scope and context from detailed practical “how to”s of a framework or tool, to high level management advices and experiences.
As I already mentioned, this year I was thrilled to be among ZendCon attendees!
I arrived in Santa Clara on the evening of November 1st. This was my very first visit to west coast and I loved it. The first thing I saw when arrived at Santa Clara (after a 6 hour flight and a 2 hour ride on three trains – one of which had two levels) was a big Yahoo sign on one of the buildings which immediately felt like technology heaven.
During the next three days, I met interesting people from all over the world, including people I knew from twitter, but never met in person. I would like to especially thank Ryan Weaver and Pablo Godel, who are seasoned conference attendees, for making a great company and helping me get accustomed to the environment and people at the conference. I also met and spent a decent amount of time with people as: Jonathan Wage, Fabien Potencier, Nils Aderman, Dustin Whitle, Michelangelo van Dam, Jeremy Kendall and many many others.
I learned about Zend Uncon from Michelangelo during continental breakfast of the very first day of the main conference. Turns out that anyone could give a talk, even if it wasn’t included into the main session program. This is called the Uncon and there you can give a talk, do an interactive tutorial or round table on any topic you choose, all you need is to put your name in an empty slot in the Uncon schedule. Uncon sounded like a great idea and a good public speaking practice, so I registered… The session was amazing! Twitter was blown by quotations from my talk - tweeted, retweeted and re-retweeted. Attendees took pictures of me speaking and posted it on twitter too. Overall I was blown away by the success of my little experiment. As a result, my session was called the best Uncon session and I won a free lifetime license for Zend Studio 8 (they even wanted to call me up on stage during the final keynote, but I had a plane to catch that day).
Jonathan Wage, who joined OpenSky on the November 1st, 2010, suffered from poor organization on the conference part. He was unfortunate to get scheduled to arrive after his first session and leave before the second one. As a result, he gave only one talk of the two planned as part of the Uncon. His talk was, however, really amazing and well received by attendees and they wouldn’t let him go for a good 30 minutes after the talk was over, asking questions and expressing admiration.
Thank you ZendCon and see you again next year! Below are some pictures I took at the conference:
4:12 pm • 8 November 2010 • 7 notes | osky-tech-admin
Unit Tests, Mocking, and PHPUnit 3.5′s new Mock Builder
Unit testing is all about testing one piece of functionality in isolation. This is very easy when the subject of your test doesn’t involve any dependencies. Take the following method:
<?php
class Tag
{
public function normalizeName($name)
{
$normal = trim($name);
$normal = strtolower($normal);
return $normal;
}
}
Testing this method requires just an input and an expected output. This is a good case for using a PHPUnit dataProvider:
<?php
class TagTest extends PHPUnit_Framework_TestCase
{
/**
* @covers Tag::normalizeName
* @dataProvider provideNormalizeName
*/
public function testNormalizeName($input, $expected)
{
$tag = new Tag();
$this->assertEquals($expected, $tag->normalizeName($input));
}
public function provideNormalizeName()
{
return array(
array('foo', 'foo'),
array('FOO', 'foo'),
array(' foo ', 'foo'),
array(' FOO ', 'foo'),
);
}
}
Unfortunately, it’s not always this easy. Let’s say we want to centralize this normalization logic in some sort of reusable Normalizer class, which we inject into the Tag class:
<?php
class Tag
{
protected $normalizer;
public function __construct(Normalizer $normalizer)
{
$this->normalizer = $normalizer;
}
public function normalizeName($name)
{
return $this->normalizer->normalize($name);
}
}
The test above still passes, but we are now testing two things: the normalizeTag method and the Normalizer class; we are no longer testing our method in isolation.
Mock objects to the rescue!
To restore this isolation we create a “mock” version of the Normalizer class and tell that mock exactly what we expect will be done to it and how we want it to respond.
In PHPUnit 3.4, creating this mock object would look something like this:
<?php
class TagTest extends PHPUnit_Framework_TestCase
{
/**
* @covers Tag::normalizeName
*/
public function testNormalizeName()
{
$input = 'foo';
$expected = 'foo';
// the final "false" tells PHPUnit not to call the Normalizer
// constructor because it requires another dependency, which we don't
// care about right now
$normalizer = $this->getMock('Normalizer', array(), array(), '', false);
$normalizer
->expects($this->once())
->method('normalize')
->with($input)
->will($this->returnValue($expected));
$tag = new Tag($normalizer);
$this->assertEquals($expected, $tag->normalizeName($input));
}
}
Most of this is quite readable, thanks to Sebastian’s nice mocking API. However, the initial getMock method is a bit gnarly. I’ve added a comment so you understand what’s going on, which I’d rather not have to do.
In PHPUnit 3.5 we can use the new mock builder object, a contribution of Giorgio Sironi, which makes our test code that much more readable:
<?php
class TagTest extends PHPUnit_Framework_TestCase
{
/**
* @covers Tag::normalizeName
*/
public function testNormalizeName()
{
$input = 'foo';
$expected = 'foo';
$normalizer = $this->getMockBuilder('Normalizer')
->disableOriginalConstructor()
->getMock();
$normalizer
->expects($this->once())
->method('normalize')
->with($input)
->will($this->returnValue($expected));
$tag = new Tag($normalizer);
$this->assertEquals($expected, $tag->normalizeName($input));
}
}
So there you go: unit tests, mocking, and the new mock builder.
by Kris Wallsmith
4:00 pm • 29 October 2010 • 10 notes | osky-tech-admin