🎉 Our packages have been downloaded one million times 🎉

I’m very happy to announce that, as of today, our Laravel and PHP packages have been downloaded a million times. We now have more than 80 packages registered on Packagist. All combined they are downloaded around 150 000 times a month, and that number seems to be growing. Our GitHub organisation has taken the number 13 spot on GitHub Awards. I’m very proud that we could achieve this in a company with only two back end developers. It’s really nice to know that the Laravel and PHP community find our packages useful. In this post I’d like to share the story behind our packages.

That one million number sounds impressive, but should be taken with a grain of salt. The amount of real users is probably much lower. Some of our packages require other ones of our own. For example, when downloading laravel-backup, our own db-dumper will get downloaded as well. And I’m pretty sure the total downloads get inflated by CI tools that download the various packages more than needed.

I think the actual number of downloads isn’t that important. The monthly growth number is a more representative figure of how our packages are doing popularity-wise.

The first package

The company where I work, Spatie, exists from 2003. We’ve always been using PHP. In the early years we dared to write our own framework. Yeah, we were still inexperienced, so that seemed the way to go. It was very basic, but it served us well. We were only creating small sites at that time. But after several years we realised that writing and maintaining your own framework is very time-consuming and we switched to Zend Framework 1.

In 2012 and 2013 we felt that the PHP ecosystem was pretty stale and we considered switching to Ruby and the Rail framework. We even made a couple of projects in Ruby to get our feet wet. But then we bumped into Laravel 4.0. I was immediately impressed by the expressive syntax and the big focus on developer happiness. I used it for a couple of projects and the more I learned about it, the more I loved using it. At that time a guy called Jeffrey Way started his next project Laracasts: a video tutorial site dedicated to Laravel. Realising that his videos could speed up my learning process immensely I immediately bought a lifetime subscription.

On the 4th of March in 2014 Jeffrey published a video titled “Continuous Integration With Travis“. My mind was blown. Travis and the integration with GitHub looked so cool that I wanted to use it. A couple of months before he made the Travis video Jeffrey made a miniseries on package development. Those videos sparked the thought in my mind that I could create a package of my own.

In a project at the time we needed to automatically create screenshots of a website. With the things I learned in the Laracasts-videos I started working on my first package Browsershot. In essence it’s just a simple wrapper around PhantomJS. It was pretty exciting working in the open. I was thrilled every time the download counter got up and was incredibly happy that other people started writing about it.

Moar packages!

As time went by we made more a more projects with Laravel. In our Zend Framework days we used a custom-built application template, called Blender, to kickstart all our projects. It was a sort of mini-cms. Beside the traditional CMS-functions Blender could do a lot of cool things: pull in data from Analytics to show graphs about the usage of the site, handle uploaded files, subscribe users to a MailChimp list, … I started creating a Laravel version of Blender from scratch. I soon realised that some of the things I was porting to Laravel could be useful for other developers as well and decided to export these functionalities to external packages. In quick succession packages like laravel-newsletter, laravel-medialibrary and laravel-analytics were made.

I started to enjoy package development more and more. The positive feedback that I got early on from package users was very encouraging. I always considered coding purely as work, but because it was so much fun creating code that others could use as well I started coding in my free time as well. Besides working on packages I also polished the aformentioned application template called Blender and open sourced that too.

Since Spatie started I always was the only back-end developer. But that changed somewhere mid 2015 when Seb joined our team. He also likes working on our open source stuff. Because I blog and tweet a lot I’m the public face of our packages, but Seb does quite a lot too. He loves working on the more lower level stuff (the regex package is one of his). I myself enjoy working on the bigger infrastructure kind of packages like backup and medialibrary.

Currently every new package that we create gets born inside a client project. In almost every project we find some functionality that can be extracted to it’s own package.

Making time to work on open source

People often ask me if it isn’t very time-consuming to create packages. The truth is that it indeed takes a lot of time. Creating the code for the package itself, writing tests, writing documentation and getting the word out all takes a fair amount of time. And that’s just the start. When a first stable release gets tagged the work is not over. Maintaining a package, responding to issues, reviewing PR’s takes a lot of time (and dedication) too. At the time of this writing we’ve responded to almost 1 000 issues and reviewed more than 750 PR’s.

