Jump to content

The PW (M)VC project


Recommended Posts





Processwire MVC by Harmster

A quick guide



I am developing a MVC like module for Processwire. My goal is to split code login and design as much as possible.

If you're familiar with CakePHP and or Zend you shouldn't have much trouble as those are the frameworks I loosely based this on.

This module comes with Twig Template engine from Symfony 2 (see more here)


Download PWMvc at github: https://github.com/Hawiak/MvcModule


1) Drag/upload/add the /site/modules/MvcModule folder into your project's module folder.

2) Search for new Modules

3) Install MVC

UyneNh9.png4) Press "Submit", this is important, without the submit your paths are not saved.

5) Leave every textfield as it is for now, these are the defaults.

6) Create 3 folders in your /site/templates folder and call them assets, snippets and layouts

7) You are going to need a default layout file, just create a new php file in the folder layouts you just created called layout.php

8) Place the AppController.class in your /site/templates

9) Place the _create_mvc.php in your /site/templates

10) Edit your /site/config.php and add the following line

$config->appendTemplateFile = '_create_mvc.php';

Files, Folders and Fields

You might be wondering what you just installed. Here's a quickreference guide to the files:

FILE: AppController.class

This is actually just an empty class and it can be used for things that are all the same over your website, so not controller reliable. For example a title that you want to append on each one of the controllers, or scripts or stylesheets you want to have all over your website.

FILE: _create_mvc.php

This script sets up the MVC, it fetches the action, calls the methods. This script runs after EVERY template but only works if the template has an MVC field. 

FIELD: mvc

If you've installed the MVC module you will notice you have an extra field installed called MVC. Add this field to every template you want to enable MVC on.

FOLDER: assets

In this folder there will be 2 folders called, scripts and styles by default but you can place any folders in here. By default MVC will look in these folders for scripts or styles you use using the $script or $styles property of the controller.

FOLDER: layouts


In this folder you will put your layout files, layout files is the structure of your website, think about a <head> and <body> tag, in general this is the same for most of your views, however you can set layouts per controller, even per action. Read about that later.

FOLDER: snippets

In this folder you will put your snippet files, snippets are piece of code that you re-use.

The Controller

The Controller is the Base provided by MvcModule. It has basic functionality and some properties (These will be extended if needed over time)

For now the Controller class has these properties:

  • layout - The "layout" property is used to set a file to be used as a layout file, this can be done in the method or the controller.
  • view - The "view" property can be used to change the view for the action, by default the view will be the same as the action e.g. index.view for the index action and edit.view for the edit action.
  • vars = array() - An array with all the variables that are being used in the controller and in the view, try and not use this variable but it is accesible in any controller or the AppController. Use the set() method instead.
  • render_layout = 1 - This will be a switch to turn of the layout rendering, handy for ajax calls.
  • layout_vars = array() - This is a array with all the vars being used in the layout, same applies here as for the vars, try and not use this variable but still it is accesible throughout your project. Use the set_layout_var instead.
  • scripts = array() - An array with all the scripts for a project, use as follow: $scripts = array('1' => 'jquery.js'); The 1 is the sequence of which the scripts will be loaded, it is handy when you want to load jquery before you load foundation or bootstrap. The scripts need to be in the /site/templates/assets/scripts folder by default.
  • styles = array() - An array with all the styles for a project, use as follow: $styles= array('1' => 'jquery.css'); The 1 is the sequence of which the styles will be loaded, it is handy when you want to  bootstrap first before your theme The styles need to be in the /site/templates/assets/styles folder by default.
And these methods:
  • set($var, $val) - Will set a variable for your View
  • set_layout_var($var, $val) - Will set a variable for your Layout

The AppController

The AppController is the class you want to extend when creating a controller, its basicly an empty class where you can put custom stuff in, this class extends the Controller inside the MvcModule folder.

Make custimizations in this class to prevent issues while updating MvcModule.

Setting up a controller

To set up a controller you need to create a file in the root of the template folder (/site/template). Name it like you named the template. It needs to be the same name as the template. 

Then create a class in it with a capital at the beginning, and append it with the word Controller.

This is an example for the Controller Test in /site/template/test.php:

class TestController extends AppController{


You'll then have to set up methods inside this class, lets say you have an edit, view, delete and a list view of a few pages.

class TestController extends AppController{
   public $title;

