The practice of PHP… And more!

Create model classes for Laravel e-commerce application

In our last post, we created Laravel migrations to generate our database tables. Now that we have these tables, we need to create corresponding model classes for each of the tables.

Before we get into creating the model classes, let’s look at what models are used for. Models are the ‘M’ in MVC, the model-view-controller design pattern. The fundamental role of the model is to manage how your application interacts with the database. In general, you will have one model for each table in the database. In addition to database interaction, the model will hold the business rules, including relationships between the various entities represented by the various models.

In our e-commerce application, we will be creating four models corresponding to each of the database tables: account (customer), order, order_item, and product. All of our model files will be in the app/model directory. Typically, the model file and class names follow the name of the corresponding table, except they usually don’t use underscores. Furthermore, while not strictly required, I suggest that you specify the corresponding table name explicitly in the $table attribute (variable) of the class.

To begin, we’ll use the Generators package again to help us create our model classes. (We used Generators to generate the framework for our database migrations classes previously.) As you recall, the account table looks like:

You can refer to the Eloquent documentation on the Laravel web site for more details, but let’s explain a few of the concepts here.

$table – This specifies the name of the database table that this model corresponds to. If the class name matches the table name, it is not strictly required to specify the table, but I find it best to be explicit about this.

$primaryKey – The default convention for Laravel is for each table to have a column named id which is the primary key (PK). I prefer to include the table name in the PK column, so we must specify this column explicitly in our class defintion.

$hidden – This is a list (array) of the columns in the table that are note returned from the JSON API. In our example, we would not want to expose the password!

$guarded – Laravel supports the concept of mass (bulk) assignment of attributes. However, we may want to prevent mass assignment of certain attributes for security reasons. The $guarded array is a list of such columns.

$fillable – These are the “opposite” of the $guarded columns in that these are explicitly allowed to be mass assigned.

This is the paradigm for how Laravel defines relationships between models and tables. In this case, we are indicating that a given account (user) can have multiple (hasMany) orders. You will notice that the reference is actually to the Ordermodel (and not strictly to the ordertable). Furthermore, we are explicitly noting that the foreign key column to account on order is the account_id column. Also, note that since we are using the hasMany relationship, we specified the method name using the plural form: orders. For an excellent discussion about the various relationships provided by Eloquent, see Visualizing Laravel Relationships.

In addition, when we get to the Order model, you will see that we have a reciprocal relationship defined back to the account using the (singular) belongsTo method.

Finally, we have the three get...() methods. The methods and especially their names may seem a bit awkward. However, you’ll notice that on the class declaration, we have included implements UserInterface, RemindableInterface (and referenced those interface libraries via use directives at the top of the class). An interface is kind of like a template for a class. Essentially, it tells Laravel (or really PHP itself!) that the class that implements the interface must include certain attributes (variables) and/or methods (functions). See the PHP documentation on interfaces for more information. The most common use for interfaces in Laravel is to handle inversion of control (IoC) design pattern, which is useful for application testing.

You will also notice that I created three additional “helper” methods with more “user-friendly” names, which simply call the methods required by the interfaces. This is just to allow us to use names that are more meaningful when calling the methods ourselves.

This takes care of the Account model. Here are the complete definitions for our other three model classes: Order, OrderItem, and Product. Note that the “headers” for these look a bit different, since none of them implement any interfaces.