We do long-term planning at Spatie, but we also have a weekly short-term planning meeting. When scheduling out to the coming week we only plan four days. So we have one work day we can be a bit flexible with. Do not imagine that day as like a fixed day, that time is mostly spread out in that week. Sometimes we do client work in that time, because an estimation was wrong, or we need to do some support things. But that time is also used to review/solve issues and review/merge pull requests.

Like I’ve already mentioned I do enjoy working on packages in my free time as well. So a few times a week I spend some time in the evening to continue improving the released ones and creating new stuff.

The benefits of creating packages

There are many benefits of creating packages that makes time working on open source code well spent. You’ll learn a lot by working on packages. Each package needs to be carefully crafted. Laravel itself greatly emphasises developer happiness. It provides a clear and understandable syntax. I want that all our packages are easy to use too. Thinking about how other people will use your code will make you a better developer. We also learn a lot from the issues reported and the PR’s submitted by the users of our packages.

A second benefit is, that sometimes, as a package gains some traction, you get quality code for free. Our laravel-fractal package is a developer friendly wrapper around The League’s Fractal package. I coded up the basic functionality to I needed myself and tagged that 1.0.0. In the next weeks I almost daily got a pull request adding another great feature to the package. And now it supports almost everything League’s Fractal can do. I think 90% of the code of that package was written by the community.

Another benefit is a commercial one. When looking at our code I hope you’ll conclude that we do know our way around PHP and Laravel. Recently we’ve landed some projects because of our open source work. In most cases users of our packages were telling their bosses to hire us for a Laravel specific project.

And last but not least we’re also dogfooding ourselves. Our own packages get used on most projects. If we discover a bug in a package used in a project we can very quickly fix that and distribute that fix through the power of Composer to our other projects. The only package that didn’t get used in any of our own projects is laravel-permission. That one was coded up just for fun.

Why we require the latest version of PHP

Before PHP 7 got released at the end of last year, we picked the oldest, still supported PHP version as a minimum requirement for a newly created package. When PHP 7 got released we changed our policy on that. Every new package now requires PHP 7.

The most asked question in the issuetrackers of our packages is “Why can’t you support PHP 5.6“. I’d like to give some background on our stance.

We create these packages primarily for our own future projects. The fact that they become popular is just a nice side effect. At our company PHP 5 is dead. So it makes zero sense to make our packages PHP 5 compatible. The latest new features such as the scalar type hints, return types, anonymous classes and the null coalescing operator can help create elegant code.

I’m well aware that requiring PHP 7 will hurt the popularity of our packages in the short run. But, like already popularity is not our main goal. People who are using the latest and greatest version of PHP can benefit from our work. And I hope others will be nudged a bit towards PHP 7 by our decision. When PHP 7.1 gets released we’ll probably set that as our minimum required version. Can’t wait to use that fancy iterable typehint.

Top 10 of most popular packages

When taking amount of downloads into consideration these are our 10 most popular packages:

  1. laravel-backup
  2. pdf-to-image
  3. laravel-glide
  4. string
  5. laravel-analytics
  6. db-dumper
  7. laravel-medialibrary
  8. laravel-tail
  9. laravel-fractal
  10. laravel-permission

Like already mentioned in the intro some of these packages, like string and db-dumper, probably get a big download boost because there are required by other packages.

Not so popular packages

There are some packages, that we ourselves use in every single project, that I expected to be more popular. I hope by mentioning them here they’ll get a little attention. If you decide to give the ones mentioned below a shot, I hope that you’ll enjoy using them as much as we do.

The first one in this category is laravel-menu. That one can generate html menus. It provides you with a beautiful, Laravel worthy, API to work with. It can even detect which one of the menu items should be considered active. Maybe I haven’t search well enough for it, and I’m certainly biased, but I think there’s no alternative that provides such an easy to work with API.

