Using Eloquent in WordPress Plugin Development

WordPress is great but I really hate it when I have to write SQL queries. Most of the developers I have seen don’t really like writing SQL Queries. WordPress Comes with $wpdb class but you still have to write sql queries. $wpdb is fine when you have small number of queries to make but If you have ever encountered a situation where you have work with lots of custom database tables and have to join them with different tables, you know the pain.

I came across similar situation and instead writing ugly sql queries , I came up with a solution using Eloquent. Eloquent is ORM developed by Laravel framework. This is very easy to work with and you can still write sql queries with Eloquent if you want to. I am not going to talk about features of Eloquent in this article. You can look into official eloquent documentation for more information about Eloquent.


Lets start setting up our plugin.

I assume you have a working WordPress installation and You have composer installed in your machine. If you are not sure what composer is, Composer is dependency manager for php. You can visit composer’s official page for more information and download.

Lets navigate to WordPress ¬†plugins directory and create a folder for our plugin, I am going to name my plugin “wpdrift-client”.

I have composer installed globally in my machine, if your composer is not global, you might want to copy composer.phar file into your plugin directory and use “composer.phar” instead of ¬†“composer” when making composer commands. lets require illuminate\database package from composer. Open your terminal window and cd into the plugin folder (i.e. wordpress-installation/wp-content/plugins/wpdrift-client) and type following command:

composer require illuminate/database

Now your plugin folder should look something like this:

