Tracking down bugs can be hard. Damn hard. And figuring out how or when they cropped up in the first place can be even harder. Recently, we launched our social media aggregator platform, Waaffle. It’s written in Laravel and deployed with Envoyer, but we also took the opportunity to try out Sentry for tracking bugs.

Spoiler alert: it was awesome.

One of the features I really like is the ability to track releases, which means you can tell at a glance which release was responsible for your bug. We’ve got a deployment hook in Envoyer that pings Sentry when we deploy a new release. Our hook runs in the “After” section of the “Activate New Release” action and contains the following command:

(FYI, it’s the very last post-deployment hook we run, just in case another hook fails.)

The Sentry PHP package includes a section in the config for specifying your app version. However, things can get tricky if, like us, you’re using, say, git commit hashes instead of version numbers.

Thankfully, Sentry’s Laravel package provides code for a nice release hash you can use for getting your git commit hash:

'release' => trim(exec('git log --pretty="%h" -n1 HEAD'))

Which if you run in Artisan’s tinker mode, gives you something like this:

1a2b3c

Now the problem: we use Envoyer for our deployments, which downloads the tarball of a specified branch/release/tag instead the entire git repository. That tarball doesn’t contain any of the git history in it, so it’s not technically a repository, thus running the Sentry Laravel command won’t give you a commit hash. If you try, you’ll get the following lovely error:

fatal: Not a git repository (or any of the parent directories): .git

Which means if Sentry tracks an error and saves it, you’ll see there’s no release attached to the issue. Drats!

Somehow, we need a way to get the current commit hash from our Envoyer deployments so we can tell Sentry how to get the current commit. Thankfully, Envoyer comes to the rescue!

In the Envoyer docs, under Deployment Hooks, you’ll see a section on how you can get the current git commit hash (or sha1 hash). Now, this hash is actually the first 12 characters of the current git commit hash – aka. something you can use in the deployment lifecycle.

From here, we want to target the current release directory, so let’s create a deployment hook in the “After” section of “Activate New Release” and call it “Write Git Hash to File” with the user “forge”:

echo "{{ sha }}" > {{release}}/.commit_hash

Pretty simple, huh? All it does is echoes the current git hash to stdout (standard output), then we redirect that output to a file called .commit_hash in the current release directory. The single arrow (>) means “set the file .commit_hash to 0 length, then append to it”. If we used two arrows (>>) we’d only append to the file, which we wouldn’t want to do – though technically it doesn’t really matter given the release directory has just been created, but it’s the principle of the thing!

Once we’ve got that file written on every deployment, we need to tell Sentry how to get that commit hash! If you wanted to, you could change the config so Sentry fetches the release, like so:

'release' => trim(exec('echo "$(< .commit_hash)"'))

(Note that I’m using echo and redirection here, I don’t want to get into the UUOC debate!)

Except this only works if you have that .commit_hash file in every environment, which we don’t. So, we’re stuck between a rock and a hard place. What we need is a solution that uses the .commit_hash file if it exists, or falls back to a git repository, or finally, returns null if neither of those exist.

In our project, we’ve got a small helpers file with all functions that exist in the global namespace. That’s where we put our solution:

Pretty basic really – just an if/elseif/else block with three possible outcomes. Note that I’m using the base_path Laravel helper, so we can be sure we’ve got the full path to the file/folder in question. Then, in our Sentry configuration file we have the following for the release:

'release' => get_commit_hash(),

Now whenever Sentry needs the commit hash, it’ll call that function and get its return value. Nice! And for those of you concerned about the overheads of getting the commit hash, you can do a php artisan config:cache so the hash is only calculated once. I highly recommend caching the app configuration as part of your deployment process to help to make things that little bit faster. That file is located in bootstrap/cache/config.php and you can verify the existence of this cached value by doing the following (in the root of the project, with the configuration cached):

When Instagram added the ability to upload non-square media images to their service, the only way to get a cropped version of the image from the API was via the thumbnail attribute from the media endpoint. Those familiar with the API would know that Instagram’s thumbnails are served at a rather small size of 150×150 which is alright in some cases, but if you need a larger thumbnail size a 150×150 image scales up very poorly.

Here’s the images attribute in the API response for a recent Instagram post we did:

And here’s the thumbnail for that image:

