Blog

10-ish Secrets for Successful Mura CMS Development

May 16, 2017 by Grant Shepert

I've been developing applications on top of and alongside Mura CMS for a long time. and over the years I've built up a list of important do's, and a few don'ts, when it comes to making the most of my time and energy.

Let me share a few of them with you (10ish, since some sections contain multiple tips).

Where should my display object override go?

One of the genius things about Mura CMS is the abundance of ways the default functionality and logic can be overridden and extended. For instance, if you don't like the way the login form is rendered, you can substitute the default /[siteid]/includes/display_objects/login/ with a custom login form of your own. You can do this by copying the directory into one of two places:

  • /[siteid]/includes/display_objects/custom/login/
  • /[siteid]/includes/themes/display_objects/themes/[current_theme]/display_objects/login/

Now, which one should you use? Well, if it is theme-related, you should put it in the theme's display_objects folder, otherwise keep your overrides in the custom folder. The more consistent you are, the easier it will be to find things later. Also, remember that if you put the /login override in both places, the one in the theme directory will be used.

When and where (not) to use custom events, plugins, formbuilder, class extensions and display objects, simplified! getmura.com/blog

Do X before Y happens

Whenever Mura CMS loads a page, logs a user in or performs any other action, there is usually an event tied to it. This means the quick answer to the question "how do I get x to happen before/after/instead of y" is always going to be, "use an event handler". You can find your generic event handlers here:

  • /[siteid]/includes/eventHandler.cfc
  • /[siteid]/includes/themes/[current_theme]/eventHandler.cfc

For examples, see the comprehensive list of events in our documentation. So, if you want to run a custom function before a Mura CMS page renders, put this into either of the above eventHandler.cfc files (and reload the Mura CMS application via the admin, because they are cached):

function onRenderStart($) {
// do my stuff!
}

That's it. The onRenderStart() and onApplicationLoad() methods are the two most powerful tools you can use to start building custom functionality into Mura CMS.

Config.xml magic

A little-known tool in custom Mura CMS development is the config.xml.cfm file. This file can contain all sorts of configuration magic, from creating new class extensions to adding custom site settings and a lot in between. They can be site- or theme-specific too, so if you need to add custom configurations when your theme (or bundle) is installed, you can cover a lot of ground by using one of these. My recommendation is that you get to know them, as they can solve otherwise complex problems very quickly.

Class Extensions, when?

Class extensions are very good at handling and displaying meta data. For instance, you want to add a middle name to a user, or an isbn field to a page for books. If, however, you are doing a lot of complex searching and sorting on these fields, consider that each class extension relies on three related tables with their own sets of indexes, each of which has to be collected independently, every time it is queried. In normal circumstances this is fine, but if you are building complex feeds, for instance, you may find they slow down your website.

Okay, so use Mura ORM then?

Yes! Mura ORM is a fantastic and powerful tool. It allows you to create Mura CMS "beans", i.e. cfc objects, that are automatically bound (aka 'wired') to both the Mura CMS core and to each other. If you are planning on doing a lot of heavy querying via feeds on a custom set of criteria, you should definitely consider using a Mura CMS bean that is indexed and configured specifically to your needs. For instance, lets take a look at a book Mura ORM object:

component extends="mura.bean.beanORM" table="example_book" entityName="book" displayName="Book" {
property name="testormid" fieldtype="id";
property name="content" fieldtype="one-to-one" belongsto="content";
property name="author" fieldtype="one-to-many" belongsto="user" fkcolumn="userid";
property name="publisher" fieldtype="many-to-many" belongsto="publisher";
property name="isbn" length="35" datatype="varchar" fieldtype="index";
property name="publishdate" datatype="date" fieldtype="index";
}

In this case, our "book" object is tied to a single content page, multiple users (via author), and a custom publisher Mura ORM object. You will be able to create a Mura CMS collection using the ISBN or publishing date, and add in any custom functionality you might want when you render it. An example in code might be:

var myBook = m.getBean('book').loadBy(isbn='x');
writeOutput( myBook.getContent().getTitle() );
// or
var myBookFeed = m.getBean('book').getFeed().addParam(field='publisherid',condition='equals',criteria='x',relationship='and');

This will make you very happy.

Auto Wiring Mura ORM

So, how do I get Mura to see these? Easy! First, read my blog post on Mura ORM. Then ... well, that was it, really. Enjoy!

Can I use Formbuilder to collect application data?

No.

Why not?

Formbuilder is a very tempting tool to use when you are contemplating a new application or extension to Mura CMS. You can build a complex multi-page form very quickly, it has built in validation, and it stores the data inside Mura. Brilliant, right? Wrong. Formbuilder builds forms, not applications. It is really good at the former, really bad at the latter. All collected data from a form submission is stored inside XML blocks, so searching through it is next to impossible. And, even if/when we tie Mura ORM to the Formbuilder (which may never happen, for reasons), it still wouldn't be a good choice because it is still at its heart a tool for building forms and nothing else.

Don't get trapped! Even if it looks like Formbuilder is going to get you 90% of the way to building your custom application, that last 10% will kill you. Stick to using Mura ORM, display objects and/or plugins to do your complex work.

That said, we do have things in the works that will make your life easier. But I've already said too much. ;)

Plugins vs. Display Objects

This used to be a no-brainer. Before Mura 7.0, display objects were for simple things, or mildly complex things when paired to Mura ORM. For anything remotely complicated or involving a lot of files, it was always going to be plugins.

Now, not so much. If you read the above blog post on Mura ORM, you will have discovered that you can place a /model directory inside of your display_objects folder, which auto-wires your beans/events/etc. Also, the ability to create a custom configurator adds a huge amount of power to your application, where before that was more easily accomplished via a plugin.

So the answer to this is no longer so straightforward. My recommendation is, if your application has multiple display objects, a lot of files, or (and this is a display object deal-breaker) needs a back-end administrator, then go the plugin route. Otherwise, display objects can offer you a much quicker path to completion.

Also See

Webinar: Super Fast Application Development with Mura 7
Mura 6/7 Documentation: docs.getmura.com/v6/   docs.getmura.com/v7/ 
ORM Bootcamp (blog): getmura.com/blog/mura-orm-boot-camp-instantiation-relationships/