Keeping MODX Relevant — Part Three

Jason Coward
Jun 19, 2015 · 6 min read

Persistence and Progress

My vision for MODX 3 is disruptive on purpose. And originally, this final part of my series on the ideas I have to keep MODX relevant as web technology continuously evolves was going to focus on some revolutionary concepts around persistence. But as time has marched on, I feel the time is not right for my next generation persistence library yet, nor is the code where I expected it to be by now after various self-imposed reviews of what I am doing. So instead of focusing on next generation persistence, I want to focus on changes to the existing xPDO project that will help keep MODX relevant in the coming years, as well as provide an update on where MODX 3 stands in its lifecycle.

xPDO Meets Composer

While it may not be revolutionary, the next generation of xPDO itself is available now on Packagist. You can include this in any composer-based project with the simple command:

composer require xpdo/xpdo ^3.0@dev

Composer, Namespaces and Autoloading

One feature which has prevented MODX from keeping pace with many other modern PHP frameworks and content management solutions is the proprietary class loading that it depends on and inherits from xPDO 2.x. xPDO was conceived before PSR-0 was established and until now has not been able to implement support for autoloading it’s classes via these now well-established standards. xPDO 3 to the rescue.

We Don’t Need No Stinkin’ Maps

Another significant difference in xPDO 3 is the absence of map files. The data maintained in these files defined the mapping between fields in the database and the properties of the objects. To achieve efficient auto-loading with xPDO 3, these maps are no longer stored in separate files. Instead, they are now stored as a static member of the “platform” class. A typical generated platform class then looks like the following:

<?php
namespace xPDO\Test\Sample\mysql;

use xPDO\xPDO;

class xPDOSample extends \xPDO\Test\Sample\xPDOSample
{
public static $metaMap = array (
'package' => 'xPDO\Test\Sample',
'version' => '3.0',
'table' => 'xpdosample',
'extends' => 'xPDO\Om\xPDOSimpleObject',
'fields' =>
array (
'parent' => 0,
'unique_varchar' => NULL,
'varchar' => NULL,
'text' => NULL,
'timestamp' => 'CURRENT_TIMESTAMP',
'unix_timestamp' => 0,
'date_time' => NULL,
'date' => NULL,
'enum' => NULL,
'password' => NULL,
'integer' => NULL,
'float' => 1.0123,
'boolean' => NULL,
),
'fieldMeta' =>
array (
'parent' =>
array (
'dbtype' => 'int',
'precision' => '11',
'phptype' => 'integer',
'null' => false,
'default' => 0,
),
'unique_varchar' =>
array (
'dbtype' => 'varchar',
'precision' => '255',
'phptype' => 'string',
'null' => false,
'index' => 'unique',
),
'varchar' =>
array (
'dbtype' => 'varchar',
'precision' => '100',
'phptype' => 'string',
'null' => false,
),
'text' =>
array (
'dbtype' => 'text',
'phptype' => 'string',
'null' => true,
),
'timestamp' =>
array (
'dbtype' => 'timestamp',
'phptype' => 'timestamp',
'null' => false,
'default' => 'CURRENT_TIMESTAMP',
'attributes' => 'ON UPDATE CURRENT_TIMESTAMP',
),
'unix_timestamp' =>
array (
'dbtype' => 'int',
'precision' => '11',
'phptype' => 'integer',
'null' => false,
'default' => 0,
),
'date_time' =>
array (
'dbtype' => 'datetime',
'phptype' => 'datetime',
'null' => true,
),
'date' =>
array (
'dbtype' => 'date',
'phptype' => 'date',
'null' => true,
),
'enum' =>
array (
'dbtype' => 'enum',
'precision' => '\'\',\'T\',\'F\'',
'phptype' => 'string',
'null' => false,
),
'password' =>
array (
'dbtype' => 'varchar',
'precision' => '255',
'phptype' => 'string',
'null' => false,
),
'integer' =>
array (
'dbtype' => 'int',
'precision' => '11',
'phptype' => 'integer',
'null' => false,
),
'float' =>
array (
'dbtype' => 'decimal',
'precision' => '10,5',
'phptype' => 'float',
'null' => false,
'default' => 1.0123,
),
'boolean' =>
array (
'dbtype' => 'tinyint',
'precision' => '1',
'phptype' => 'boolean',
'null' => false,
),
),
'indexes' =>
array (
'unique_varchar' =>
array (
'alias' => 'unique_varchar',
'primary' => false,
'unique' => true,
'type' => 'BTREE',
'columns' =>
array (
'unique_varchar' =>
array (
'collation' => 'A',
'null' => false,
),
),
),
),
);
}

New CLI Tool

Part of xPDO 3 is a new CLI tool which handles reverse and forward-engineering of schemas and models. The scripts are easy to use and provide more flexible options than the techniques in 2.x afforded.

bin/xpdo parse-schema [[ — compile|-c]| — update=[0–2]| — regen=[0–2]] PLATFORM SCHEMA_FILE PATH
bin/xpdo write-schema [?] PLATFORM SCHEMA_FILE PATH

Backwards Compatibility

Though not yet solved, backward compatibility should be achievable by providing some extended core classes in the global namespace. This should allow existing 2.x model code that is not aware of namespaces to continue operating on the 3.x runtime, and pave the way for a decent level of BC to be maintained for the models developers have created in their MODX Extras built for existing releases.

Early Proof of Concept

Since we can all rest easy now, knowing that persistence in MODX 3 will remain familiar to what we already have, it’s time to focus on the actual implementation of existing MODX features on the new architecture. A very simple proof of concept I worked on a couple of weeks ago might provide some insight into what the foundation of MODX 3 might start to look like and be capable of. This is using Slim’s latest stable releases, not the 3.x branch with PSR-7, but the concept of how Slim’s routing, requests, and responses might replace the proprietary ones built into MODX currently is exemplified none-the-less.

Slim 3 Beta

I’ve also been busy working with a group of amazing contributors to get Slim 3 ready for the first beta release. It shouldn’t be too long before we see it. We are essentially just waiting for a release of the fast-route dependency that contains a new feature we needed added to the project in order to reach beta state. The feature, optional route segment support, is integrated and working, but is not yet in a release of FastRoute with at least beta stability which prevents the use of Slim 3 in any project that does not set it’s root minimum-stability to “dev”.

Thanks to Ryan Thrash

Jason Coward

Written by

MODX Co-Founder and Chief Architect — loves cooking, backpacking, snowshoeing, playing drums, web development, Open Source Software, and photography

Jason Coward

Written by

MODX Co-Founder and Chief Architect — loves cooking, backpacking, snowshoeing, playing drums, web development, Open Source Software, and photography

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store