Alternatives to using a constants.php file in your Laravel project

One of the common patterns I have come across in Laravel projects is the use of a constants.php file carrying a long list of all constants used across the application.

While there may be good use cases for having such a file, I'm writing this article to suggest a few alternative approaches. My intent is not to advertise these as "best practices", but leave it for you to decide what fits best your specific situation.

Let's assume that our original constants.php file looks like this:

const ADMIN_ROLE = 1;
const EDITOR_ROLE = 2;
const PUBLISHER_ROLE = 3;

Configuration files

As pointed out by the most upvoted answer in this popular thread, one way to manage constant values in your Laravel app is to park them as configurations.

My only variation to this approach is to use a more specific file name depending on the context, which in this case could be roles.php:

<?php

return [
  'admin' => 1,
  'editor' => 2,
  'publisher' => 3
];

This would allow me to access those values throughout my application using:

config('roles.admin'); // Using helper functions

Config::get('roles.admin'); // Using facades

The benefit of this approach compared to using a plain constants.php file is that it uses the framework's original mechanics to store and access values. Laravel configurations are familiar to most developers, and so people new to your code won't have to learn something new to use them.

The downside is that, unless you use a plugin such as Laravel Idea, most IDEs won't autocomplete config keys for you.

Constants in your classes

Another approach, which is more inline with OOP, is to keep your constants in the specific context (i.e. classes) they belong.

In the case of user role constants, for example, we could keep everything under the User model class:

class User extends Model {
  const ADMIN_ROLE = 1;
  const EDITOR_ROLE = 2;
  const PUBLISHER_ROLE = 3;

  public function isAdmin(){
    return $this->role === static::ADMIN_ROLE;
  }
}

To take this one step further, you may consider creating a dedicated Role class that contains all values/logic related to roles:

class Role {
  const ADMIN = 1;
  const EDITOR = 2;
  const PUBLISHER = 3;
}

This would enable a more expressive syntax when you're trying to access your constants:

class User extends Model {  
  public function isAdmin(){
    return $this->role === Role::ADMIN;
  }
}

Enum values

Another alternative to constants that are related to a specific model is to use enumerated (ENUM) types at your database level.

When using your migration for your users table, you may use the enum function to create your column:

public function up()
{
  Schema::create('users', function (Blueprint $table) 
  {
    $table->enum('role', ['admin', 'editor', 'publisher']);
    // Other columns...
  });
}

While ENUMs are compact values (e.g. in MySQL they are automatically encoded as numbers behind the scenes), they allow you to deal with readable string values in your application:

class User extends Model {
  public function isAdmin(){
    return $this->role === 'admin';
  }
}

If you are going for this approach, you should note that not every database engine supports ENUMs (e.g. MySQL and PostgreSQL both support ENUMs, but SQLite doesn't).

What do you think?

What are some other values you store in a constants.php file? Where else do you place your constants?

13