Laravel with a legacy database

If you ever need to work with a database that doesn't quite follow convention, remember that Laravel has some pretty sweet built-in functionality to help you use that old data in new ways.

For example, let's say that you work for a company that's been around for a while and they've been rocking a vanilla PHP website for decades. The hardest part of migrating that beast to Laravel is probably going to be the millions of records in the database.. so, why migrate it at all? Instead, what if you could just hook your new Laravel installation up to the old database and get cranking on a shiny new redesign? Well you can, but with some caveats.

One of the biggest caveats, and the one I'm going to focus on here is that Laravel expects models to be set up in a certain way and if you haven't been using Laravel, your data probably isn't set up that way. For example, Laravel's stub migration includes an id primary column, but your model might have a pid instead. Even the table name might not match convention -- Laravel expects that a model called Post corresponds to a posts table, but maybe your table name is wp_posts.

Fortunately, Laravel gives you the option and ability to break out of the conventions when you need to. Notice I said "when you need to", I believe that most Laravel conventions do make sense and generally are good practices. I tend not to want to break away from those conventions unless I have a very good reason. To me, wrapping Laravel around a legacy database is a very good reason if it's not feasible to just migrate the data.

Let's say we're working on an e-commerce site with millions of orders in the legacy database. For the sake of this example, let's say that the database table we're working with is called customer_orders and the relevant columns look something like this:

pid => integer(11), primary key
created_timestamp => timestamp, created at timestamp
updated_timestamp => timestamp, updated at timestamp

In Laravel we want to create an Order model to make it easier to work with orders in our database. The only problem is that Laravel is going to be looking for an orders table to wire up to that model by convention. Laravel also isn't going to know that the pid is the primary key or that the created_timestamp and updated_timestamp columns should be filled.

Let's make a model and see how to solve these issues

php artisan make:model Order

That'll give you a model that looks something like this:

<?php

namespace App;

class Order extends Model
{
    
}

First, this model is pretty useless if Laravel doesn't know what database table it's tied to. Let's set that up by setting the protected $table property.

protected $table = 'customer_orders';

We can also fix the primary key by setting a corresponding property.

protected $primaryKey = 'pid';

Then we can tell Laravel which columns map to the conventional created_at and updated_at timestamp columns by setting constants.

public const CREATED_AT = 'created_timestamp';
public const UPDATED_AT = 'updated_timestamp';

All in all, our model should be looking something like this:

<?php

namespace App;

class Order extends Model
{
  	public const CREATED_AT = 'created_timestamp';
    public const UPDATED_AT = 'updated_timestamp';
    protected $table = 'customer_orders';
  	protected $primaryKey = 'pid';
}

Bonus: More Timestamp Options

If you don't save one of these timestamps, you can set it to null.

public const CREATED_AT = 'created_timestamp';
public const UPDATED_AT = null;

Or, if you don't use timestamps at all, you can set the property $timestamps to false.

public $timestamps = false;