Secondly, there’s laravel-translatable. This one can make your Eloquent models hold translations. Unlike Dimitris Savvopoulos’ excellent translatable package, ours does not need separate translation tables to store translations. Our package stores the translations as json in a column of the table. It’s very easy to work with, there are no extra queries needed to fetch translations. We got the idea to store translations as json in a column from Mohamed Said (who now enjoys fame as Laravel employee #1 😎).

And lastly I like to mention laravel-medialibrary. You saw this package at number 7 in the top 10 above, but I think this one deserves to be a few places higher. The package can associate all kind of media files (images, PDFs, …) with Eloquent models. It can generate thumbnails, and can store files on external filesystem and generate URLs to the files. It’s very easy to work with and it has excellent documentation. I think a lot of applications need to handle uploaded images and files. This package can save you countless hours by managing all of that for you.

The future

The past two years we’ve been regularly released packages. The most common problems in our projects are already solved with one of our packages. That’s why our package output will probably diminish a bit in the foreseeable future.

Of course we’re dedicated to maintaining our code. We’ve recently created new major releases of laravel-backup, laravel-newsletter, laravel-analtyics and a few others.

There’s no fixed roadmap for new packages. It really depends on the client projects we’re handling. If there is something there that can be solved in a generic way, we’ll create a package.

In closing

Creating and working on open source packages continues to be a truly fun experience. On a technical level I’ve learned lots of things that I wouldn’t have learned when working solely on client projects.

The positive feedback for our users also gave me enough confidence to start this blog and start speak publicly. The past year I’ve spoken at several local users groups (and I’m co-organizing the one in my home town), I got to speak at Laracon EU, and have two talks at [php]world to look forward to. At all those occasions I got to meet a lot of awesome fellow developers.

That all probably wouldn’t have happened if I stayed in my little bubble. So in short, working on open source helped getting to connect to the community. That sounds a bit corny, but that doesn’t make it less true.

If you haven’t used our packages before, take a look at the list on our company website. Probably we’ve made some things that could be useful to you. If you already are using any of our stuff, and you like it, send us a postcard.

Creating a mail driver in Laravel

Over at Sitepoint, Younes Rafie wrote a tutorial on how to create a custom mail driver in Laravel 5.3. In the post he shows some code that can log all email to the database.

One of the many goodies Laravel offers is mailing. You can easily configure and send emails through multiple popular services.

Laravel also provides a good starting point for sending mails during the development phase using the log driver, and in production using smtp, sparkpost, mailgun, etc. This seems fine in most cases, but it can’t cover all the available services! In this tutorial, we’re going to learn how to extend the existing mail driver system to add our own.


The MIT License, Line by Line

Kyle E. Mitchell goes over the MIT License, line by line.

If you’re involved in open-source software and haven’t taken the time to read the license from top to bottom—it’s only 171 words—you need to do so now. Especially if licenses aren’t your day-to-day. Make a mental note of anything that seems off or unclear, and keep trucking. I’ll repeat every word again, in chunks and in order, with context and commentary. But it’s important to have the whole in mind.


Computer Vision Syndrome

Eric L. Barnes explains what Computer Vision Syndrome is, and what you can do to avoid it.

In no point in human history have people been staring at bright screens just a few feet from their face like they are today. Computer vision syndrome or CVS (not to be confused with Concurrent Versions System) is one side effect to this, and it’s affecting millions of people.

The National Institute of Occupational Safety and Health reports computer vision syndrome affects about 90% of the people who spend three hours or more a day at a computer, which means almost everyone in our industry is susceptible.


A little library to deal with color conversions

My colleague Seb needed to convert some color values in PHP. He looked around for some good packages, but there weren’t any that fit the bill. So guess what he did? He just created a new package called spatie/color.

Here’s what it can do:

$rgb = Rgb::fromString('rgb(55,155,255)');

echo $rgb->red(); // 55
echo $rgb->green(); // 155
echo $rgb->blue(); // 255

echo $rgb; // rgb(55,155,255)

$rgba = $rgb->toRgba(); // `Spatie\Color\Rgba`
$rgba->alpha(); // 1
echo $rgba; // rgba(55,155,255,1)

$hex = $rgb->toHex(); // `Spatie\Color\Hex`
echo $hex; // #379bff

Currently the package only supports rgb, rgba and hex formats. If you need another format, submit a PR.

Using class_alias to maintain BC while moving/renaming classes

I’ve been using PHP for quite some time now, and I had never heard of class_alias before reading this post by Fabian Schmengler.

Sometimes you want to rename a class or move it to a different namespace. But as soon as it is used anywhere outside the package, this is breaking backwards compatibility and should not be done lightheartedly.

Luckily there is a way in PHP to have both, the old class and the new class, while deprecating the old one: class_alias().


Preventing API drift with contract tests

In an older post on his blog Adam Wathan shared an interesting approach on how to prevent API drift between a test mock and an actual implementation.

One of the risks of writing your own test doubles is that the API of the double can fall out of sync with the API of the real implementation.

In this screencast I walk through an example that explains:
– How interfaces can provide a false sense of security
– Why tests make better contracts than interfaces
– How to run multiple implementations against a shared set of contract tests

If you’ve ever had issues with API drift, try this approach and let me know how it works for you.


How (not) to use accessors in Eloquent

Jarek Tkaczyk wrote a blogpost on the usage of accessors in Eloquent. He demonstrates what could go wrong when using accessors on certain fields.

The moral of the story is, that data handling and its presentation should not go into the same bucket. And the model is that bucket – instead of creating accessors, traits or god knows what for this task, better use decorator (like) pattern where you can do all the necessary work for preparing your data to be displayed in your view, without touching actual values anywhere else.


Keep this in mind when you should use my pragmatic approach for presenters. Watch out for conflicting names.

Simplifying presenters in Laravel

In the Laravel template that we use to kickstart all our client projects at Spatie, I recently changed the way we handle presenters. Instead of using Jeffrey Way’s popular presenter package we now use simple traits. In this post I want to give some background on that change.

In case you’ve never heard what a presenter is, let me give you a crash course. Imagine you have a User model with a first_name and last_name attribute and that you need to show the full name of the user in your UI. Sure you could just code this in a Blade view.

{{ $user->first_name}} {{ $user->last_name }}

But that becomes tedious very quickly when you need to do this in several views. You could solve this by adding a fullName function to your User-model:

namespace App\Models;

class User

   public function fullName(): string
       return $this->first_name . ' ' . $this->last_name;

Sure, that’ll work, but when I open up a model file I do not want to see methods on how things should be presented in the UI. For one small function it’s probably fine, but in a real life projects there will be many of such presentation methods. Putting them all in your model file itself will make it bloated.

A common solution is to place such methods in their own dedicated class: a presenter class. In the past we’ve used the popular presenter package by Jeffrey Way for our presenting needs. It’s a very nice package, but there are some things that were bothering me. Using the package this is the way to call a method on a presenter in a Blade view:

{{ $user->present()->fullName }}

That present() part is kinda ugly. It would be much nicer if we could just call {{ $user->fullName }} in our view. But we don’t want to bloat our model by adding a fullName function to it. This can be solved pragmatically by using traits. In most cases traits are used to dry up code duplication across classes. But in my mind it’s perfectly fine to use traits to break down a big class in smaller bits. So in our case we could just make a separate presenter trait for each model that needs a presenter.

Using example above the UserPresenter could look like this:

namespace App\Models\Presenters;

trait UserPresenter
   public function getFullNameAttribute(): string
       return $this->first_name . ' ' . $this->last_name;
namespace App\Models;
use App\Models\Presenters\UserPresenter;

class User
   use UserPresenter;



Notice that we used an Eloquent accessor. In this way we can use {{ $user->fullName }} in a view. The model didn’t become bloated with presentable methods. And the presenters-package can be ditched. Triple win! Let me know in the comments below what you think of this approach.

Taking care of backups with Laravel

A new major version of laravel-backup was recently tagged. This package can backup files and databases of your Laravel app (or any PHP application really). The backup consists of a zipfile containing a dump of the databases and all files that are selected for backup. The package will copy over the zipfile to external storage such as S3, Dropbox, SFTP, … If something goes wrong during the package can notify you via, amongst others, mail or Slack. In this post I’d like to give some background on why and how it was built.

Keep in mind that there is no one size fits all solution for backups. A small company will probably handle backups in another way than a bigger company. This post has small companies in mind with a couple of developers and no dedicated operations person or team.

Using modern hosting

Up until a few years ago the company where I work made small sites and applications. We used shared hosting for all our projects. When our client or we ourselves accidentally deleted files or some values in db, we asked our hosting provider make the necessary restores. We didn’t do anything regarding backups ourselves.

But as time went by we started to make bigger applications. Shared hosting wasn’t cutting it for us anymore. We experimented with some of the newer cloud hosting providers and we liked the freedom that goes with using such solutions. Resources like serversforhackers.com and tools like Forge make it real easy to setup and administer your own servers. We settled on DigitalOcean. When I look around me I see many developers that are make the switch to DO, Linode, Rackspace, Amazon, etc… too.

The problem with modern hosting

But using such a provider can also bring a lot of sadness. At one fine morning I got a mail from DigitalOcean saying that they had lost our entire server. This kind of thing doesn’t happen at DigitalOcean alone. Here’s another horror story about a crashed server at Rackspace. If you google around a bit, you’ll find similar stories for all major cloud hosting providers.

Some of those providers provide a backup service. You might think that enabling such a backup service will save you from the problems described above. But unfortunately that’s not the case. In the beginning of this year Taylor Otwell, the creator of Laravel, found that out the hard way.

The hosting provider he was hosting his sites on was experiencing a denial of service attack. The whole datacenter was down for several days.

Taylor had enabled the backups, but soon learned that if the entire datacenter is down, those backups can’t be restored, because they can only be used in the datacenter where they were taken. Since that datacenter was down, the backups could not be restored.

If you’re on DigitalOcean you should be aware that their backup service only backs up your server once a week. So if your server crashes on a Friday, and your last backup was performed on a Monday, you’ve just lost data for an entire week. Your clients won’t be happy.


I should stress that I’m not trying to bash on DigitalOcean or any other specific provider. The point I want to make is that, in most cases, it’s not enough to rely on the backups of your hosting provider alone. You shouldn’t but your eggs in one basket. In addition to the backups performed by the hosting provider it’s a good idea to take care of backups yourself as well.

There are many options available, both free and paid. You could take matters in your own hands by running your own custom backup script. Here’s a great one by Chris Fidao. This script will dump the database and will, together with the files that need to be backed up, be copied over to S3. The only downside that it will not notify you when something goes wrong with the backup. If you need notifications you will need to code that up yourself.

Another option you have is to subscribe to Ottomatik.io, a paid service. I haven’t used this myself but a lot of people seem to be happy with it. Take a look at their site to learn more about it.

There are also free, open source, alternatives, such as BackupPC, Bacula and many others. They all work pretty good and have some great features, but the downside is that you need some system administration knowledge to set them up.

Introducing laravel-backup

My goal in creating laravel-backup was making a powerful backup solution that could be easily used by any developer that has some experience with Laravel. It can be installed into any Laravel app. These are the main functions it provides:

Backing up files and databases

Once installed the package can dump the databases used by the application and, together with the files selected in the config file, create a zipfile. The package will copy over the zipfile to one or more backup destinations. These backup destinations can be local, S3, Dropbox, … Under the hood Laravel’s cloud filesystem is used.

When the package is installed, artisan will have gained some backup commands. A backup can be performed by running this command:

php artisan backup:run

Of course, this command can be scheduled in the console kernel of your application.

Cleaning up old backups

When using the package for a couple of weeks or months you will have hopefully taken many backups . Probably some of the older backups are not as important as the newer backups. When using S3 to store your backups you’re going to pay for every byte you use. So it’s probably a good idea to get rid of any excess backup that you don’t need.

Out of the box the package contains a sane strategy of cleaning up the backups that you don’t need anymore. When running php artisan backup:clean the package will use the grandfather-father-son rotation scheme to remove backups. In short this means that all backups for a certain period are kept. After that, only one backup a day will be kept. After that only one backup a week will be kept. After that, only one a month. And, not surprisingly, after that only one backup a year will be kept.

Sending out notifications

The package can send out notifications when there was a problem taking a backup. Out of the box it can notify you via mail or Slack. The notifications are powered by Laravel 5.3’s native notification capabilities. This means that, if you want to be notified using a another channel, you can easily use one of the community created notification drivers or create a notification driver yourself.

Monitoring the backups

Once you’ve setup and scheduled the backups you’re probably never going to take another look at them again. You’re going to assume that backup process will run frequently. But what if something unexpected goes silently wrong?

The package comes with monitoring capabilities built in. Running php artisan backup:monitor will check if a backup was made in the last day and that the total storage used for the backups is not to high. Both criteria can be configured in the config file.

You can monitor the backups from inside your app but I recommend setting up a separate server from which you do the monitoring. This will ensure that the monitoring will still work even if your app is completely down.

Stuck on PHP 5 or and older version of Laravel?

The new version of laravel-backup, v4, requires PHP 7 and Laravel 5.3 or higher. If you’re stuck on PHP 5 or on Laravel 5.1 or 5.2 you can use v3 of the package. That version can do everything described above. Instead of relying on Laravel 5.3’s notifications v3 of the package uses a custom notification system that has support for mail, Slack, Pushover and Telegram.

There’s also extensive documentation on v3 available. Though we won’t introduce new features to v3 anymore we will still fix bugs.


I recommend using this package only in small- to medium-sized apps. There should be enough free space on your local disk in order for the zip to be created.

You should also be aware that, by using this package, your application holds the credentials to access your backups. In the case that your app is hacked, the hacker will gain access to your backups as well.

In closing

If you’re interested in using this package, head over to our documentation site to learn in detail how to set it up and use it. If you like it be sure to take a look at the list of Laravel packages we’ve previously made.

A retrospective on creating Laravel Shift

Laravel Shift is a paid service that can upgrade a Laravel project. I’ve used it a couple of times. Although some manually work is needed to complete the upgrade, it has saved me many hours. The service has recently shifted it’s 1000th project, a major milestone. In a post on his blog Jason shares how he started the service and where it’s going in the future.

In this post, I want to focus more on reaching the milestone of 1,000 Laravel applications upgraded. This may not sound like many, however for my first SaaS product it marks the achievement of my stretch goal. So allow me to share the most important decision, biggest challenge, and what the future holds for Laravel Shift.


How to design words

John Saito, a designer at Dropbox, wrote down some very useful tips to improve the text in your UI.

Technically speaking, I’m a writer. I get paid to write words. But here’s something most people don’t know about me: I hate to read.

You see, I mostly write interface text for apps and websites. It’s a style of writing where brevity beats brilliance, and every character counts. Writing interface text is actually a lot like design—designing words for people who hate to read.

https:[email protected]/how-to-design-words-63d6965051e9

Is your JavaScript function actually pure

What does “pure function” mean in the context of JavaScript? In programming in general, purity is also known as “referential transparency”, a fancy way of saying “replacing an expression or function call with its result will never change the behavior of the program” or a way of saying “every time you pass the same inputs, you always get the same outputs”.

That sounds intuitive, and a function like x => x * 10 looks pure because every single time you pass it the number 3 as argument you will get 30 as output. So how can we tell that one function is pure and the other isn’t? Is it enough that we just read the code?

Spoiler: reading the code isn’t enough.


Advancing in the Bash Shell

If you want to learn some neat bash tricks, read this excellent read by Sam Rowe.

If you’ve ever used GNU/Linux, chances are good that you’ve used bash. Some people hold the belief that using a GUI is faster than using a CLI. These people have obviously never seen someone who uses a shell proficiently. In this tutorial, I hope to show you just a few of the amazing features bash provides that will increase your productivity in the shell.


Building a search engine friendly sitemap XML with Laravel

Eric Barnes of Laravel News wrote a good tutorial on how to create a sitemap with Laravel.

A few years ago search engines recommended submitted sitemaps to help with indexing your website and now the importance of this is debatable.

I’m of the mindset creating and submitting can’t hurt, so I spent a little time putting one together and wanted to share how easy this is in Laravel.


Solidify Fragile Tests

Joe Ferguson shares a tip on how to make a version of PHPUnit’s assertArraySubset where the order of the array does not matter.

The problem with this test is that `assertArraySubset()` will fail if the items in the array are out of order. And since we don’t have an `ORDER BY` on our query in our data source we cannot guarantee the order of the returned data.


Changes to the type system in PHP 7.1

PHP 7.1 is nearing completion. A few days ago Release Candidate 1 was released. One of the areas that got some love from the developers is the type system. Pascal Martin wrote a blogpost about those changes.

One of the most important changes PHP 7.0 brought us last year was about typing, with the introduction of scalar type-declarations for functions/methods parameters and their return value.
PHP 7.1 adds to those type-declarations, with several points that were missing in the previous version of the language.


That new iterable pseudo-type will sure come in handy.

If you want to know what’s changed regarding error handling, Pascal has got that covered as well.