Lexicons

Fusebox

Note that the mix of references to FuseNG and Fusebox is due to the ancestory of FuseNG and its fork from Fusebox, explained here .

In Fusebox 4.1, there are two ways to extend the framework: custom lexicons and Plugins. The former method has undergone significant changes in Fusebox 5, the latter method is almost completely unchanged. This page covers the differences between Fusebox 4.1 and Fusebox 5 and the new features in lexicons offered by Fusebox 5.

Fusebox 5 supports per-circuit custom lexicons using XML namespace syntax. You declare a custom lexicon using the xmlns attribute in the <circuit> tag:

As with Fusebox 4.1, the path is relative to the lexicon/ directory in your application root. Fusebox 5.1 allows the path to be absolute (or mapped) so that lexicons can be shared across multiple applications.

You invoke custom verbs using XML namespace syntax as follows:

Custom verbs can have nested child verbs:

What's happening here?

At this point, its worth remembering what goes on when Fusebox 5 parses your circuit.xml file. Once the parser has understood the verb Fusebox has to validate the parameters and then add code to the parsed file that implements the verb concerned. The same is true with a custom verb.

Custom verbs now execute twice - just like custom tags in ColdFusion when you specify a closing slash or an end tag - with an execution mode of "start" at the opening tag and "end" at the closing tag. A Fusebox 5 custom verb implementation file therefore typically looks like this:

You add CFML code to the parsed file primarily by calling fb_appendLine() as follows:

This adds the CFML line to the parsed file, to be executed at runtime. It's important to remember that custom verbs execute at compile time, i.e., when a circuit.xml file is loaded and parsed, but the code that the verbs generate is executed at runtime, i.e., on all requests.

PHP Fusebox 5 has the same functionality in custom verbs, and the syntax from above is essential identical:

The only "gotcha" is when actually writing to the parsed fuseaction file, you have to make sure you prefix the string functions with $this:

You can also specify custom attributes on <fuseaction> tags (and <circuit> tags) using the XML namespace notation:

A plugin (or custom verb) can then call getCustomAttributes("prefix") on the fuseaction or circuit object to retrieve a struct containing any matching attributes. The assumption is that you will generally have custom verbs associated with the prefix / path. Using custom attributes like this is the recommended way to extend the grammar in Fusebox 5 and ensures that you will not conflict with any future built-in attributes.

You can also specify custom attributes on <class> declarations in fusebox.xml, and the <fusebox> tag itself, if you declare the XML namespace on the <fusebox> tag. Again, getCustomAttributes("prefix") can be called on the class object or Fusebox application object to retrieve any matching attributes.

Built-in Verbs

It is worth noting that built-in verbs are also implemented as a custom lexicon. Built-in verbs exist in a reserved namespace called $fusebox. They are invoked without a prefix. In all other respects, they are just like user-defined custom lexicon verbs. Note that the verbs <do> and <fuseaction> are handled inside the framework and do not exist as external verbs (because they require framework 'magic' to accomplish their tasks: they are really compiler directives, rather than actual verbs).

Writing Custom Verbs

Fusebox 5 verbs behave somewhat like custom tags. They have an execution mode (start, inactive, end) accessible through the fb_.verbInfo structure. That structure has the following members:

  • lexicon - the prefix for the namespace (in Fusebox 4.1 this was the lexicon name)
  • lexiconVerb - the actual verb being invoked (same as Fusebox 4.1)
  • attributes - the struct containing attributes provided in the verb invocation (same as Fusebox 4.1)
  • circuit - the alias of the circuit in which this verb is being invoked
  • fuseaction - the name of the fuseaction in which this verb is being invoked
  • action - the object that represents the current fuseaction (see fuseboxAction below)
  • hasChildren - true if there is are other verbs nested within this invocation
  • skipBody - if the verb sets this to true in start mode, no nested (child) verbs are executed (but this verb will still execute in end mode)
  • executionMode - "start" / "end" / "inactive"
  • parent - present if this verb is nested inside another verb (parent is a reference to the verbInfo structure of that enclosing verb, therefore parent.executionMode will be "inactive")

As indicated above, custom verbs are typically written in CFscript and always follow this form:

A custom verb has access to a locally declared struct called fb_ but in reality the only useful content is in fb_.verbInfo. However, a custom verb can use the fb_ struct to store temporary local variables that exist for the execution of the verb (including its children). This allows a custom verb to set up some data in start mode that is accessible in end mode, directly in the fb_ structure. That data is not accessible to any children of that verb. A custom verb may also store additional data inside the fb_.verbInfo structure, which is accessible to any children of that verb, as the fb_.verbInfo.parent structure. In this way, custom verbs have both a private data area and a public data area, allowing quite a bit of flexibility.

In addition, custom verbs have access to the following methods for writing to the parsed file:
fb_appendLine(lineContent) - write the specified line to the parsed file, followed by a newline (the lineContent should not include a newline).

  • fb_appendSegment(segmentContent) - write the specified text to the parsed file (without a newline).
  • fb_appendNewline() - write just a newline to the parsed file.
  • fb_throw(type,message,detail) - throw the specified exception.

Remember that PHP Fusebox requires that you prepend these functions with $this->, such as $this->fb_appendLine(lineContent), or $this->fb_throw(type,message,detail)

There are other fb_*() methods provided primarily for backward compatibility that deal with indentation but those are not officially supported in Fusebox 5 and may be deprecated in a future release.

In ColdFusion, to access the current circuit's object within a verb, use fb_.verbInfo.action.getCircuit(). To access the application object (and, hence, any fusebox.xml parameter values), use fb_.verbInfo.action.getCircuit().getApplication().

If you're writing your application in PHP5, you can express the above in essentially the same fashion. To access the current circuit's object within a verb, use $cir =& $fb_[ 'verbInfo' ][ 'action ']>getCircuit(). To access the application object use $app =& $fb_[ 'verbInfo' ][ 'action' ]>getCircuit()->getApplication(). PHP4 doesn't support method chaining so you'd need to create an intermediate object in order to access the application object. Note the use of a reference to the objects in order to ensure the variables stay current through the course of the request.

It's definitely worth looking at the source of both the built-in verbs and the skeleton application's custom verbs for ideas on how to write your own custom verbs. In particular, the argument / instantiate / invoke group of verbs and the include / parameter pair of verbs show how parent and child verbs can communicate using the fb_.verbInfo structure.

Example verbs

In order to show how easy it is to create custom verbs here are a couple of simple but useful examples of verbs that implement standard ColdFusion Features that are not present in standard Fusebox 5.

<cf:abort>

<cf:dump>

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.