unleashing creative freedom with modx (2015-07-21 @ php frl)
TRANSCRIPT
July 2015 Meetup
www.php.frl / www.meetup.com/PHP-FRL / @PHPFRL
Echo ‘Hello World!’;www.php.frl / www.meetup.com/PHP-FRL / @PHPFRL
Location Sponsor
Pronamic
www.php.frl / www.meetup.com/PHP-FRL / @PHPFRL
Speaker
Mark Hamstra Unleashing Creative Freedom with MODX
www.php.frl / www.meetup.com/PHP-FRL / @PHPFRL
Unleashing Creative Freedom with
Who am I?Mark Hamstra
Founder & CEA at modmore Freelance MODX Developer
not me
Turbo
Bommel
Agenda
• What is MODX, for whom, available features, how to build a MODX site
• Tour of the MODX Manager (back-end)
• The Architecture of MODX, xPDO ORM, extending and overriding
MOD-what?
MOD-what?
• Open Source
MOD-what?
• Open Source
• Written in PHP (of course)
MOD-what?
• Open Source
• Written in PHP (of course)
• Already 10 years old young
MOD-what?
• Open Source
• Written in PHP (of course)
• Already 10 years old young
• Content ManagementSystem Framework Platform
All the features of a CMS
All the features of a CMS
rich text editor versioning user groupsmultisite templates multilingual extensionsmarkdown media browser hierarchicalpage tree commercial support automaticmenu builder blogging permissions seofriendly urls server-side caching
Out-of-the-box Install
Out-of-the-box Install
Elements as Building Blocks
TemplatesTemplate Variables
ChunksSnippetsPlugins
Templates
• Usually HTML
• Contains MODX tags
• One template per page
Template Variables
• Custom field for resources
• Commonly “TV”
• Tied to templates
• Text, image, select, checkbox, date, radio, richtext, tag and custom types available
• [[*name-of-tv]]
Chunks
• Usually HTML
• Reusable piece of code
• [[$name-of-chunk]]Template
Chunk “head”
Snippets
• PHP!
• Comparable to a function
• Accepts properties
• [[name-of-snippet]] or [[!name-of-snippet]]
Snippet “helloWorld”
Template
Snippets
But wait, there’s more!
• [[name-of-snippet]]
• [[!name-of-snippet]]
• = uncached!
• [[++name-of-setting]][[!++name-of-setting]]
• [[$name-of-chunk]][[!$name-of-chunk]]
• [[*name-of-field]][[!*name-of-field]]
But wait, there’s even more!
• [[helloWorld? &property=`value ̀]]
• [[$head? &extraCss=`<link rel=.. href=..> ̀]]
Plugins
• PHP!
• Event-based, so no tags
• Can read and often influence behaviour
No need to reinventthe wheel
• Packages (aka extras, add-ons, extensions, third party components…) provide common functionality
• Install via Package Installer inside the manager
Example: getResources
• Lists resources matching conditions
• Uses a Chunk as template
• Use Cases:
• Article listings
• Dynamic (sub)menus
• RSS feed generation
Template
Chunk “blogListItem”
Time for a Manager Tour!http://localhost/tmp/phpfrl/manager/
MODX Architecture
Secure by Design
• Automatic $_GET, $_POST, $_REQUEST sanitisation in the request handler
cve.mitre.org
Secure by Design
• Automatic $_GET, $_POST, $_REQUEST sanitisation in the request handler
• xPDO ORM prevents SQL Injections
cve.mitre.org
Secure by Design
• Automatic $_GET, $_POST, $_REQUEST sanitisation in the request handler
• xPDO ORM prevents SQL Injections
• 28 CVE entries, 8 since 2014• WordPress: 906, already ~85 in 2015• Drupal: 915, already ~120 in 2015
cve.mitre.org
xPDO
xPDO
• Object Relational Bridge / ORM
xPDO
• Object Relational Bridge / ORM
• Open Source (modxcms/xpdo)
xPDO
• Object Relational Bridge / ORM
• Open Source (modxcms/xpdo)
• Extension to PHP’s PDO
xPDO
• Object Relational Bridge / ORM
• Open Source (modxcms/xpdo)
• Extension to PHP’s PDO
• Support for MySQL, sqlsrv (and more)
Fetching a Single Object
$c = 5;
$obj = $modx->getObject(‘modChunk’, $c);
$c2 = array(‘name’ => ‘head’);
$obj = $modx->getObject(‘modChunk’, $c2)
Easy Query Builder
$c = $modx->newQuery(‘modResource’);
$c->where([
‘parent’ => 0,
‘AND:pagetitle:LIKE => ‘%About%’
]);
$matches = $modx->getCollection(‘modResource’, $c);
foreach ($matches as $modResource) { . . . }
Automatic Filtering
$search = $_POST[‘search’];
$c = $modx->newQuery(‘modResource’);
$c->where([
‘introtext:LIKE’ => “%{$search}%”,
]);
$modx->setPlaceholder(‘search’, sanitise($search));
function sanitise($value) { return htmlentities($value, ENT_QUOTES, ‘UTF-8’); }
👍
⚠
Custom Models with xPDO
Custom Models with xPDO
1. Create an xPDO Package Schema (XML)
2. Use build script to write schema into the actual model files/classes
3. Register it before use ($modx->addPackage)
4. Use any xPDO method (getObject, getCollection) on your custom model
xPDO Package Schema - Head
<?xml version="1.0" encoding="UTF-8"?>
<model package="phpfrl"
baseClass="xPDOSimpleObject"
platform="mysql"
defaultEngine="MyISAM"
version="1.1">
xPDO Package Schema - Object
<?xml version="1.0" encoding="UTF-8"?>
<model package=“phpfrl” …
<object class="frlMeetup" table=“meetups”>
.. fields ..
</object>
<object class="frlSpeaker" table=“speakers”> … </object>
</model>
xPDO Package Schema - Fields<?xml version="1.0" encoding="UTF-8"?>
<model package=“phpfrl” …
<object class="frlMeetup" table=“meetups">
<field key="name" dbtype="varchar" precision="100" phptype="string" null="false" default=“PHP FRL Meetup" />
xPDO Package Schema - Indices
<?xml version="1.0" encoding="UTF-8"?>
<model package=“phpfrl” …
<object class="frlMeetup" table=“meetups"> <field key="name" dbtype=“varchar" … <field key=“starts_on" dbtype=“datetime" <field key="name" dbtype=“varchar" …
<index alias="name" name="name" primary="false" unique="false" type="BTREE"> <column key="name" length="" collation="A" null="false" /> </index> </object>
xPDO Package Schema - Relations<?xml version="1.0" encoding="UTF-8"?>
<model package=“phpfrl” baseClass=“xPDOSimpleObject" …
<object class="frlMeetup" table=“meetups"> <field key="name" dbtype=“varchar” …>
<composite alias=“Speakers” class=“frlSpeaker” local=“id” foreign=“meetup” cardinality=“many” owner=“local” /> </object>
<object class="frlSpeaker" table=“speakers"> <field key="name" dbtype=“varchar” …> <field key="meetup" dbtype=“int” …>
<aggregate alias=“Meetup” class=“frlMeetup” local=“meetup” foreign=“id” cardinality=“one” owner=“foreign” /> </object>
xPDO Generated Model
<?phpclass frlMeetup extends xPDOSimpleObject {
}
<?php
class frlMeetup_mysql extends frlMeetup {
}
Interacting with that model$modx->addPackage(‘phpfrl’, ‘/path/to/model/‘);
$c = $modx->newQuery(‘frlMeetup’);$c->sortby(‘starts_on’, ‘DESC’);$meetup = $modx->getObject(‘frlMeetup’, $c);
echo ‘De volgende meetup is ‘ . $meetup->name . ‘ en vind plaats op ‘ . $meetup->starts_on . ‘. ’;
$speakers = $meetup->getMany(‘Speakers’); // or just $meetup->Speakersforeach ($speakers as $spegfytaker) { echo $speaker->name . ‘ zal vertellen over ‘ . $speaker->subject;}
Interesting links: • MODX.com => official website • rtfm.modx.com => official documentation • github.com/modxcms/revolution => source code • MODX.today => daily links/articles about MODX • modmore.com => premium extras for MODX • https://joind.in/14897 => please leave feedback
Enjoy your Creative Freedom