Getting Started with WordPress MVC

Share this article

In WordPress we often have to stick with plain PHP when creating plugins. This leads to PHP and HTML code getting mixed up in a single page, which isn’t a good practice. Separation of concerns is a design principle that states that we should split up a program into different parts, namely the logic and the presentation. In this tutorial, we will be taking a look at one solution to this problem: WordPress MVC. It’s a plugin that adds MVC support to WordPress so we can write our plugins the MVC way.

Key Takeaways

  • WordPress MVC is a plugin that introduces the Model-View-Controller (MVC) architecture to WordPress, enabling developers to separate logic and presentation in plugin development.
  • To use WordPress MVC, you must install and activate the WP MVC plugin, which then allows you to scaffold new plugins using specific MVC commands in the command line.
  • The tutorial demonstrates building a sample plugin called “AnimeList” which includes creating custom database tables, forms for adding and editing entries, and managing data presentation on both admin and public sides.
  • WordPress MVC enhances code organization and maintainability by structuring code into models (data handling), views (output presentation), and controllers (request handling), which is particularly useful for complex or large-scale WordPress projects.
  • The tutorial covers the entire workflow from setting up the MVC environment in WordPress, generating the necessary MVC components for a plugin, to adding custom styles and scripts, showcasing a practical implementation of MVC in WordPress plugin development.

What Is MVC?

Before we move on, it’s important that we are all on the same page. If you already know what MVC is, feel free to skip to the next section.

Ok so what is MVC? MVC stands for Model View Controller. The Model represents the data that our application utilizes. It’s the part that does the talking to the database. The View deals with the presentation. It’s where we put in HTML code and basic presentation logic. Lastly there’s the Controller whose main job is to tie those two together. Examples include validating and sanitizing user input. It’s basically responsible for controlling the overall flow of the application.

Installation and Setup

WP MVC is a plugin which we need to install in order to make MVC work with WordPress. You can download the plugin here and install it like you would usually install a plugin in WordPress. Once that’s done, login to WordPress and activate it from your plugins page.

Building a Plugin the MVC Way

Before we move on, I’ll give you a brief overview of what we will be building in this tutorial. We will build a plugin that will list out all the anime that is created in the admin side of the website. Pretty much like what this site does. In the admin side, we will have an interface where we can add, list, edit or delete anime shows. In the public side, we will have them presented in a grid view in a specific page.

Now we’re ready to build a new plugin. You can do that by navigating to the path where you installed the WP MVC plugin.

cd path/to/plugins/wp-mvc

Then add execution permissions to the wpmvc file. This is the file that we will be using to generate a new plugin.

chmod +x wpmvc

Next, we can now generate a new plugin. Execute the following command to do that.

./wpmvc generate plugin AnimeList

This will create a new plugin under the wp-content/plugins directory of your WordPress installation. For me, it created an anime-list directory. Open that directory and then open the anime_list_loader.php file. This file contains the functions that will get executed upon activating or deactivating the plugin. As we will need to save a lot of custom data, we will have to create a custom table instead of using the options API to store things in the database. To do that, we have to add the code that will create the new table upon plugin activation. Add the following code inside the activate method.

global $wpdb;

$sql = '
CREATE TABLE '. $wpdb->prefix . 'animelists (
  id int(11) NOT NULL auto_increment,
  title varchar(255) NOT NULL,
  poster varchar(255) NOT NULL,
  plot TEXT NOT NULL,
  genres TEXT default NULL,
  PRIMARY KEY  (id)
)';

dbDelta($sql);

In the code above, we are creating a table which has the id, title, poster, plot and genres field using a raw SQL query. The dbDelta function is then used to execute the SQL query.

Next, under the deactivate method, we have to clean up our mess. The code below removes the table from the WordPress database.

require_once ABSPATH.'wp-admin/includes/upgrade.php';

global $wpdb;

$sql = 'DROP TABLE ' . $wpdb->prefix . 'anime_lists';
$wpdb->query($sql);

Normally this isn’t the way you would like to do it. Some users might still need the data that your plugin has acquired over time. Even if they deactivate your plugin. But to keep things simple, we won’t handle that here.

Now is a good time to activate your new plugin from the WordPress admin page. If everything worked correctly, that should have created a wp_anime_lists table in your WordPress database.

