Skip to Content
🎉 WpMVC 2.0 is released! Now compatible with PHP 7.4 to 8.5. Read the guide →
DocumentationDatabase & EloquentSchema Builder

Schema Builder

Introduction

WpMVC’s Schema class provides a database-agnostic way of manipulating tables, making it an ideal tool for WordPress developers who need to create custom database tables for their plugins. It works gracefully with WordPress’s database structure and provides an expressive API for creating and modifying tables without writing raw SQL.

Internally, WpMVC uses WordPress’s dbDelta function to ensure that your table schema is correctly synchronized during plugin installation or updates.


Creating Tables

To create a new database table, use the create method on the Schema class. The create method accepts two arguments: the first is the name of the table, while the second is a closure which receives a Blueprint object that may be used to define the new table.

Best Practice: The Setup Class

In a WpMVC plugin, table creation is typically handled within a Setup class. This class is responsible for executing schema changes during plugin activation or updates:

<?php namespace MyPluginNamespace\Database; defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; class Setup { public function execute() { Schema::create( 'customers', function( Blueprint $table ) { $table->big_increments( 'id' ); $table->string( 'name' ); $table->string( 'email' )->unique(); $table->timestamps(); } ); } }

When creating the table, you may use any of the schema builder’s column methods to define the table’s columns.

Checking For Table Existence

You may easily check for the existence of a table or column using the has_table and has_column methods:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; if ( Schema::has_table( 'customers' ) ) { // The "customers" table exists... } if ( Schema::has_column( 'customers', 'email' ) ) { // The "customers" table exists and has an "email" column... }

Updating Tables

The alter method on the Schema class may be used to update existing tables. Like the create method, the alter method accepts the name of the table and a closure that receives a Blueprint instance:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; Schema::alter( 'customers', function( Blueprint $table ) { $table->string( 'phone' )->nullable(); } );

SQL Preview

Most Schema methods (create, alter, rename, drop, drop_if_exists) accept an optional boolean as the final argument. If set to true, the method will return the generated SQL string instead of executing it:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; $sql = Schema::create( 'customers', function( Blueprint $table ) { $table->big_increments( 'id' ); }, true );

Renaming & Dropping Tables

To rename an existing database table, use the rename method:

Schema::rename( $from, $to );

To drop an existing table, you may use the drop or drop_if_exists methods:

Schema::drop( 'customers' ); Schema::drop_if_exists( 'customers' );

Indexes & Constraints

The schema builder supports several types of indexes. The following example creates a new email column and specifies that its values should be unique:

$table->string( 'email' )->unique();

Alternatively, you may create the index after defining the column:

$table->string( 'email' ); $table->unique( 'email' );

You may even pass an array of columns to an index method to create a compound index:

$table->index( [ 'account_id', 'created_at' ] );

Primary Keys

You may also define a primary key for the table:

$table->primary( 'id' ); // Or for composite keys: $table->primary( [ 'account_id', 'id' ] );

Foreign Key Constraints

WpMVC also provides support for creating foreign key constraints, which are used to force referential integrity at the database level. For example, let’s define a customer_id column on the products table that references the id column on a customers table:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; Schema::create( 'products', function( Blueprint $table ) { $table->big_increments( 'id' ); $table->unsigned_big_integer( 'customer_id' ); $table->foreign( 'customer_id' ) ->references( 'id' ) ->on( 'customers' ) ->on_delete( 'cascade' ); } );

Foreign keys are automatically checked to avoid duplicates. The naming convention used is fk_{prefix}{table}_{column}.

Dropping Indexes

To drop an index, you must specify the index’s name. By default, WpMVC assigns a reasonable name to the indexes. You can simply pass the index name to the drop_index method:

$table->drop_index( 'geo_state_index' );

Available Column Types

The schema builder blueprint offers a variety of methods that correspond to the different types of columns you can add to your database tables.

Big Integer

big_increments()

The big_increments method creates an auto-incrementing BIGINT UNSIGNED (primary key) equivalent column:

$table->big_increments( 'id' );

unsigned_big_integer()

The unsigned_big_integer method creates an UNSIGNED BIGINT equivalent column:

$table->unsigned_big_integer( 'customer_id' );

big_integer()

The big_integer method creates a BIGINT equivalent column:

$table->big_integer( 'votes' );

Strings & Text

string()

The string method creates a VARCHAR equivalent column of a given length:

$table->string( 'name', 100 );

text()

The text method creates a TEXT equivalent column:

$table->text( 'description' );

long_text()

The long_text method creates a LONGTEXT equivalent column:

$table->long_text( 'content' );

Numbers

integer()

The integer method creates an INT equivalent column:

$table->integer( 'votes' );

unsigned_integer()

The unsigned_integer method creates an UNSIGNED INT equivalent column:

$table->unsigned_integer( 'votes' );

tiny_integer()

The tiny_integer method creates a TINYINT equivalent column:

$table->tiny_integer( 'status' );

decimal()

The decimal method creates a DECIMAL equivalent column with the given precision (total digits) and scale (decimal digits):

$table->decimal( 'amount', 8, 2 );

float()

The float method creates a FLOAT equivalent column:

$table->float( 'price' );

boolean()

The boolean method creates a BOOLEAN equivalent column:

$table->boolean( 'confirmed' );

Date & Time

timestamps()

The timestamps method adds created_at and updated_at TIMESTAMP equivalent columns:

$table->timestamps();

timestamp()

The timestamp method creates a TIMESTAMP equivalent column:

$table->timestamp( 'added_on' );

date()

The date method creates a DATE equivalent column:

$table->date( 'birthday' );

datetime()

The datetime method creates a DATETIME equivalent column:

$table->datetime( 'published_at' );

Miscellaneous

enum()

The enum method creates an ENUM equivalent column with the given allowed values:

$table->enum( 'difficulty', [ 'easy', 'hard' ] );

json()

The json method creates a JSON equivalent column:

$table->json( 'options' );

In addition to the column types listed above, there are several column “modifiers” you may use while adding a column to a database table. For example, to make the column “nullable”, you may use the nullable method:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; Schema::alter( 'users', function( Blueprint $table ) { $table->string( 'email' )->nullable(); } );

nullable()

Allows the column to allow NULL values.

default()

Specify a “default” value for the column:

$table->string( 'status' )->default( 'draft' );

comment()

Add a comment to the column:

$table->string( 'role' )->comment( 'User role in the system' );

use_current()

Sets the default value for a timestamp column to the current timestamp:

$table->timestamp( 'created_at' )->use_current();

use_current_on_update()

Sets the column to automatically update to the current timestamp when the record is updated:

$table->timestamp( 'updated_at' )->use_current_on_update();

after()

When using MySQL, the after method may be used to specify the order of columns:

$table->string( 'address' )->after( 'email' );

Dropping Columns

To drop columns from an existing table, you may use the drop_column method on the Blueprint instance within a Schema::alter callback:

<?php defined( 'ABSPATH' ) || exit; use MyPluginNamespace\WpMVC\Database\Schema\Schema; use MyPluginNamespace\WpMVC\Database\Schema\Blueprint; Schema::alter( 'customers', function( Blueprint $table ) { $table->drop_column( 'phone' ); // You may also drop multiple columns $table->drop_column( 'address' ); $table->drop_column( 'social_security_number' ); } );
Last updated on