Welcome to the first iteration of a tutorial document. I'll try to take you through some of the initial tasks of creating new Reason data types, modifying how those types are managed, and how to create a custom module for display. This will be a somewhat long winded document to try to explain
some of the foundational concepts involved in Reason coding.
Before you being, you need to make sure that you have access to the development server (for code editing and creation) and an account that can access the Master Admin site.
Part One: The Data
We'll be developing an application from a data-first perspective, both because this is often the work that needs to be done and also because it's a good way to understand Reason from the ground up. In this tutorial, we'll use the example of a blogging tool. This tool won't be too complicated - basically, it will be composed of some screens to add, update, delete, and list all posts on a site, the public side that visitors would see, and, a little bit later, the ability to categorize posts and have individual posts for those pages. If another kind of application sounds like a better idea, go for it. Some simple ideas are things like a library of movies, books, or CDs (these have the same sorts of information and the ability to be categorized later, which is important for later lessons). We'll start by creating the data model of the post itself and the activities surrounding it. We'll worry about categories later.
The first thing to do is determine what pieces of information are going to make up the data type you are creating. In many ways, this is similar to determining what variables should be part of a class. For a super simple version, we can just include a title for each post, the body for the post, the date of the post, keywords, and a description. (Movies, books, or albums would be a little more complicated since, for the sake of database normalization, we probably wouldn't want to include actors, directors, band names, or the like within the actual definition. Those would ideally be handled by other data types specifically for Actors, Bands, and the like).
To create the Reason data type to hold this information, we need to work backwards a little bit. Instead of creating the type first, we're going to create abstract groups of data and then the fields themselves. Some of the fields already exist, in some sense. Keywords and descriptions are common fields throughout Reason, so we've grouped these fields together in what we call an Entity Table named Meta. So instead of creating these fields anew, when we create the Type, we'll just link the Type to pre-existing Meta table. We'll get to that in a minute.
For the title, body, and date, we will create our own group. So the first step is to log into Reason, go into the Master Admin site, select the Entity Table type, and add a new one. For this tutorial, make the name of the item something like yourname_blog (so for me, it'd be dave_blog). The name needs to be unique and not conflict with other tables in the database. For this step, you can ignore the Unique Name field and leave it blank. Enter the information and click Save and Finish.
So we've now created a group of data fields but have not put any fields into that group. To do that, we need to add some Fields, so go into Fields and click on Add a new field. Here, we need to enter the name of the field, the database type, and the entity table to link it to. For the post title, use a name like 'post_title' with database type 'tinytext'. In the drop down menu, you should see the name of the entity table you created in the last step. Choose that one. For now, ignore Plasmature Type. Click Save and Finish and then add the fields 'post_body' with db type 'text' and 'post_date' with db type 'datetime'. (For more information on the database types, see MySQL's database column type reference).
So now we have an entity table containing the fields that we just created. If you want to see what it looks like, you can connect to MySQL directly (if you have access) and do a 'DESCRIBE dave_blog', with your table name, of course. It should have an id field and the fields we just entered.
Now we want to create the Blog Post data type. To do this, choose the Type link in the Add/Edit section and then add a new one. There are a lot of fields here, but we really only care about a few right now: Name, Plural Name, and Unique Name. Name and plural name should be a short string giving a good idea of what the type actually is. In the blog case, 'Blog Post' and 'Blog Posts' are good candidates. Unique name is a string that will be used in code later to uniquely identify this item, so we generally prefer all lowercase letters, underscores instead of spaces, and '_type' at the end. For this one, let's use 'blog_post_type'. Leave all the rest of the fields at their default value.
Now, we want to hit Save and Associate - this will take us to the first association which is Choose Entity Tables. On this screen, we'll want to choose all the data groups (entity tables) that this type will use. In the blog case, we want the table we just created ('dave_blog') and 'meta' (which we talked about earlier). For each of these, use the 'Select' link to link this table to this type. You may need to search for the 'meta' table since it might not be on the first results page. If you want to see more information on the 'meta' table, or your own even, you can click on the 'Preview' link and scroll down to see both which types use this table and which fields are contained within it.
Once you've selected both and they appear within the Selected area, hit the Finish link on the left hand navigation of the page. This will finish the creation of your type and take you back to the listing page where you can see your new type along with all the other ones.
So now we have a new type. It's not doing anything at the moment. The easiest way to start using this type is to add the new type to a site. If you don't already have a sandbox site for yourself, talk to someone and get one. To add the type to your site, you can go the Site listing, edit your site, and then choose Types in the left hand nav. You'll get a list of all types available - select the one you just created and Finish.
If you go to your site's administration screen, you should see your type now available in the list of types. Clicking on it will take you to the now familiar listing screen where you can add new items. The form that you will see when adding new items is the bare bones default form. Reason makes some educated guesses about how to show the fields you've added (dates are shown as date fields, text fields appear as textarea, etc). We'll get into modifying this form in a little bit.
Anyhow, there's your type in all its glory. You can add, edit, delete, and sort your data to your hearts content.
Part Two: The Frontend
So now we have some data. But we want it to appear on an actual public website. This section is about just that. There's a lot here to get started, but once you get used to it, it makes, at least, a nominal amount of sense. Hopefully.
A quick discussion on the frontned is in order. We call the system that runs all the public websites the Minisite system. Just about all sites that use Reason use this system. It's basically one script that calls a sequence of classes based on what page a visitor is looking at. The methodology can be looked at something like this: a URL that Reason manages maps directly to a particular site and a particular page. The Minisite system determines which MinisiteTemplate should be loaded for that site. The template, in turn, determines the page type of the page. Page types associate sections of the template with modules to run. Modules then determine the actual behavior of the section of the page. More concretely, most sites use the DefaultMinisiteTemplate which uses the default page type. This maps sections of the page (with names like 'main', 'sidebar', 'foot', and the like) to specific modules. So each page can place different modules in different places.
The basic process to get a page using your module, which in turns uses the data type you created in the last step, looks something like this:
- Create basic module
- Add new page type that uses that module
- Set page to use that page type
- Modify the module to your liking
I'll gloss over a bunch of the details for now and just get you in a position to start playing with modules.
So, in the Reason lib directory there is a core/minisite_templates/ and a local/minisite_templates/ directory. Here live all the templates, the page types file (page_types.php) and the modules/ directory. The local directory is the one you want to add to; the core directory is for the distributed files of Reason, and might get overwritten when you update. Create a new file in lib/local/minisite_templates/modules/ called my_blog_module.php or somesuch thing. The skeleton for one of these files looks like this:
// the value at the end of the following line should match your class name EXACTLY
$GLOBALS[ '_module_class_names' ][ basename( __FILE__, '.php' ) ] = 'MyBlogModule';
// you need to include the DefaultMinisiteModule since you will be extending it
include_once( REASON_INC . 'minisite_templates/modules/default.php' );
class MyBlogModule extends DefaultMinisiteModule
// a super simple module doesn't need to init anything
// this is the section that is run when the page renders your module
echo 'Module says "Hello World"';
Now we have a simple module that says one thing. We need to create a page type that knows to use this module. So, we edit the page_types.php file and create a new page type. The simplest method is to add a couple lines at the end of the files looking something like this:
'my_blog_module' => array(
'main_post' => 'my_blog_module',
Note that the value you specify is the name of the file, minus the .php. I've used the main_post section instead of the main section which is usually how things are done. The main section is generally used for the ContentModule so that most pages can have some content up top.
Also, it's important that you get the syntax right in this file. It's currently a very fragile file and if there is a misplaced quote or comma, it can actually bring down all of Reason. This is bad.
With that done, you can create a new page on your site and then choose your module in the Page Type drop down menu. Once you've done that, check out that page and you should see the message from your module.
To start playing with getting your data out of Reason and showing it on your site, we get to start playing with the entity_selector object. Basic usage goes something like:
// the module has access to the current site id, so grab it
$site_id = $this->site_id;
// create a new entity selector and limit the results to the current site
$es = new entity_selector( $site_id );
// add_type takes a type id, so use id_of to get the id of your type (by using its unique name)
$es->add_type( id_of( 'blog_post_type' ) );
// run the object and get back an array of entity objects
$posts = $es->run_one();
// dump it all out to see what you got
print_r( $posts );
This example just dumps out all of your entities. The result array from run_one() will always be a bunch of entity objects. These have their own interface for retrieving information about their own fields and their relationships. A simple way to get the data without dumping it all out looks something like this:
foreach( $posts AS $post )
echo $post->get_value( 'post_title' );
echo $post->get_value( 'post_body' );
echo $post->get_value( 'post_date' );
You can then throw in whatever HTML is suitable for the output.
Part Three: The Backend
Backend development is easy for most things -- editors, listers, deleters, etc. all have well-defined frameworks for extending and overloading the basic functionality the Reason backend provides. However, the shell within which these frameworks live is a bit overwhelming, poorly documented, and idiosyncratic. In other words, it pays to work from the bottom up on the backend rather than from the top down.
We'll start with the content managers.
Let's say you've created a type, and you want to modify the form used to edit items of this type. First, you need to create a new file in lib/local/content_managers/. It's generally easiest to copy an existing file from lib/core/content_managers/ and edit it to suit.
Content managers always extend the default content manager, and, like the frontend module, they need to identify in the $GLOBALS array what class corresponds to the file.
Once you have done that, you can use methods defined as hooks to modify the form. alter_data() is the primary hook used to modify the presentation of the form.
Content managers inherit from Disco, so they use all of the basic Disco interface. For example, to change the label for a field, overload the alter_data() method like this:
$this->set_display_name('dob','Your Date of Birth');
To make a field required, add this line to alter_data():
To hide an element add this line to alter_data():
Disco and the content managers give you more tools for error checking, form modification, and workflow than we can discuss here, so read the full Disco documentation (currently in Reason's phpdoc documentation) to find out more. Or you can poke around in the other content managers to figure out how to get your content manager to go what you want.