Next, execute the following command:

./wpmvc generate scaffold AnimeList AnimeList

The command above generates the views, controllers and model for the model that you specify. The first AnimeList is the name of the plugin and the second one is the name of the model. Note that wpmvc uses a naming convention here. A model should always be in singular form and the table is plural form. And every capital letter in the name of the model means that it should be separated with underscores. The name of the model should be based on the name of the table. So using the rules above, if the name of the table is anime_lists, the model should be named AnimeList. Underscores are turned into CamelCasing and plural is converted to singular form.

Next, open up the add.php file and edit.php under the app/views/admin/anime_lists/ and add the following code:

<h2>Add Anime List</h2>

<?php echo $this->form->create($model->name); ?>
<?php echo $this->form->input('title'); ?>
<?php echo $this->form->input('poster'); ?>
<?php echo $this->form->input('plot'); ?>
<?php echo $this->form->input('genres'); ?>
<?php echo $this->form->input('producer'); ?>
<?php echo $this->form->end('Add'); ?>

On the edit.php file:

<h2>Edit Anime List</h2>

<?php echo $this->form->create($model->name); ?>
<?php echo $this->form->input('title'); ?>
<?php echo $this->form->input('poster'); ?>
<?php echo $this->form->input('plot'); ?>
<?php echo $this->form->input('genres'); ?>
<?php echo $this->form->input('producer'); ?>
<?php echo $this->form->end('Update'); ?>

What we did above was to create the forms for adding new anime shows and editing existing one’s. This utilizes the form helpers which is built-in to wpmvc. To break it down, first we create a new form and then supply the name of the model as its argument. In this case the name of the model is AnimeList.

<?php echo $this->form->create($model->name); ?>

Next, we output each of the columns that we have added in the table using the input method. This method takes up the name of the field as its first argument. By default, wpmvc determines what type of field it would output by checking the data type. So if the data type is varchar, it will output a text input. If the data type is text it will output a textarea and so on.

<?php echo $this->form->input('title'); ?>
<?php echo $this->form->input('poster'); ?>
<?php echo $this->form->input('plot'); ?>
<?php echo $this->form->input('genres'); ?>
<?php echo $this->form->input('producer'); ?>

If you want to use another input type, you can specify an array containing the type of input as a second argument:

<?php echo $this->form->input('is_awesome', array('type' => 'checkbox')); ?>

Finally, we close off the form using the end method. This takes up the label of the button as its argument.

<?php echo $this->form->end('Add'); ?>

At this point we can now add a few anime shows. WP MVC automatically handles adding a new menu on the WordPress dashboard named after the name of the model. In this case the name of the new menu should be ‘Anime Lists’. From there you can start adding new items using the ‘add new’ sub-menu.

Next we need to update the code which lists the existing items. You can find it on the following path:

app/controllers/admin/admin_anime_lists_controller.php

By default, it contains the following code:

<?php

class AdminAnimeListsController extends MvcAdminController {

    var $default_columns = array('id', 'name');

}

?>

This results to an error returned for every row in the table since we don’t have a name field in the anime_lists table. To solve this issue, all we have to do is use the fields that we have on the wp_anime_lists table:

var $default_columns = array('id', 'title', 'genres', 'producer');

Once you’ve updated the file, the result should now look like this:

Anime Lists

Now we can proceed with the public facing side of the website.

Before we move on, it’s important to know that every time we use the command line to generate models, controllers and views. WP MVC also assigns a new page for that model. So for the AnimeLists model, it creates the anime_lists page. Don’t forget to enable mod_rewrite in your Apache configuration, add the WordPress .htaccess file, and set the permalinks settings to use post name.

Permalinks

For your convenience, here’s the .htaccess file that I’m using:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /WordPress/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /WordPress/index.php [L]
</IfModule>

# END WordPress

Once you’re done with that, you can now check if you can access the page. By default, you wouldn’t see anything in there. That’s what were going to work on.

http://localhost/WordPress/anime_lists/

First, open the app/controllers/anime_lists_controller.php file. This is the controller for the anime_lists page. By default, it should contain the following code:

<?php

class AnimeListsController extends MvcPublicController {

}

?>