   public function index(){
      $this->set('list-view', $pages->find('/'));
   public function view(){
      $this->set('view', $pages->get($this->input->urlSegments[2]));
   public function edit(){
      $this->set('edit', $pages->get($this->input->urlSegments[2]));
   public function delete(){
      $page_id = $sanitizer->value($this->input->urlSegments[2]);

The code here is just to demonstrate how different views work and far from efficiant.

In order for the views to work you'll have to create views in the view folder, like index.view, view.view, edit.view and delete.view.

Because the TestController extends AppController and AppController extends Controller and Controller extends Wire you can use ProcessWire function by using $this.

Template variables

The following variables should be available in your template/layout/snippet (Not all of them have been properly tested)

  • user
  • pages
  • page
  • sanitizer
  • files
  • input
  • permissions
  • roles
  • templates
  • session
  • config
  • controller
  • wire
  • this (mvc module)

Using Layouts

A layout is the markup of your website. Its most of the time the same on all the pages for every view. It goes like. A very simple example of a working layout is:

		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
		{{ this.render_headers()|raw }}
	    <title>{{ this.controller.title }}</title>
	<body data-spy="scroll" data-target="#main-nav">
		{{ this.render_snippet('navbar.php')|raw }}
		{{ this.render_view()|raw }}
		{{ this.render_snippet('login.php')|raw }}

As you can see I used $this->controller->title you can set any variable you like and used it in here.

Also, there is the $this->view_body. The view body is the result from the rendered view. 

And I use the method $this->render_headers() this renders the script and styles for your layout defined in your controller. 

You can define a layout for each controller or even for each method. Using $this->layout = 'yourlayout.php'; anywhere in your controller.

Using Snippets

A snippet can be used for a lot of stuff, like your navbar or your login, something you want to re use but not necessary on your layout. You can render a snippet using the {{ render_snippet(string $snippet_name, array $vars)|raw }} Just give the name e.g. login.php and an array of variables you want to use within the snippet, the variables are optional.

The snippets can also access controller variables and/or wire variables objects.

Using Views

A view is where you will put your markup and all the stuff that your visitor will see. A simple basic page could just display a body 

A view that just displays the body that is set in the controller ($this->set('body', $this->pages->get('/'))) and then just echo $body on the view

This is an example view:

   {{ body }}


Twig template engine has been implemented see the Twig documentation for more info


  •  Create more controller methods that make it easier to generate views 
  •  Create an Error class for MVC enabled templates.
  • Implementing Twig as a template engine for views and possible layouts, snippets.
  • Implement feutures like extend in twig. May change the core.
  • Advanced testing
  • Write tutorial

The module now features an admin panel.

  •  Create view files/folders from admin panel
  •  Create controllers from the admin panel
  •  Create new methods in the controller from the admin panel


- 11/20/2013 - Updated whole module

- 11/22/2013 - Implemented Twig, renamed views extension to .tmpl


  • Like 5
Link to comment
Share on other sites

Created new OP.


No i was not aware, however, I do like to try around a little and I managed to rebuild part of my site within 30 minutes to the MVC model I just made, there are some bugs and its far from polished but its 2 days old...;)

Link to comment
Share on other sites

Hi Harmster, This is looking pretty cool.

I made a module that does some of the same things yours does, I was able to work around needing to set appendTemplateFile by taking advantage of a couple hooks, you might find what I did useful:


Hey, thanks! that is helpful, I am almost certain that your module is about 20 times better then mine, but I do like to try and make my own just to see if I can. Thanks for sharing! I'll implement this.

Link to comment
Share on other sites

  • 1 month later...

As I’ve been playing around with Ruby on Rails lately, I really like this approach, Harmster! Have been trying to implement a similar–but by far not as sophisticated–structure in my PW projects. I especially like the possiblity to define what scripts and styles are loaded in what order for each view. Also the “scaffolding” helpers in admin panel are a great idea.

Keep on the good work. I will test it and try to implement it in one of my on-going side projects.

BTW: I forked your repo, Harmster, to play with your code and get a better understanding how your ideas work: https://github.com/oliverwehn/MvcModule/tree/dev

I don’t really get the way you get everything together and rendered in the _create_mvc method. But I’m diggin’!

Link to comment
Share on other sites

  • 2 weeks later...

Sorry I was busy with my internship. So I haven't replied for a while.

What do you mean, how I render everything? I added a hook and then used methods from the module to echo the result from those methods. I'll try and update this more but I am very busy finding a job atm (anyone in Zwolle area? please? :D)

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Currently I am facing an issue Twig related. 
The issue:

When I tried to use the CSRF methods from PW in a twig template I encountered an error. I've tried hundrerds of different things and on Stackoverflow I didn't find the solution either.


If anyone knows something more I'll glad to hear from you.

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By MarkE
      This fieldtype and inputfield bundle was built for storing measurement values within a field, rendering them in a variety of formats and converting them to other units or otherwise modifying them via the API.
      The API consists of a number of predefined functions, some of which include...
      render() for rendering the measurement object, valueAs() for converting the value to another unit value, convertTo() for converting the whole measurement object to different units, and add() and subtract() for for modifying the stored value by the value (converted as required) in another measurement. In the admin the inputfield includes a checkbox (which can be optionally disabled) for converting values on page save. For an example if a value was typed in as centimeters, the unit was changed to metres, and the page saved with this checkbox selected, said value would be automatically converted so that e.g. 170 cm becomes 1.7 m.

      A simple length field using Fieldtype Measurement and Inputfield Measurement.
      Combination units (e.g. feet and inches) are also supported.
      Please note that this module is 'proof of concept' at the moment - there are limited units available and quite a lot of code tidying to do. More units will be added shortly.
      See the GitHub at https://github.com/MetaTunes/FieldtypeMeasurement for full details and updates.
    • By tcnet
      File Manager for ProcessWire is a module to manager files and folders from the CMS backend. It supports creating, deleting, renaming, packing, unpacking, uploading, downloading and editing of files and folders. The integrated code editor ACE supports highlighting of all common programming languages.

      This module is probably the most powerful module. You might destroy your processwire installation if you don't exactly know what you doing. Be careful and use it at your own risk!
      ACE code editor
      This module uses ACE code editor available from: https://github.com/ajaxorg/ace

      This module uses the JavaScript dragscroll available from: http://github.com/asvd/dragscroll. Dragscroll adds the ability to drag the table horizontally with the mouse pointer.
      PHP File Manager
      This module uses a modified version of PHP File Manager available from: https://github.com/alexantr/filemanager
    • By tcnet
      This module implements the website live chat service from tawk.to. Actually the module doesn't have to do much. It just need to inserted a few lines of JavaScript just before the closing body tag </body> on each side. However, the module offers additional options to display the widget only on certain pages.
      Create an account
      Visit https://www.tawk.to and create an account. It's free! At some point you will reach a page where you can copy the required JavaScript-code.

      Open the module settings and paste the JavaScript-code into the field as shown below. Click "Submit" and that's all.

      Open the module settings
      The settings for this module are located int the menu Modules=>Configure=>LiveChatTawkTo.

    • By tcnet
      Session Viewer is a module for ProcessWire to list session files and display session data. This module is helpful to display the session data of a specific session or to kick out a logged in user by simply delete his session file. After installation the module is available in the Setup menu.

      The following conditions must be met for the module to work properly:
      Session files
      Session data must be stored in session files, which is the default way in ProcessWire. Sessions stored in the database are not supported by this module. The path to the directory where the session files are stored must be declared in the ProcessWire configuration which is by default: site/assets/sessions.
      Serialize handler
      In order to transform session data easier back to a PHP array, the session data is stored serialized. PHP offers a way to declare a custom serialize handler. This module supports only the default serialize handlers: php, php_binary and php_serialize. WDDX was dropped in PHP 7.4.0 and is therefore not supported by this module as well as any other custom serialize handler. Which serialize handler is actually used you can find out in the module configuration which is available under Modules=>Configure=>SessionViewer.

      Session data
      The session data can be displayed in two different ways. PHP's default output for arrays print_r() or by default for this module nice_r() offered on github: https://github.com/uuf6429/nice_r. There is a setting in the module configuration if someone prefers print_r(). Apart from the better handling and overview of the folded session data the output of nice_r() looks indeed nicer.

      ProcessWire module directory
    • By Robin S
      Repeater Easy Sort
      Adds a compact "easy-sort" mode to Repeater and Repeater Matrix, making those fields easier to sort when there are a large number of items.
      The module also enhances Repeater Matrix by allowing a colour to be set for each matrix type. This colour is used in the item headers and in the "add new" links, to help visually distinguish different matrix types in the inputfield.
      A Repeater field

      A Repeater Matrix field with custom header colours

      Easy-sort mode
      Each Repeater/Matrix item gets an double-arrow icon in the item header. Click this icon to enter easy-sort mode.
      While in easy-sort mode:
      The items will reduce in width so that more items can be shown on the screen at once. The minimum width is configurable in the field settings. Any items that were in an open state are collapsed, but when you exit easy-sort mode the previously open items will be reopened. You can drag an item left/right/up/down to sort it within the items. The item that you clicked the icon for is shown with a black background. This makes it easier to find the item you want to move in easy-sort mode. You can click an item header to open the item. An "Exit easy-sort mode" button appears at the bottom of the inputfield. Configuration
      In the field settings for Repeater and Repeater Matrix fields you can define a minimum width in pixels for items in easy-sort mode. While in easy-sort mode the items will be sized to neatly fill the available width on any screen size but will never be narrower than the width you set here.
      In the field settings for Repeater Matrix you can define a custom header colour for each matrix type using an HTML "color" type input. The default colour for this type of input is black, so when black is selected in the input it means that no custom colour will be applied to the header.
      The easy-sort mode is only possible on Repeater/Matrix fields that do not use the "item depth" option.
  • Create New...