Laravel to October CMS: The Differences (Part 3)

If you missed them, you can find part one in the series here and part two here.

So last time we discovered that the C of our beloved MVC has gone. But given that we no longer have a routes.php file and all of the models are kept in plugins, it wasn't going to be able to work in the traditional Laravel way anyway.

Introducing... Components

So where the devil are my controllers? A quick look at the php artisan manual shows a create:controller command. Ignore that, it's for the CMS. The one above that, create:component.

php artisan create:component pluginCode componentName

So what is a component then? As we can see from the command above, they sit in your plugin; which gives them access to your models. The reality is they sit between the models in your plugin and the views in your theme. So far so controllers, so what's the difference?

Running the command will create a components/ directory in your plugin containing a class and a directory, both with the name of the component. The directory contains a default.htm Twig file.

We were just in controller world, but that Twig file has encroached rather rudely on the view world. The reality is a component is mostly used to get some HTML from out of your plugin and onto your pages. In most cases, those plugins will need access to some models in the plugin, so a component covers all of that.

If you take a peek in the CMS section you can see you can drop components into any of your views by just dragging and dropping them in. You can also set some options to customise the component, if possible in that particular component.

October CMS components

Then you can place them anywhere in your views with the following code:

{% component 'contactForm' %}

Easy! That will drop the contents of default.htm into your page.

As ever, if you want to read more about actually implementing a component, check out the October CMS documentation, where you can learn how you set your component's details, its properties (the arguments) and how to register it with your application.

Run Forrest, Run

Components also have a few execution cycle functions that can be overriden. You can find a full list here, but the most useful is the onRun() function. Overriding this function allows you to setup everything in preparation for adding a component's HTML to the page. Here's an example:

use Archybold\Projects\Models\Project;

class Projects extends ComponentBase
{
public $featured = null;

public function onRun()
{
$project = new Project;
$this->featured = $project->getFeatured();

$this->addJs('/plugins/archybold/projects/assets/js/projects.js');
}
}

This is a little snippet from a component I created for this very site. One to allow me to embed projects into a page.

I've overriden the onRun() function and this does a couple of things. It runs a getFeatured() function on one of my models Project, which is also defined in the plugin, and assigns the result to a public variable on the component Class $featured.

It also calls a function on ComponentBaseaddJs(). This will include a javascript file every time this component is included in a view. Similar can be done for CSS.

The first task is one that's very common for a controller to perform, but the second is unusual as we're dealing with view-specific assets.

Let's look a little deeper into our default.htm file.

{% set featured = __SELF__.featured %}

<div class="row">
{% for project in featured %}
<img src="{{ project.image|raw }}" class="img-responsive" alt="{{ project.name }}">
{% endfor %}
</div>

Here we can see we have access to that public $featured variable through __SELF__ and to the properties of each Project object eg project.image. Allowing us to access any data we've loaded in the component's onRun() function.

There's abviously far more we can do with components; you can have multiple views, for example. But I don't want to get too deep into the implementation.

Component Fantastic

As you can probably see, they're fairly powerful these components, allowing you to bundle and distribute models, views, assets and giving other users a very simple way of adding your stuff to their sites. October also make it insanely easy to distribute and even sell them, with their own plugin store. Plugins can also be added through the CMS directly. This ease of implementation makes them very powerful and must have the Wordpress guys looking over their shoulders.

But how do they differ from Laravel packages? Mostly in that you're forced into implementing them in a very specific way and there's a fantastic distribution model that even allows developers to easily monetise their work.

Also, unlike packages, you're forced into using them. Meaning the plugins library is going to grow at a speed it's hard to imagine Laravel packages growing.

Asset Yourself

We've not yet looked in any depth at how October CMS handles asset compilation, so lets take a quick look at that.

Laravel 5 introduced Elixir, a gulp plugin that made writing gulp tasks for asset compilation ridiculously simple.

Unfortunately, we don't have Elixir at our disposal out of the box here. What we do have is a very simple mechanism for bundling assets. Javascript can be bundled directly in your layout file:

<script src="{{ [
'assets/vendor/bower_components/bootstrap-sass/assets/javascripts/bootstrap.js',
'assets/js/app.js'
]|theme }}"></script>
{% scripts %}

Which will bundle any javascript files in the array into one cache-busting file with a name such as http://www.archybold.com/combine/4a78d73bb0450c17eb849e99e30728c7-1432305474. The second part - {% scripts %} - will drop your javascript dependencies from any of your included plugin components into the page, unfortunately as individual files rather than bundled into one. This is all far simpler than the Elixir equivalent where you need to write the task in your gulpfile.js:

var paths = {
'bootstrap': './vendor/bower_components/bootstrap-sass-official/assets/',
'assets': './resources/assets/'
}

elixir(function(mix) {
mix.scripts([
paths.bootstrap + 'javascripts/bootstrap.js',
path.assets + 'js/app.js'
], 'public/js/app.js', './)
.version(['public/js/app.js']);
});

Which compiles your javascript into a single file and versions it for cache-busting. Then to add it to the page you just drop the script tag into the page view:

<script src="{{ elixir('js/app.js') }}"></script>

Now lets look at CSS, well it's not far off from being the same as for the javascript:

<link href="{{ [
'assets/less/theme.less'
]|theme }}" rel="stylesheet">
{% styles %}

The first line bundles your LESS/CSS files into one file, gives it a cache-busting name and the next line adds your CSS dependencies. Without repeating code, in Laravel Elixir world you'd need to write your task, version the file and add it to your page HTML.

Seems a bit too simple, what's the catch? Yep, there are a couple of catches unfortunately. You're limited only to straight up javascript compilation - sorry no CoffeeScript - and CSS/LESS for styles. And as a SASS man (sorry), that leaves me a bit sad. Also, I've yet to find a way of minifying assets for production.

Most people might say they could live with that, but it meant I ended up writing my own gulp tasks to handle SASS compilation and minification can only be achieved with another gulp task and some extra plugins. Something you can achieve in Laravel Elixir with a single command.

gulp --production

So I'd say on assets, Laravel probably just edges it, but mostly because I use SASS as my CSS preprocessor of choice and prefer my assets production-ready.

To Conclude

And that's my introduction to October CMS for anyone who found it because of its proud 'based on Larave' tagline. I've barely even touched on the CMS, which is the only reason any of you are here really! Spoiler: it's very good, it's pretty and it's very easy to create bespoke CMS pages.

So in conclusion? There are places where October CMS edges over Laravel and there are places where it's lacking to the slightly better thinking on the Laravel side. The reality is if you're considering using October, you're only doing so because of the bundled CMS. And if that's a requirement on your project, then take the plunge; it's definitely worth it. If you're working on a larger application where you'd see the plugins of October CMS as a restriction then stick to Laravel and look into alternative CMS options. Perhaps Bootstrap CMS. Which I've not looked into in any depth myself yet.

So what do you think of October CMS? Will you be taking the plunge? Post a comment below and let me know. And if there's something October CMS-related you'd like me to write about next, let me know about that too and I'll do my best to give it some column space.

Reading in the wrong order? Click here for part one and here for part two.

Posted on Jun 12, 2015

Discuss This

blog comments powered by Disqus