PHP isn’t that bad

Katy Williamson
The Storyblocks Tech Blog
6 min readJul 18, 2022

Walking our (currently metaphorical) halls, you’ll hear a lot of self-deprecating humor about our monolithic core site, www.storyblocks.com, which is written mostly in PHP. It’s important to not take ourselves too seriously, right?

But as a company, Storyblocks (SB) has a highly tech-agnostic culture. We use a lot of different technologies, and we’re constantly having those important conversations — evolving, experimenting, and trying to pay down technical debt. And I think we got that way by learning the cost of maintenance of our beloved monolith. A team of engineers with a shared experience like that is a powerful thing. It keeps our values top-of-mind as we look toward the future.

Photo by Nicole Wolf on Unsplash

A little history

Storyblocks was founded as Videoblocks in 2009, and some of the PHP foundation was laid then. The backend, frontend, and much of the business logic of the core site was achieved in one PHP repository that a handful of engineers worked on. If faced with the same decision today, we might not make the same choice, but it made sense for a few reasons.

  1. In 2009, the PHP community was strong. The open source of PHP was popular and well-maintained. Facebook chose it, and Vimeo (then underwent a similar journey to ours). Today, it’s still widely used, but many references say it’s in decline.
  2. NodeJS launched in 2009, and the field of alternatives widened in the 2010’s. Today, PHP is not known as the most performant option.
  3. PHP is known to have a low learning curve, being clear, well organized, and easy to understand. On the flip side, it’s very flexible and can be un-opinionated, increasing the potential for errors. Over the last 13 years, by adding new engineers to our team and adding scope to the codebase, we’ve created more than a few messes for ourselves to clean up.
  4. Monolithic architectures are great for small teams, simple applications, and quick launches. All of these things were true of SB in 2009. Monoliths also started getting a bad rap around 2010–2012 when the big names in tech (e.g. Amazon) were vocally defending their decisions to switch to micro-service architectures.
% of StackOverflow questions per month (source)

Enter: newbie, stage left

When I was interviewing with Storyblocks in 2020, I almost said “ick” out loud re: the PHP monolith, but still I was excited to hear about it. The way my interviewers talked about it — their dreams for improving it, and how important tech-agnosticism is to them — I could tell this team was invested in collaborative problem solving, not just listening to one senior architect’s opinions. Invested in refactoring and tuning, as much as greenfield development or rip & replace.

And the fact that so many lines of old code, written by the founding engineers of Videoblocks, were still in production doing what they were supposed to do impressed upon me that I would be surrounded by smart and talented people when I joined!

PHP cannot die (source)

Well well well, how the turn tables

Fast forward two years, and in the course of my day-to-day work on the Maker product (check it out here and here!), I work with technologies that are more “favorable” than PHP. In 2018, the founding engineers of Maker heeded the learnings of the past, and set things up pretty differently. Maker is written in React, and split into three small codebases: Frontend, Renderer, and Engine. And we joke that we operate like a “startup within a startup,” free to make decisions that could flop or could inform improvements to SB’s other products and services.

And today, when I dabble in the core site PHP code, I find myself comfortable navigating it, and noticing how far it’s come. PHP releases regularly, and is releasing v8.2 later this year; from what I can tell v5 and then v7 offered huge boosts in performance over what we were used to at founding. In 2018, my predecessors added the Laravel framework, including the Eloquent Object-Relational Mapper. In 2020, there was a huge “One Url” refactor effort that consolidated three domains into one, and cut our legacy PHP code by half. Today, the team is united to break chunks of functionality off into micro-sites, micro-services, dependencies, backends-for-frontends, etc, whenever we can — but since the code is stable and well-tested, we’re not in a panicky rush to do so.

Scrubbing PHP off for the 2020s (source)

Recently, I even found myself reflecting on how not-bad our monolith can be, with the addition of the Laravel framework. On my first day at SB, I remember feeling like our PHP code was pretty overwhelming… but now I’m having thoughts like “Laravel is pretty cool” and “hey, I was able to solve that problem rather elegantly.” Coming from a Java & Spring background, Laravel’s Eloquent ORM is really clean. And Laravel’s Artisan CLI makes other operations easier too — from super-user stuff in your local dev environment to model changes in production.

A little love for Laravel

Consider an association table (aka pivot table). To populate the table with many-to-many relationships of Model A (let’s say Project) to Model B (let’s say Upload), all you have to do in Project is,

public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'project_uploads');
}

and where Projects are created or updated,

$upload->projects()->sync($project);

Beautiful! In Java Spring, the relationship would need to be defined as an entity, bringing with it a mess of annotations and dozens more lines of code.

The Laravel router is nice too. Check out how we register our controller methods as routes:

Route::apiResource('upload', Api\UploadController::class);

Et voila, you have index, create, store, show, edit, update, and destroy ready to be defined in your controller! In Java Spring, adding CRUD operations to a model requires code generation so everything gets properly autowired before you start using it. If you want to make a change, you’ll have to regenerate or fight with complicated annotations. With Laravel, there is automatic propagation of changes in routes into relevant links (a feature called “reverse routing”). No fighting with configuration at all.

One last highlight is the Artisan CLI. Recently I needed to make copies of a bunch of models in the production database, while tweaking one property. I used artisan to generate the boilerplate for such a command,

php artisan make:command CopyBrandToOrg

And in the autogenerated file, just filled in the handler (I cut out some of the boilerplate/phpdoc here for brevity):

<?php
namespace App\Console\Commands;
use App\TemplateEditor\Models\Brand;
use Illuminate\Console\Command;
class CopyBrandToOrg extends Command
{
private int $brandId;
private int $organizationId;
protected $signature = 'brand:copy-to {brandId} {organizationId}';
protected $description = 'Copy a brand between orgs.';
public function handle()
{
$this->brandId = intval($this->argument('brandId'));
$this->organizationId = intval($this->argument('organizationId'));
$originalBrand = Brand::where('id', $this->brandId)->firstOrFail();
$newBrand = new Brand();
$newBrand->organization_id = $this->organizationId;
$newBrand->detail = $originalBrand->detail;
$newBrand->save();
foreach ($originalBrand->uploads()->get() as $upload) {
$upload->brands()->syncWithoutDetaching($newBrand);
}
}
}

Then I ran it as many times as I wanted (in this case, 200 times), with confidence that my models were being created correctly!

#!/bin/sh
php artisan brand:copy-to 123 1007 --env=prod
php artisan brand:copy-to 123 1008 --env=prod
php artisan brand:copy-to 123 1009 --env=prod
... and on and on

My eyes were opened to how I could make the oft-maligned PHP work for me.

It can work for you too

All of that to say, SB is taking steps to modernize our monolith, but PHP is a part of us and will be for a while yet.

The main takeaway from this journey is, don’t let deviation from a popular tech stack deter you. On the right team, it’s not a frustration — it’s a colorful history, a uniting challenge, a learning opportunity, and a catalyst for your engineering values.

And PHP really isn’t that bad!

Willing to put your technology biases aside and work with great people? We’re hiring!

--

--