Our thoughts on the business of software & 10 years of bootstrapping

Delivered weekly. Unsubscribe at anytime.

Organizing Snappy

by
Taylor Otwell on
Nov/04/2013

Snappy is built on top of the Laravel PHP framework. One of the most common questions we receive from other Laravel users is how to organize a large code base like Snappy. In this post I'll share a few of the things we do to keep our Laravel code base manageable.

Many modern web frameworks ship with a folder equivalent to models, including Laravel and Rails. However, if you put all of your code within this directory, the folder will get crowded quickly. One key to organizing your project will be simply creating more folders, which correspond to namespaces within your Laravel application. When starting to work on Snappy, we simply renamed our "models" directory to "Snappy". Model is a vague and generic word for most programmers, and we find it helpful to just discard it entirely.

Next, we create sub-folders within our "Snappy" directory that correspond to various "areas of responsibility". So, for example, Snappy has a group of classes that handle sending and receiving e-mail. We call this our e-mail "pipeline", and we have a "Pipeline" folder / namespace that holds these classes. Likewise, we have a group of classes that deal with persisting data to our database. We call these classes "repositories" and place them within a "Repositories" folder / namespace.

By breaking our classes up by responsibility, an individual class stays manageable. Rather than digging through files with thousands of lines of code, it's much easier to explore a class that is a few dozen to a few hundred lines. And, by standardizing all of our data access into repositories, controllers are able to share common data access logic.

We also like to create helpful base classes like our TenantRepository. This class provides a convenient method to constrain all of our queries by a given Snappy account ID. A simple make method creates a new Eloquent ORM query and sets the account ID constraint:

We then have a few generic methods, like one that allows us to quickly pull a record by a key / value pair. This helper utilizes the make method which sets the account ID:

Creating these types of "helper" methods will save you tons of time, and keep you from repeating the same logic over and over again.