Composer has generated vendor directory which includes are package, composer.json file and composer.lock file. Lets open composer.json and setup our namespace. Lets edit it to look something like following code:

    "require": {
        "illuminate/database": "^5.4"
    "autoload": {
        "psr-4": {
            "Models\\": "app/models",
            "Controllers\\": "app/controllers"

Run a composer command from your terminal

composer dump-autoload

We have setup namespace for our models and controllers now lets create these folders. We will be creating a folder named “app” and inside that we will create two folders “models” and “controllers” which will store our Models and Controllers respectively. You can name your namespace anything you like.

We have installed Eloquent successfully, lets go ahead and create other files for plugin. We will create a main plugin file “wpdrift-clients.php”, a blank “index.php” file, “assets” folder which will store our css, js, images and fonts, we will also create a folder named views which will store views for our plugin. We will also create a folder called “core” which will be responsible for storing other files like plugin activation hook, connecting eloquent to database and helpers.

After creating these files and folders, your plugin directory should look something like this:

Let me explain what I did here:

We are creating a database table named “clients” (with prefix), core/create_db_tables.php includes code to create database, core/class-enqueue.php is responsible for styles and scripts required for plugin. helpers.php includes helper functions. Pretty much most of the things are included inside core/init.php

Here are the codes for these files:

Main plugin file : wpdrift-client.php

Plugin Name: WpDrift Clients
Plugin URI:
Description: Custom plugin using Eloquent
Version:     1.0
Author:      WPDrift
Author URI:
License:     GPL2
License URI:
Text Domain: wpdrift-clients
Domain Path: /languages

if(! defined('ABSPATH')) exit;

if( ! defined('WPDRIFT_CLIENTS_URl')){

if( ! defined('WPDRIFT_CLIENTS_PATH')){

require WPDRIFT_CLIENTS_PATH.'/core/create_db_tables.php';

if(! class_exists('Wpdrift_Clients')){
        class Wpdrift_Clients {
            function __construct(){ 
            function include_dependencies() {
                include WPDRIFT_CLIENTS_PATH.'/core/init.php';

new Wpdrift_Clients();


require WPDRIFT_CLIENTS_PATH.'/vendor/autoload.php';

/*database connection*/
$capsule = new Illuminate\Database\Capsule\Manager;
        'driver'    => 'mysql',
        'host'      => DB_HOST,
        'database'  => DB_NAME,
        'username'  => DB_USER,
        'password'  => DB_PASSWORD,
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',

// enqueue styles and scripts with class-enqueue.php
// helper functions helper.php

include_once WPDRIFT_CLIENTS_PATH.'/core/helpers.php';
include_once WPDRIFT_CLIENTS_PATH.'/core/class-enqueue.php';

// add ajax actions
$actions = new Controllers\ActionController();

// shortcode
        wpdrift_clients_load_view('clients',['title'=>'Clients list']);


if(! class_exists('Wpdrift_Clients_Enqueue')){
        class Wpdrift_Clients_Enqueue {
                function __construct(){
                function enqueue() {
        new Wpdrift_Clients_Enqueue();


function wpdrift_clients_load_view($file,$data=[]){
    if(! empty($data)){
        include_once WPDRIFT_CLIENTS_PATH.'views/'.$file.'.php';
        echo 'File not found in '.WPDRIFT_CLIENTS_PATH.'views/'.$file.'.php';

function get_clients(){
    $clients = Models\Client::all();
    return $clients;

Basically, we are just displaying a view with shortcode. Shortcode will trigger a function wpdrift_clients_load_view() (Location: core/helpers.php) , this function will extract array argument and include a view from views folder.

View file includes a table which is displaying dynamic data with a function get_clients() (Location: core/helpers.php), this function gets data from Client Model.

each dynamic data has a delete button which is a form with a ajax action, (Action defined on core/init.php), call back for these actions are stored in app/controllers/ActionController.php, this controller is using app/models/Clinet.php to interact with clients table.


namespace Controllers;
use Models\Client as Client;

class ActionController {
        function create(){
           $name = $_POST['name'];
           $email = $_POST['email'];
           $phone = $_POST['phone'];
           $purchased_service = $_POST['service'];
           $client = new Client;
           $client->name = $name;
           $client->email = $email;
           $client->phone = $phone;
           $client->purchased_service = $purchased_service;
           $response = [
              'response_type' => 'success',
              'response_data' => [
                 'name' => $clinet->name,
                 'email' => $clinet->email,
                 'phone' => $clinet->phone,
                 'service' => $clinet->purchased_service,
           return $response;
         function delete(){
            $client_id = $_POST['client_id'];
            $client = Client::find($client_id);
               return 'success';
            return false;


namespace Models;
use Illuminate\Database\Eloquent\Model as Model;

class Client extends Model {
        protected $table;
        public $timestamps = false;
        function __construct() {
                $this->table = $this->get_table_name('clients');
        private function get_table_name($name) {
                global $wpdb;
                return $wpdb->prefix.$name;

As You can see, we don’t have much code on our model, all we are telling model is to use prefix_clients table, Eloquent by default expects table to have created_at and updated_at column. So, by defining public $timestamps = false; we are disabling that feature. Eloquent assumes you have a primary key table with the name id, if you are thinking of using some other name, you will have to define one more property called $primaryKey . For example, if you are creating a model for WordPress native Users table, it would look something like this:

namespace Models;
use Illuminate\Database\Eloquent\Model as Model;
class User extends Model {
        protected $table;
        public $timestamps = false;
        protected $primaryKey = 'ID';
        function __construct() {
                $this->table = 'wp_users';
                $this->table = $this->get_table_name('users');
        private function get_table_name($name) {
                global $wpdb;
                return $wpdb->prefix.$name;
        function meta() {
                return $this->hasMany('App\Usermeta');
        function posts() {
                return $this->hasMany('App\Post');

In the above example meta and posts method define relationship with other Models “Usermeta and Post”, which can use usermeta and posts table.

We built a very basic plugin using eloquent orm. But this article is not about how big the plugin is but structuring your plugin to use MVC architecture and using Eloquent orm with your plugin. This article only focused on using MVC and Eloquent, you will have to implement security when you build your real plugin.

Hence, if you are using creating a big custom plugin with lots of custom tables, I believe this approach will be very manageable and easy where as I would not suggest you to use this approach to publish your plugin in as it makes extra database connection and user is using 5 plugins with similar approach, they will have 6 database connections.

Download code


Want to receive weekly updates? Sign up to the newsletter and never miss new article.