Scaling that thumbnail up even 1.5 times makes it look very grainy and shows very little detail. For normal square images you can just use a different image size (like low_resolution or standard_resolution), but for images that aren’t square, you won’t get a nice square image. Not great if you’re trying to use a square grid to display Instagram pictures.

Now, here’s the images attribute in an API response for another recent Instagram post we did, except this time the image in question is landscaped:

Instagram are nice enough to provide a cropped, square version of the image for the thumbnail, but the low_resolution and standard_resolution URLs are both uncropped and are not square. Gross!

Say we want a 320×320 thumbnail of the Instagram post, but as you can see, we want a square image. If we use the low_resolution URI, we’ll get this:

If you take a look at the URIs for the images, you’ll notice that the thumbnail URI has an extra parameter in the filename path… the magical crop dimensions! Unfortunately, the crop dimensions aren’t accessible anywhere else in the API (as far as I know), except for in the thumbnail URI. With a bit of spelunking and messing around with the URI, you can change the s150x150 part of the URI to s200x200 for example to get a 200×200 sized thumbnail.

With that in mind, I’ve set the thumbnail URL to use 320×320 instead of 150×150 and voila! We have a larger, square version of the Instagram image:

Note that you can’t provide arbitrary dimensions and expect the API to automagically generate custom images sizes to your specification (Instagram isn’t an image processing CDN!). Change the dimensions to s220x220 and you’ll see what I mean.

If you run the above command you’ll see that the server returns a 404 “Unsupported Size” error in the headers but the body response is 5xx server error. Assuming the thumbnail size you wanted was a thumbnail size Instagram generated, you can semi-reliably use your custom dimensions, however I couldn’t guarantee that those thumbnail sizes will remain accessible forever. We’ve decided to bite the bullet and use 320×320 image dimensions where we can, so fingers crossed they don’t remove those dimensions!

If you’re crawling the API with a script, you can do something like this in PHP to alter the thumbnail (where $post is your Instagram post object):

Recently there have been some interesting discussions and posts about the use of incrementing IDs in websites and whether that’s accidental information leakage or not. An excellent article by Phil Sturgeon showed that you can learn a lot about how much a service is being used with just a few minutes of investigation. An incrementing identifier (or ID) is an integer that starts at 1, and is increased by 1 each time a new record is saved to the database. A UUID (or universally-unique identifier), on the other hand, is a 36 character long identifier made up of 32 alphanumeric characters with four hyphens in amongst it. Due to the length of a UUID it is much more difficult to guess UUIDs, let alone figure out how many users have registered on a site.

Note! The code in this article was written for Laravel 5.1 LTS

In the last few months we started working on a new project in the Humaan labs and the discussion of IDs versus UUIDs came up. This particular project was to be written in Laravel, and while Laravel uses auto-incrementing IDs as the unique key for a model, it’s easy enough to switch those out and use UUIDs instead. Having said that, we decided that we wanted to keep the auto-incrementing IDs for internal use but use UUIDs for user-accessible records (and by that I mean records where a URI would need to be generated like /post/uuid-here, for example).

So, I was tasked with implementing UUIDs for models in Laravel which, in itself, isn’t a difficult task. There were a few caveats however:

Not all models will have UUIDs so it can’t be on the base Model class

It must be reusable so adding or removing it from a Model doesn’t involve copying/removing a chunk of code each time

Users must never be able to generate their own UUIDs nor can they override them

However I implement UUIDs there must be a method that allows me to supply an auto-incrementing ID, or a UUID, which will return the requested record

Given that it must be reusable and can’t be on the base Model class in Laravel (and by that I mean the one in app/models, not the actual Eloquent class itself), I decided to go with a trait (truth be told I actually initially went with an abstract class but having to override the parent boot method just didn’t seem right). While there’s no defined place to store traits in Laravel I created a folder in the app/ directory called Traits. The name of our trait is UuidModel so, naturally, the file name is UuidModel.php.

When working with UUIDs in PHP there’s no point trying to roll your own solution to create and validate UUIDs. Time and time again developers have been caught out implementing their own half-baked solutions (hello rot13 or base64 as “hashing” or “encryption“), so we’re going to use a well-known PHP library that will generate the UUIDs for us. Open up your terminal and enter in composer require ramsey/uuid and press enter. Alternatively you can put "ramsey/uuid": "^2.8" in your composer.json file and run composer install. Once that library has installed, we’re ready to go!