This is fine if you want to stick with the defaults that are added from the base public controller (MvcPublicController). But if you want to customize things a little bit, you have to override the index method with the following:

public function index() {

    $params = $this->params;
    $params['per_page'] = 6;
    $collection = $this->model->paginate($params);
    $this->set('objects', $collection['objects']);
    $this->set_pagination($collection);

}

What we’re doing above is to get the default parameters supplied in the base controller by using $this->params. We then assign it to a variable so that we can override the default values. By default, the controller selects 10 items from the database per page. If I only want to select 6, I can do that by setting the per_page parameter to 6:

$params['per_page'] = 6;

That’s really all we need to customize. The rest of the code just creates a collection using the paginate method in the model. This collection is then used to pass the ‘objects’ (anime shows), and then set the pagination into the view.

$collection = $this->model->paginate($params);
$this->set('objects', $collection['objects']);
$this->set_pagination($collection);

Now open up the view that’s responsible for rendering the anime_lists page. It’s at app/views/anime_lists/index.php. Once opened, add the following code:

<h2>Anime Lists</h2>

<div id="anime-shows">
    <?php foreach ($objects as $object): ?>

        <?php 
        $this->render_view('_item', array('locals' => array('object' => $object))); 
        ?>

    <?php endforeach; ?>
</div>

<div id="pagination">
    <?php echo $this->pagination(); ?>
</div>

This loops through all the objects that we have passed earlier from the controller. Inside the loop, we render the view which displays the details for each object. The render_view method takes up the name of the view as its first argument, and the data that we want to pass in as the second.

<?php 
$this->render_view('_item', array('locals' => array('object' => $object))); 
?>

Finally, we output the pagination.

<?php echo $this->pagination(); ?>

Next, open up the _item.php file on the same directory and then add the following code:

<div class="anime-show">
    <div class="anime-poster-container">
        <a href="<?php echo mvc_public_url(array('controller' => 'anime_lists', 'id' => $object->id)); ?>">
            <img src="<?php echo $object->poster; ?>" class="anime-poster">
        </a>
    </div>
    <div>
        <strong><?php echo $object->title; ?></strong>
    </div>
    <div>
        <?php echo $object->producer; ?>
    </div>
    <div class="genre">
        <small><?php echo $object->genres; ?></small>
    </div>
</div>

This shows the details for each object. As you can see from the above code, we can directly access each of the fields from the $object variable. We’re also using a helper function called the mvc_public_url to generate a URL which points to the individual pages for each object. This method takes up an array which contains the name of the controller and the ID of the object.

<?php 
echo mvc_public_url(array('controller' => 'anime_lists', 'id' => $object->id)); 
?>

This generates a URL similar to the following:

http://localhost/WordPress/anime_lists/2/

Next, we also have to update the individual object page. To do that, open up the show.php file. Still on the same directory.

<p>
    <?php 
    echo $this->html->link('&#8592; All Anime Lists', array('controller' => 'anime_lists')); 
    ?>
</p>
<div id="anime-show">
    <div class="anime-poster-container">
        <img src="<?php echo $object->poster; ?>" class="anime-poster">
    </div>
    <div>
        <strong><?php echo $object->title; ?></strong>
    </div>
    <div>
        <?php echo $object->producer; ?>
    </div>
    <div class="genre">
        <small><?php echo $object->genres; ?></small>
    </div>
    <div class="plot">
        <small><?php echo $object->plot; ?></small>
    </div>
</div>

Not much difference here. It’s basically the same as the output in the previous view. Only this time we also output the plot.

<div class="plot">
    <small><?php echo $object->plot; ?></small>
</div>

We are also adding a link to the main anime_lists page:

<?php 
echo $this->html->link('&#8592; All Anime Lists', array('controller' => 'anime_lists')); 
?>

To make things a little bit pleasing to the eye. Let’s add some css for the public facing side of the website. You can add stylesheets on the app/public/css directory. Just name the file anime-lists.css and add the following code:

#anime-shows {
    overflow: auto;
    padding: 20px;
}

.anime-show {
    float: left;
    width: 227px;
    margin: 10px;
    height: 470px;
    font-size: 15px;
}

.anime-poster-container {
    height: 332px;
    overflow: hidden;
}

