Laravel Modding: Generating Models with singular table names

Photo by jim quenzer on Unsplash

One of the most common habits I’ve seen developers have is sticking to the conventions they’ve learnt from their earlier days of being in school or college. A strong example of this is singular nouns (think ‘team’ over ‘teams’) for database tables. It’s something that’s taught frequently but in reality it doesn’t make any difference which you choose when making an application. It does however present a problem some times with Laravel. Artisan’s make model command (when making migrations) and the models themselves by default expect table names to be plural.

What is important though is that table names stay consist, if not just that it looks better to have things follow a set pattern, it will also mean developers don’t have to remember which tables are named with a singular and which are plural when building manual queries. Ultimately this is harder to maintain when you’ve started with singular table names (or maybe migrated your database from a legacy app) but you keep forgetting to make sure all your Models and migrations match up if like many you use the make model command to generate your new models etc.

How to combat Plural table names

It’s actually really easy to fix this problem with just a simple command that will replace the one that comes in the Laravel framework. We can do this by quickly generating a new command from the artisan console:

php artisan make:command ModelMakeCommand

This then gives us the file app/Console/Commands/ModelMakeCommand.php to edit. First we might as well clear out all the content as we won’t need a handle or constructor method. We also don’t need the signature and description properties by by the default command.

The next thing to do is to change the inheritance of our new ModelMakeCommand. Instead of extending Illuminate\Console\Command we instead need to extend Illuminate\Foundation\Console\ModelMakeCommand. For this I personally like to set and alias in the use statement so we’ll call it BaseCommand instead. Our new command should currently look like the following.

Now we’ve done this we can start to make sure our migration gets made with the singular table name instead of a plural. We’ll do this by overriding the createMigration method from the inherited command class. This is what the original method looks like:

protected function createMigration()
{
$table = Str::snake(Str::pluralStudly(class_basename($this->argument('name'))));

if ($this->option('pivot')) {
$table = Str::singular($table);
}

$this->call('make:migration', [
'name' => "create_{$table}_table",
'--create' => $table,
]);
}

As you can see it calls the Str class’ pluralStudly method to generate a plural of the given Model name. So what we’ll do if copy the exact same method to our own command but remove the use of the pluralStudly method and then we’ll end up with a command like this (don’t forget to import the Str class for the other parts of the method though):

Fixing the Model Generation

This solves the migration problem but now we have another one. Model classes still expect table names to be plural to query them which means our Models won’t work unless we manually add the table property and specify what the table is. Doing this manually sucks though because given a chance to forget something we ultimately will so instead we’re going to modify the template.

We’re firstly going to do this by overriding the getStub method of our command with one which will use our own template.

Similar to the parent class but instead it’ll point to the resources path where we’ll have a new stubs folder to keep our model templates. You can see the stub method added in the command below:

We then add the model stub to the stub folder, which will be resources/stubs/model.stub.

As you can see in the model.stub file it already has a table property set up which will have it’s value replaced by the model command when the Model is generated.

To do this we just need to modify one more method and add another one to keep everything clean.

What we need to do now is add a makeClass method to our ModelMakeCommand. This is going to override what the original ModelMakeCommand does because we need an extra step in our method to be able to do the replacement of the DummyTable text to then produce the final text of the class.

How we perform the replacement is by adding a replaceTable method that’s going to modify our stub text and then return the command so it can perform further replacements. This will be the last step that allows us to make new Model classes and migrations with singular table names.

The final class will look like this:

Now we can use the command as we normally would:

php artisan make:model Team -m

And we can now expect a migration and model ready to work with our database as we need it.

Our new Team Model.
Our new Team table migration file.

Hopefully in following this article you now understand how you can always extend and alter the commands provided by Laravel to have something more customised to your own application’s needs.

If you want to look at the code as a whole you can take a look on GitHub.


I’m Peter Fox, a software developer in the UK who works with Laravel among other things. If you want to know more about me you can at https://www.peterfox.me and feel free to follow me @SlyFireFox on twitter for more Laravel tips and tutorials.