Pretty basic so far – just a namespace, use statement, and the trait itself. If you look at the source for the base Eloquent Model class (for reference: Illuminate\Database\Eloquent\Model) you’ll see there’s a method pretty early on in the piece called bootTraits. This is called by the booter and looks for any traits on the model that have a static method starting in boot. This means that rather than having to do a nasty like this:

protected static function boot()
{ parent::boot();

// our stuff here
}

And perhaps forgetting to call parent::boot(); in a sub class (and thus causing Eloquent to implode) we can safely separate out our boot logic without interfering with the rest of the boot process. On a side note, if there’s one BIG tip I can give anyone working with Laravel it’s to check out the source code. You’ll find so many handy methods that will make your life much easier (and quicker too). Anyway, now that we’ve figured out we can add to the booting process, we’re going to make our booter and then attach some event listeners to the model so we can watch for specific events.

The boot method for the trait must be the same as the trait name with boot prepended. So, UuidModel becomes bootUuidModel, PickleCat becomes bootPickleCat, you get the idea. Check out the method class_basename in the Illuminate\Support\helpers.php file to see what it looks for. As mentioned before, the method must be static so don’t forget that keyword otherwise your booter will never run.

First off, we want to ensure that users can’t be sneaky and assign their own UUIDs (this is assuming your FormRequests, controllers, models, and what not prevent user input from setting the UUID) we’ll need to watch the creating event. This alone is perfect for preventing user input from wiping out your UUID but also saves you having to add another line to each instance where you create a model with UUIDs and generate it. What it doesn’t count for, however, is updates to the model. Thankfully, there’s an event for saving updates to a model so we can bind to that too. Let’s get started, shall we?

As mentioned in the Laravel Eloquent documentation, you can use a Service Provider to listen in on Eloquent events, or you can just use the late static binding static keyword to reference the current class in runtime! Simply put, the line static::creating will be called when that event is fired on the current model.

We’ll use a anonymous function as the creating event callback and supply the current model as a parameter with the name $model. Assign the attribute uuid with our UUID that we generate by calling the uuid4() method, and getting its value as a string (without the toString() method, the UUID is actually an array with 6 values). Pretty simple really. The creating event fires just before the model is persisted to the database, so unless you have a trait that boots after, your assigned UUID won’t be overwritten. If you’re curious on where this event is in the workflow check out the method performInsert on the aforementioned Eloquent model class.

Once again in this boot method we’ll bind to event but this time we’ll bind to the saving event. This one is a little more complete, mainly because we have to verify that the UUID hasn’t been altered in some way (whether that be maliciously, or accidental – although that’d never happen, we both know programmers never make mistakes). Whenever you’re interacting with an Eloquent model, you’ll notice that there’s an attributes property along with an original property. If you were to make a modification to the Eloquent model during the application lifecycle the changed value is stored in the attributes property. Using this information, we can safely check to see if the UUID stored in attributes is identical to the UUID in original.

Using the handy Eloquent method getOriginal, we can obtain the original UUID value and compare it. If the UUID has been changed somehow, revert it back. If the UUID hasn’t changed, we do nothing. This alone will give you UUIDs for a model in Laravel, but what if you want a reliable way to search for a particular model without having to write Query Builder statements every time? Look no further, I have the solution below.

As you may recall, Eloquent models have the fantastic ability that allow you to generate custom Query Builder queries on the model that can be reused time and time again. If you’re not familiar with these “scope” queries take a look at the “Query Scopes” section in the Eloquent documentation. I’ve defined two queries that we can use – one called scopeUuid, which receives and searches for a UUID only, and another query called scopeIdOrUuid, which can take either an ID or a UUID, and find the associated record. In both my scoped queries, I’m going to add an extra parameter so I can either return the model directly or return the Query Builder instance. This is more of a convenience thing rather than anything else – I find I’m usually just fetching a model straight rather than using the Query Builder, but adding it in means I can have the best of both worlds.

On to scopeUuid:

As with our magic booter method, all methods starting with scope are magically called by the Eloquent Query Builder class. Our first parameter is a required one that all scopes must include. It’s the Query Builder query so you can access the Query Builder, and return it to chain queries. Next up in our parameters is the UUID, enough said. Thirdly, the boolean parameter to determine whether we return the found model, or the Query Builder instance. This defaults to true as a convenience – it works well for me but feel free to change or remove it if you find it not to your taste.