#anime-show {
    padding: 20px;
    width: 500px;
}

.plot {
    margin-top: 10px;
    font-size: 16px;
}

.genre {
    color: gray;
}

#pagination {
    padding: 20px;
}

#pagination .page-numbers {
    padding: 0 10px;
}

In order to use the stylesheet that we’ve just created. Create a bootstrap.php file under the app/config directory of your plugin. Then we add the following code:

<?php
add_action( 'wp_enqueue_scripts', 'animelists_enqueue_scripts' );

function animelists_enqueue_scripts($options) {
    wp_register_style('animelists_style', mvc_css_url('anime-list', 'anime-lists.css'));
    wp_enqueue_style('animelists_style');
}

The code above should look familiar. It’s how we usually add custom scripts and styles to WordPress. Only this time we’re using another helper function called mvc_css_url. This function takes up the machine-friendly name of the plugin (Hint: copy the folder name of your plugin) and the file name of the stylesheet.

Once you’re done with that, and you’ve added some items in the admin side. The final output should look like this:

Public

You can check out the code used in this plugin on this GitHub Repo.

Conclusion

That’s it! In this tutorial you have learned about how to implement MVC in WordPress by creating a plugin which utilizes it. We have only scratched the surface in this tutorial. Be sure to check out the WP MVC documentation to learn more. How about you? Do you know or use any other MVC solutions for WordPress? Let us know in the comments.

Frequently Asked Questions about WordPress MVC

What is the difference between WordPress MVC and traditional WordPress development?

Traditional WordPress development involves using PHP to create themes and plugins, while WordPress MVC (Model-View-Controller) is a design pattern that separates the application logic into three interconnected components. This separation allows developers to manage complex applications more efficiently. The Model handles the data and business logic, the View manages the display of data, and the Controller handles user input. This structure makes the code more organized, reusable, and easier to maintain.

How can I start using WordPress MVC?

To start using WordPress MVC, you need to install a WordPress MVC framework. There are several options available, such as WP MVC, Typerocket, or Rareloop. Once installed, you can start creating models, views, and controllers for your WordPress application. These frameworks provide detailed documentation and tutorials to help you get started.

What are the benefits of using WordPress MVC?

WordPress MVC offers several benefits. It provides a clean and organized structure for your code, making it easier to maintain and update. It also promotes code reusability, as you can use the same model or view across different parts of your application. Moreover, it separates the business logic from the presentation layer, allowing developers and designers to work independently.

Is WordPress MVC suitable for all types of WordPress projects?

WordPress MVC is particularly beneficial for complex projects that require a high level of organization and scalability. However, for simple websites or blogs, traditional WordPress development might be more straightforward and efficient.

Can I use WordPress MVC with existing WordPress themes and plugins?

Yes, you can use WordPress MVC with existing themes and plugins. However, you might need to modify the code to fit the MVC structure. It’s also possible to create your own MVC-based themes and plugins.

Is it difficult to learn WordPress MVC?

If you’re familiar with the MVC design pattern and have experience with PHP, learning WordPress MVC should be relatively straightforward. However, if you’re new to MVC or PHP, it might take some time to get used to the structure and syntax.

Can I use WordPress MVC for e-commerce websites?

Yes, WordPress MVC can be used for e-commerce websites. It can handle complex functionalities and large databases, making it suitable for online stores.

How does WordPress MVC handle database operations?

In WordPress MVC, the Model is responsible for handling database operations. It communicates with the database, performs queries, and returns the results. This separation of concerns makes the code cleaner and easier to manage.

Can I use WordPress MVC with other programming languages?

WordPress MVC is based on PHP, which is the primary language used for WordPress development. However, you can use other languages for certain parts of your application, such as JavaScript for the front-end.

What resources are available to learn WordPress MVC?

There are several resources available to learn WordPress MVC. You can start with the official documentation of the MVC framework you’re using. There are also online tutorials, courses, and forums where you can learn and get help from the community.

Wern AnchetaWern Ancheta
View Author

Wern is a web developer from the Philippines. He loves building things for the web and sharing the things he has learned by writing in his blog. When he's not coding or learning something new, he enjoys watching anime and playing video games.

ChrisBmvcplugin developmentWordPressWordPress MVCWP MVCwpmvc
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week