First up in our method is a bit of a doozy – first we need to check to see if the supplied UUID is a string and secondly we need to make sure it’s a valid UUID. The is_string (line 14) check, while defeated easily, is necessary to ensure we don’t pass an object, array, etc off to preg_match and cause a fatal runtime error – that ain’t catchable! The regular expression you see above is designed specifically to match UUIDv4 strings. Certain parts of the UUID string start with specific letters so we do a check to make sure that we don’t have a v1 UUID, for example.

If for some reason the above regex doesn’t work for you, use ^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$ instead, which is from the above UUID library. This regex will verify that a string matches any type of UUID, regardless of version.

If either one of the if statement checks fails, we throw a ModelNotFoundException exception so the developer can reliably catch it. Next up, we simply chain a where method call (line 18), which essentially means WHERE uuid = $uuid (Eloquent actually uses parameters with SQL, but this statement is purely an example of what the query would look like – never ever ever send user data blindly into an SQL query).

Lastly, in our little scope that could, we do a check to see if the $first parameter is set to true or false (line 20). If it’s true, return the firstOrFail method that executes the $search query or return the Query Builder instance so we can keep on chaining. There we are! Our scopeUuid method is done, now it’s on to the scopeIdOrUuid method.

This method is rather similar (the only parameter that’s different is $id_or_uuid – pretty self explanatory really) so I’ll just breeze over it quickly. First, we’ll do a check to ensure it’s either a string, or numeric (whether that be 1 or '1' – line 14), and throw ModelNotFoundException if it isn’t. Next, use regular expressions to determine whether the $id_or_uuid variable is an integer or a UUID (line 18). If it doesn’t, throw a ModelNotFoundException exception.

Next up is a nifty feature of the where method in Query Builder. Did you know where can actually be a callback, you can nest WHERE queries in one bigger WHERE query so that you don’t accidentally break your tightly scoped query with a misplaced WHERE. We’ll use an anonymous function for our callback and use the use language construct so that our anonymous function can inherit the $id_or_uuid variable from the parent scope (line 22).

Once again, a final check to see if the developer wants the model (or catch a ModelNotFoundException) or the Query Builder instance returned to them (line 27).

And there we are! Now you can go out and use it! Oh wait, no you can’t. Unless you’ve already generated UUID fields your models won’t be able to store their UUIDs! Whip up a migration using php artisan make:migration _migration_name_here and let’s add UUIDs to the tables. For each table that needs a UUID, add this to your schema:

$table->string('uuid', 36)->unique();

If you’ve installed doctrine/dbal and are using MySQL, you can also append ->after(‘id’) to the above command so it appears after the ID in your SQL table.

To use this handy trait, use it in a model like so:

// app/User.php

use App/Traits/UuidModel;

class User extends Model
{ use UuidModel;
// ...

Simple as that! It’s also recommended that you add the ID to the hidden attributes property so the ID is removed from the array/JSON representation of the model. Add the following to all your models using the UUID trait:

For those of you who don’t know me, I’m a huge Laravel fan. I recently finished up a large project for a client, and I learnt many important things along the way. Below, you’ll see features of Laravel I used and loved in Laravel to make the development cycle much more enjoyable (and painless). By no means should you feel like you have to, these are merely just tips I’ve found that helped me.

Middleware is awesome – use it.Middlware allowed me to very easily filter out users who had been added to the portal, but had not activated their account. It also gave me the ability to block access to users who once had an account in this portal, but were now “archived” and no longer able to log in and make changes. Middleware is easily applied/removed to routes as you require, so use them when you can!

Form Request validators can help you save time. The Form Request classes allow you to easily abstract your form submissions into a separate step/file which in my opinion, makes for cleaner code. The portal I developed had a number of different models, and having one validation Form Request for each made it so easily to ensure the data submitted would be validated correctly. Type hinting is amazing.

Home(stead) is where the heart is. Just in case you didn’t know, Homestead is a pre-configured development environment for Vagrant that makes it painless to develop your PHP site with a modern toolset. Technically, Homestead is created for Laravel, but you can use it for any PHP project! I have the VMware Integration for Vagrant which I find to be a fair bit faster, but if you’re just checking Homestead out , the VirtualBox adapter should be more than enough.

Eloquent accessors and mutators are fantastic. Instead of jamming your create/update methods with formatting of different attributes of a model, use mutators and accessors to automatically handle all those little tasks. For example, in a project I needed an attribute to be stored in the database as JSON, but when accessed within the project, it’s automatically formatted to an array by the Eloquent model. When that array is modified throughout the lifetime of the application and then saved back to the database, it’s converted to a JSON string. It can be tempting to include validation in mutators, but I would recommend against doing that. For the most part, use it as a way to convert or format one thing to another.

Forge and Envoyer are a match made in heaven. When it came to deploying this project, I had the opportunity to deploy to a VPS, rather than a bog-standard Apache web host. I decided to deploy to DigitalOcean using Forge then continuosly deploy using Envoyer. The initial configuration of Forge + Envoyer was a bit confusing, but luckily Laracasts came to the rescue. After I got my head around how the two worked together, all updates I’ve done to the project since have been easily deployed with virtually no hassle at all.

Finally,

Testing… 1, 2, 3, testing… In Laravel 5.0.x, I was using Jeffrey Way’s Integrated testing utility, which got merged into Laravel core in 5.1. The aforementioned testing utility allows one to write tests in a more self-explanatory way. What that means is rather than getting down and dirty with PHPUnit, you can write tests like $this->visit('/')->see('Hello!'); which reads much better.

By the way, if you’re interested in signing up with DigitalOcean, please use my referral link. I scratch your back, you scratch mine 🙂

Update (24/02/2015): Laravel 5.0.6 has been updated to support cleartext X-XSRF-TOKENs. As explained in the recent post CSRF Protection in Laravel explained by Barry vd. Heuvel, Laravel can now process X-XSRF-TOKENs if they are transmitted in cleartext. Some would argue it’s still better to encrypt the CSRF token, but that’s for much smarter InfoSec people than me.

The following article was written for Laravel 5.0.5 in mind, but is still relevant as of 5.0.6

If you’ve recently started using Laravel 5 and are trying to use csrf_token() with the header X-XSRF-TOKEN with your AJAX requests, you’ll notice that you get a HTTP Error code 500, rather than a 200 OK response. This is because the CSRF middleware is expecting the csrf_token via X-XSRF-TOKEN to be encrypted – Something the Laravel documentation doesn’t make clear.

When I originally stumbled across this issue I thought it was a bug in Laravel and submitted a PR (which turned out to be a bad, naughty, terrible, not so good thing to do – in short, I should learn to search.) Regardless, we have two ways of getting around this. Our first way is to just encrypt the damn CSRF token and use that in our code, or alter the middleware to not perform decryption on the CSRF Token.

Option 1 – Encrypted CSRF Token

Our first option is to encrypt the CSRF token. As you may already know, you can access the CSRF token by using the function csrf_token. Load up your routes.php file so we can add the encrypted token to the views.

For each view you call, you’ll need to append this method:

withEncryptedCsrfToken(Crypt::encrypt(csrf_token()));

So, if you were calling a view for the home template, you’d do this:

view('home')->withEncryptedCsrfToken(Crypt::encrypt(csrf_token()));

Terrific. In that template you can access the variable like below:

<meta name="csrf_token" ="{{ $encrypted_csrf_token }}" />

Chuck that in your main view in the <head> so your JavaScript framework of choice can gobble it up. Just make sure to do use Crypt; if you’re in a different namespace.

Option 2 – Non-encrypted CSRF Token

Our second option is to alter the VerifyCsrfToken middleware to not expect an encrypted CSRF Token when transmitted via a HTTP Header.

Open up the VerifyCsrfToken.php middleware (located at app/Http/Middleware/) and we’ll extend the method tokensMatch.

Essentially, what I’ve done is copied the method from Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php then removed the call to $this->encrypter. You’ll also need to add a use at the top of VerifyCsrfToken.php like so:

Implementing in jQuery

If you happen to be using jQuery with Laravel, here’s how you can add the HTTP Header to your AJAX requests. As usual, there’s a few different options. If you’re doing a heap of requests over the lifetime of the session, you’ll want to set this token for all AJAX requests. If not, you can do it inline with the AJAX call.

Moving Forward

Now, it’s entirely up to you how to proceed. Just to be safe, I’ve decided to go with Option 1 because I want to err on the side of caution, but if your Laravel 5 app is super simple and can’t do much/any harm, I think it’s OK for your CSRF Token to match in a string-to-string comparison, but not be valid JSON.

Only time will tell.

Updates:

19/02/2015: — I originally had the CSRF Token encrypted in the boot method of the AppServiceProvider. This was incorrect as csrf_token isn’t set unless it’s called from within a Route. My mistake!