Table of Contents

1. Introduction
I. Getting Started
2. Installing Recess
Requirements
Downloading & Installing Recess
Installing to Lighttpd
Recess Release Log
3. The Structure of Recess Applications
4. Hello World
Starting an Application with Recess Tools
Creating a New Application Manually
The Controller & View
Routing
The Request Object
The Controller-View Relationship
The Response
The urlTo Helper
II. Writing a Recess Application
5. The Project
III. The Recess Framework
6. Recess Core
recess.lang as a language extensions to PHP
The Library Class & Autoloader
The Object Class
Hooks in Object while expanding Annotations and shaping ClassDescriptor
Attached Methods
!Wrappable Methods and the IWrapper Interface
The Mechanics of Wrapped Methods and Wrappers
Combining Method Wrappers with IWrapper's combine method
Using the !Before and !After Annotations
Annotations
Authoring an Annotation
7. Recess Framework
8. Routing Requests
Simple Routing Techniques
What is routing?
Parametric Routes
Multiple Routes per Method
Keeping it DRY
Advanced Routing Techniques
HTTP METHOD Aware Routes for RESTful Routing
Relative Routes
Implicit Routes
Recess Tools & Routing
Routing Performance
9. The Recess Controller
10. Views and Templates
A Leading Example
Fundamental Concepts
Registering & Selecting Views
View
Templates
Assertive Templates
Helpers
Views by Example with Layouts
Views
AbstractView
NativeView
LayoutsView
JsonView
Implementing Custom Views
View Helpers
Loading with View's loadHelper
Html
Url
Layout
Part
Buffer
Blocks
Abstract Block
HtmlBlock
PartBlock
11. View Helpers
12. Models
Generating Models with Recess Tools
Querying Models
Persisting Model state with insert , update , save , delete
13. Relationships Between Models
A Preview
Relationships
Naming Conventions
Model to Table
!BelongsTo Relationship
!HasMany Relationship
!HasMany, Through Relationship
14. Plugins & Extensibility
15. RESTful APIs in Recess
IV. Deploying Recess Applications
16. Deploying Applications
17. Production Mode
V. Contributing to Recess
18. Forking on GitHub
Working with Recess as a Git Submodule
19. Setting up PHPUnit for Recess
20. Useful Git Commands
21. Submitting Bug Reports
22. Contributing to Documentation
Index

Let's create a simple, new application manually with the automated Wizard in Recess Tools, and then we'll walk through step-by-step what this wizard has done to set up a new application.

The New App Wizard in Recess Tools

To stay true to programming pedagogy let's create a "Hello World!" application.

Lets open up Recess Tools in a browser by navigating to the directory you installed recess to, /recess. This is probably http://localhost/recess/


The wizard kicks off by asking us for two names, first a human readable name. This is used by Recess Tools to identify the application. We'll name this application simply "Hello World". The programmatic name is what the wizard will use when generating the Application class and directory structure. The programmatic name should not have spaces and should be a valid PHP identifier, like HelloWorld.


Next we'll select a URL prefix for the application. A URL prefix determines how Recess will map a request URL to your application. Recess Tools, for example, has the prefix recess/. For hello world lets use helloWorld/.


At this point the wizard will generate a directory structure and some files that form the skeleton of an application. We will walk through what the wizard generates in detail in the following section. Let's keep going through the wizard which is asking us to place a string into the RecessConf::$applications array. The string 'helloWorld.HelloWorldApplication' references the HelloWorldApplication class which the wizard generated which is located in the apps/helloWorld directory.


Open your recess-conf.php file and find the RecessConf::$applications array. Add the line to the array as instructed. This array of strings tells Recess which applications are installed. Your recess-conf.php file should look like this:


After saving the recess-conf.php file we have finished installing our 'Hello World' application. By navigating to 'Apps' we'll see our application 'Hello World' installed on the list of applications. Go ahead and follow the link.


When viewing an application in Recess Tools we can see the Models, Controllers, Views, and Routes. Note the new application wizard created a HelloWorldHome controller for us.


The routes section shows us which URLs our application will respond to and which method in a controller is being mapped. We can see the url helloWorld/ will call the index method in our HelloWorldHomeController class. In a new tab try navigating to the location you installed Recess followed by /helloWorld/ (probably http://localhost/helloWorld/). You should be greeted with the default new application landing page:


We've now got a simple hello world application. In the next sections we'll explore what's going on in the Controller and View which the wizard generated.

Note: This Section is Details Oriented

This section describes the files that Recess Tools will create automatically when starting an application. You can safely skip this section if you are not interested in those details right now.

Behind the scenes of the new application wizard a couple of steps happen to kick off a new application. There's nothing to stop developers from doing this manually should the need arise.

The first step is creating the application directory structure. After installing Recess open up the 'apps' directory. Create a new sub-directory with a name for your application like 'helloWorld'. Directories in Recess are typically named using the camelCaseConvention.

Now create the following 'views' and 'controllers' sub-directories so your structure looks like this:

  • apps/

    • helloWorld/

      • models/

      • views/

      • controllers/

After creating the directory structure, the next step is creating a sub-class of Application. This class holds settings specific to the application such as the location of views in the directory structure and the prefix of models and controllers in the class path. In the apps/helloWorld/ directory create a new file named HelloWorldApplication.class.php. The '.class.php' extension is an important distinction for the Recess Library to know the file contains a PHP class named HelloWorldApplication. The class should be specified as follows:


Now that the HelloWorldApplication class is setup our last step is to 'install' the application into the recess-conf.php file. Within recess-conf.php there is an array of strings named RecessConf::$applications. These strings point to application classes in the class path. The apps folder is in the Library's class path so we can reference the newly created HelloWorldApplication using 'helloWorld.HelloWorldApplication'. If we were to put the HelloWorldApplication class in a subdirectory called app within the helloWorld subdirectory the fully-qualified class name would be helloWorld.app.HelloWorldApplication. The convention of single classes per file and directories being broken up with dots is an influence from Java/C# namespacing. Library is covered in later documentation.

In Recess a is an object responsible for taking a web request, invoking the intended logic in a Model, and then selecting a View which will generate the response, likely in HTML, to be sent back to the client.

Having kicked-off a HelloWorldApplication in Recess Tools, let's take a quick look at some basic concepts.

In an apps/helloWorld directory there is a subdirectory controllers where Controllers are placed. Creating a new controller involves creating a new PHP file containing a class which extends Controller. Here is an example:


The file will be named HelloWorldController.class.php. The .class.php extension is important in Recess because it implies to the Recess Library that the file has only classes defined in it.

Let's add some functionality to the controller. We will begin by adding a simple method to print 'Hello World' and exit.


If we now navigate to helloWorld/printIt we will see 'Hello World!' printed. How did the request for helloWorld/printIt wind up getting mapped to the printIt method? This process is called Routing.

A Controller is responsible for indicating which view template to use. If no response is returned from a controller method the default view template will be nameOfTheControllerMethod.php in the views/ directory. Try removing the body of the printIt method and refresh to get an error indicating no view template at helloWorld/views/printIt.php can be found. To change the view template file we can use the ok helper method.


After refreshing the error message will change to indicate the new location helloWorld/views/the-view.php. The ok helper method will be discussed soon. Let's create a new file named the-view.php with the content below and save it into the views folder:


Try refreshing, you should see 'Hello World!'. Lets pass some variables from the Controller to the View Template.



Refresh to see 'Hello World!' printed 10 times. How do those variables propagate to the view template? The public instance variables in a controller are copied into the Response object which gets passed to a View, the View then sets those variables in the context of the view template. This process is vaguely similar to the Memento design pattern.

When writing view templates a great trick to quickly see what variables are available is to force an error in the view and look at the Recess Diagnostics screen. Try replacing the for loop in your view template with this code:


This will trigger an undefined variable error in PHP that will bring up Recess Diagnostics. On the Diagnostics screen there is a 'Context' table that shows all of the variables available in the local context. Here we can see $message and $repeat set as well as some other variables, one of which is the Response object.

Controller methods are allowed to return either nothing at all or a Response object. When a controller method does not return anything Recess assumes an OkResponse is intended with a view template that has the same name as the controller method. The 'Ok' prefix of OkResponse corresponds to the HTTP 200 OK response code. A Recess Response object contains the information Recess needs to respond to a request including: the response code, data to be passed to the view, headers to be sent back, cookies, a reference to the request, and some additional meta data used by Recess.

In the base AbstractController class there are a number of helper methods which will import and instantiate a response for you. The ok method is an example of a helper method which returns an OkResponse. Other helpers include: conflict, redirect, forwardOk, forwardNotFound, created, and unauthorized. The forwarding responses are a special kind of Response.

A ForwardingResponse causes Recess to handle another request and sends the body of that response to the client. For example, imagine you would like to build a PHP REST interface for creating Posts. After creating a Post you would like to send a 201 CREATED response that contains a Location header informing the client where to find that resource. For web browsers you likely want to send back meaningful content, perhaps the new list of Posts. In Recess this would look like:


The important line is $this->created('/post/' . $post->id, '/posts'); The created helper method takes two arguments, the first is the URL to the created resource that will be sent in the Location header, the second is the URL to the 'content' to respond with. In this case the REST resource created is at /posts/$id but the response will render the HTML for the list of all posts at /posts.

Introducing dependencies on specific URLs in your controllers (and views!) is a bad practice because these URLs may change due to refactoring. Recess decouples this knowledge by providing a helper method that returns the URL to a controller method. Lets take another stab at the PostsController using urlTo.


The urlTo helper method will return the URL which maps to the controller method passed as an argument. Notice that methods which take parameters must be passed the parameters as subsequent arguments as shown in urlTo('showPosts', $post->id). Now if we change URLs using the relative routing techniques shown in the Routing Screencast we do not have to find all of the points where that URL was referenced. Also, if the name of a method changes and urlTo('thatMethod') is called Recess will throw an error which simplifies debugging.

Controllers in Recess simplify the process of accepting a request, delegating to application logic in Models, and passing off responsibility for responding to a view all in a RESTful manner. The conventions of selecting a view name based on the controller method name and returning a 200 OK response by default can be overriden with ease using helper methods. Finally, the urlTo method helps keep controllers and views DRY.

The Library class' purpose is to simplify the inclusion of dependencies between classes. Under the covers Library uses an autoloading mechanism and some other techniques to ensure high-performance in applications that use Recess Core's functionalities. These caching and script compilation techniques will be discussed in-depth later.

Library's most useful static methods are addClassPath and import. Library maintains a list of directories it attempts to find an imported class in. The exact location of imported class files can be cached by Library to avoid hitting disk multiple times to locate single files. The order in which paths are added to Library using addClassPath is important. When attempting to import a class paths are checked from the most-recently added to the least-recently added using addClassPath. The Recess Framework uses this mechanism to allow classes defined in plugins/ to take precedence over recess/, and classes in apps/ to take precedence over plugins/.

Library's import style is inspired by Java/C# imports and is a stylistic difference from libraries like the Zend Framework. Suppose the following directory structure:

/public_html
   /foo
       ClassA.class.php
       /bar
           ClassB.class.php

These classes can be imported using Library with the following snippet of PHP:


If you ever need to use use Library and Recess classes in PHP files outside of the Recess Framework it requires setting up some environment variables and using include on Library directly. The following snippet can be placed into a php script and included by plain-old PHP files.


These directory paths may need to be tweaked depending on where you've extracted the Recess distribution. Explanations for each of these environment variables follows:

$_ENV['dir.bootstrap'] - The absolute directory that contains the bootstrap file. This is a helper variable that simplifies defining the other environment directories by reference.

$_ENV['dir.recess'] - The base directory for Recess' source files. This directory should contain two subdirectories: recess/ and test/.

$_ENV['dir.temp'] - A directory that is writable by PHP scripts. This directory is used by Recess to store temporary data such as cached data structures or compiled scripts.

$_ENV['url.base'] - This is the base URL path that relative URLs should be constructed from. Outside of the Recess Framework this is less meaningful. Recess uses it for mapping routes, and generating URLs in view helpers.

Object is the base class for extensible classes in the Recess. Object introduces a standard for building a class descriptor through reflection and the realization of Recess Annotations. Object also introduces the ability to attach methods to a class at run-time and create wrappable methods.

Object is the superclass for the major components of Recess: Models, Controllers, and Views. The two most common types of classes created when using the Recess Framework are Models and Controllers. There is nothing prohibiting developers from extending Object in their own custom classes. In fact, if you are a developer feeling particularly ambitious and needing to roll a mini-framework with a different composition than Recess, starting with Object and other primitives like Library defined in Recess Core may make your job much more pleasant!

A primary purpose of any framework is to remove boilerplate code whereever possible. Object-oriented (OO) languages provide different means for removing code-duplication. The most commonly used techniques in well-known OO languages of Java and C++ are inheritance and composition. PHP has support for these common techniques and Recess makes use of them wherever possible. Other languages that support object-oriented programming like SmallTalk, Scala, and Ruby go beyond composition and inheritance and allow modules or traits to attach new units of functionality to class definitions (like properties and methods) dynamically. Recess Core provides a systematic way for simulating similar language features and allows for methods to be attached to classes that extend Object at run-time. This technique in combination with annotations is how the Recess ORM provides methods to access relationships, for example. Further discussion of attached methods see the section called “Attached Methods”.

Another form of extensibility in Recess that draws inspiration from a more sophisticated Aspect-Oriented Programming and the 'similar in spirit' Decorator OO pattern are wrappable methods. Classes extending Object can declare a method to be !Wrappable. Once wrappable, other classes implementing the IWrapper interface can dynamically wrap functionality around calls to the method. Key methods in the framework, like Controller's serve and Model's insert, update, delete, are wrappable. Why is this useful? It allows user-defined functionality to inject behavior just before or just after core framework method calls in a simple, standard way. For example, validations on a Model may take place just before insert or update, using wrappable methods the validation system does not need to be closely coupled to the Model class. Similarly with Controllers, authentication could happen before serve is called and the wrapping authentication class can subvert a request by redirecting to a login page. Further discussion on wrappable methods see the section called “!Wrappable Methods and the IWrapper Interface”

The final major unit of functionality exposed in Object is a system for realizing Recess Annotations. Annotations give programmers the ability to work in a more declarative, meta-programming style. What does this mean? Rather than telling PHP how to do something, you tell Recess what you want with an annotation and it is then up to Recess and the annotation's class to expand your declarative statement into PHP. Annotations can be written on three PHP constructs: classes, methods, and properties. Because PHP does not have first-class support for annotations, Recess Annotations are placed inside of doccomments, comments that begin with /**, which are a first-class construct in PHP available through PHP's Reflection API. Annotations often make use of attached and wrappable methods to inject units of functionality. For further discussion on annotations see the section called “Annotations”

Underlying attached methods, wrappable methods, and annotations is fundamental data structure, the ClassDescriptor. The ClassDescriptor is where the information used to describe Recess' language features like attached methods are stored. There is one ClassDescriptor per class and, when Recess is running in production mode, this data-structure is computed once and cached. Sub-classes of Object can use the class descriptor as a store for computed data structures by overriding hooks in the Object class. For example, Model uses this cache to hold database information and the meta-data for relationships, and Controller uses it to store routing information. Annotations expand to 'shape' a class's ClassDescriptor. The following section describes the hooks available to sub-classes of Object for shaping class descriptors.

Initialize Class Descriptor - A class's descriptor may need to initialize certain properties. For example Model's descriptor has default properties initialized for database table based on convention by the name of the class, primary key, etc.

protected static function initClassDescriptor($class) - Parameters: $class is the class' name as a string. Returns a ClassDescriptor.

Shape Descriptor with Method - Prior to expanding the annotations for a class method this hook is called to give a subclass an opportunity to manipulate its descriptor. For example Controller uses this in able to create default routes for methods which do not have explicit Route annotations.

protected static function shapeDescriptorWithMethod($class, $method, $descriptor, $annotations)- Parameters: $class string name of class whose descriptor is being initialized. $method is of type ReflectionMethod. $descriptor is the ClassDescriptor. $annotations is an array of Annotations found on method. Returns a ClassDescriptor.

Shape Descriptor with Property - Prior to expanding the annotations for a class property this hook is called to give a subclass an opportunity to manipulate its class descriptor. For example Model uses this to initialize the datastructure for a property before a !Column annotation applies metadata.

protected static function shapeDescriptorWithProperty($class, $property, $descriptor, $annotations) - Parameters: $class string name of class whose descriptor is being initialized. $property is of type ReflectionProperty. $descriptor is the ClassDescriptor. $annotations is an array of Annotations found on property. Returns a ClassDescriptor.

Finalize Class Descriptor - After all methods and properties of a class have been visited and annotations expanded this hook provides a sub-class a final opportunity to do post-processing and sanitization. For example, Model uses this hook to ensure consistency between Model's descriptor and the actual database table's columns.

protected static function finalClassDescriptor($class, $descriptor) - Parameters: $class is the class' name as a string. $descriptor is the ClassDescriptor after all properties and methods have been visited. Returns a ClassDescriptor.

Sub-classes of Object allow you to attach methods to a class dynamically at run-time. Once a method has been attached all instances of that class in existance, or instantiated thereafter, will have the method available. Attached methods also show up with reflection when using the RecessReflectionClass. Example usages of attached methods are: the implementation of relationship methods on models, and wrappable methods. To attach a method to a class you must first define the target method on another class. The following detailed example demonstrates attaching a method to a class.


1

The class we will attach a method to is MyRecessObject, it is important that it extends Recess' Object class.

2

The class AttachedBehavior contains the method we will attach to MyRecessObject: targetMethod. Attached methods must be defined within a class because attaching requires an instance of the class as well as the method name.

3

Notice that attached methods always take an instance of the class they are attached to as their first parameter. Subsequent parameters are the parameters to be passed by the attached method's call (6).

4

We've created an instance of the AttachedBehavior class and given it some state. The ability to provide the method with some context is key to being able to do interesting things with attached methods on a class-by-class basis. For example, when a !HasMany or !BelongsTo annotation expands it attaches multiple methods to the class the annotation is defined on. Each of these target methods are defined on an instance of HasManyRelationship or BelongsToRelationship that have additional state, such as the relationship name, related table, foreign key, etc, that are vital state for the attached methods. One way to think of this is a poor man's closure.

5

The call to the static method attachMethod is where the magic mapping happens. Object defines attachedMethod which has four parameters. The first is an unfortunate one: the string classname the method is being attached to[1]. The second parameter is the name we are assigning to the new method on our class. So, in this example the method's name will be attachedMethod(). Next we provide the target the attached method will call. We specify this by passing an instance of an object, and the string name of the method being attached.

6

We can now call attachedMethod on an instance of MyRecessObject and it will map to targetMethod on our AttachedBehavior instance.

Underneath the covers there is some simple indirection taking place in Object's __call method that maps the attached method call to the target method based on entries in the ClassDescriptor. If methods are attached during the process which sub-classes of Object expand annotations and build-up ClassDescriptors then the target instance, its state, and the mapping will be automatically cached in production mode. For more information on ClassDescriptor, see the section called “Hooks in Object while expanding Annotations and shaping ClassDescriptor

Wrappable methods are special methods on an Object class whose invocations be dynamically 'wrapped' with new behavior before and/or after the invocation of the wrapped method. For Python coders method wrappers are similar to method decorators, for Aspect-Oriented folks this is a poor man's join-point, for everyone else wrappable methods are a flexible extensibility point where you can flexibly inject new behavior.

Consider inheritance in traditional object-oriented programming. By overriding a method in a sub-class you can effectively wrap behavior around the parent class' method call. Here is some example code:


1

MyBaseClass defines a method foo that will be 'wrapped' using inheritance.

2

foo is overridden by MySubClass and first echos a message.

3

Now, we call the 'wrapped', or in this case overridden, parent class' foo method.

4

Finally, let's print an after message once the call to MyBaseClass' foo has returned.

In this simple example we've effectively wrapped MyBaseClass' foo method with some new behavior: we print 'Before!' and 'After!' foo is called on instances of MySubClass. What is so bad about pure inheritance?

Other languages and programming paradigms have a fairly simple solution to these limitations, as mentioned Python's decorators and AOP's join-points, that Recess looked towards for inspiration. Recess' solution is called 'Wrappable' methods. A !Wrappable method can be wrapped by, (or decorated with), unbounded IWrappers that can be composed dynamically at runtime. Let's take a look at how we could make foo a wrapped method:


1

The !Wrappable annotation can be used on methods to create a 'wrappable' method. Notice that foo follows !Wrappable, this indicates that the wrappable method will be invoked with the name foo.

2

The actual name of the method is wrappedFoo. The only restriction on naming the wrapped method is that it can not have the same name as the wrappable method. By convention Recess prefixes wrapped methods with wrapped. I.E. foo() wraps wrappedFoo()

3

We can now invoke a method foo() on instances of MyBaseClass. Underneath the covers wrappable methods are surfaced using attached methods, for more info on attached methods see the section called “Attached Methods”.

Great! We have a wrappable foo method, now let's wrap it with printing behavior. All we need to do is create a PrintWrapper class that implements the IWrapper interface.


PrintWrapper implements the three methods defined in the IWrapper interface. Let's discuss each:

1

before is called before the wrapped method is called. It is passed a reference to the object the wrappable method has been called on, as well as an array of the arguments passed to the wrappable method. The arguments are passed by reference so that wrappers can transform what is eventually passed to the wrapped method. Not shown here, but if a wrapper's before method returns a non-null value it will short-circuit the call and return the value immediately to the callee without calling the wrapped method.

2

after is called when the wrapped method returns. It is passed a reference to the object the wrappable method has been called on, and the return value of the wrapped method. The value after returns is passed to the calle so after has an opportunity to transform or replace the value returned from the wrapped method.

3

combine is an optimization method that will be discussed shortly.

4

Here we use the static method wrapMethod to wrap a PrintWrapper instance on the wrappable method foo on MyBaseClass.

5

By invoking foo we first work our way through PrintWrapper's before(), then call MyBaseClass' wrappedFoo(), and finally back out to PrintWrapper's after().

6

For the sake of being thorough we show that you can still call wrappedFoo directly. Because wrapped methods are implemented at the Recess Core library level and not directly in PHP there is no way around this.

We now have the same printing behavior as in our Inheritanc example, but without using inheritance. The power and flexibility of wrappable methods and wrappers is that multiple wrappers can wrap a wrappable method. So we could create a logging wrapper that also wraps foo and easily flip either wrapper on or off, dynamically at run-time, without having to reorganize our class hierarchy. For more detail see the section called “The Mechanics of Wrapped Methods and Wrappers”. Lets point out exactly how wrappable methods address the downsides of inheritance:

  • Wrappable methods avoid the inflexibility of inheritance-based overriding because methods can be wrapped dynamically. Wrapping methods with new functionality does not affect the type system or class hierarchy.

  • Wrappable methods encapsulate a behavior around a method call. This presents a new way for PHP programs to package functionality to fight code duplication. To use Aspect-Oriented Programming terminology you could think of wrappers as a means for separating crosscutting concerns. Cross-cutting concerns are tasks like logging/printing debug messages as shown in the example above, authorization and access control, etc.

Given these two specific characteristics wrappable methods and wrappers provide a natural extensibility model. Plugin-developers can implement IWrappers that application-developers can easily incorporate in their projects because there is no need to modify a class heirarchy and the plugin's wrapper behavior is encapsulated in a simple class. For application-developers, instantiating wrappers and applying them with the Object::wrapMethod API can be awkward and cumbersome. This is where Recess Core's annotations come to the rescue, annotations provide the perfect vehicle for making declarative statements about a class or method which then employ wrappers and attached methods to do the leg work under the covers. For more information on annotations, see the section called “Annotations”

Where in the code base are wrapped methods implemented? What is the exact logic for processing methods wrapped with multiple wrappers? The answers to these questions are the focus of this section.

The implementation of wrapped methods can be thought of as a combination of the Observer and Strategy design patterns with specific semantics. Wrappers are observers of wrapped methods who are notified before and after the wrapped method is called. The before and after aren't vanilla notifications, though, and can return values that affect the logic of the call similar to a strategy. The logic of wrapped method invocation is implemented in the recess.lang.WrappedMethod class. The addWrappedMethod in recess.lang.ClassDescriptor brings wrapped methods onto a class' descriptor, and, finally the recess.lang.WrappableAnnotation abstracts away the pattern of making a plain-old class method a wrappable method.

When a wrapped method is invoked, the following process occurs:

  1. Statement S invokes wrapped method M on object O with arguments A*.

  2. Each wrapper's before method is invoked in the reverse order that the wrappers were added[2](LIFO). before is passed, by reference, O and an array of A*. The wrapper, thus, has an opportunity to get or set public state from O or any argument in A*. If a wrapper's before does not return a value or returns the value null then the next wrapper's before is called until all wrapper's before methods have been called. If a wrapper's before returns a non-null value this value does not pass go and does not collect two hundred dollars, it short-circuits the wrapper call-chain and is immediately returned to statement S.

  3. The call to the wrapped method M is made using the (potentially transformed) arguments A*. M returns value R.

  4. Each wrapper's after method is invoked in the order that the wrappers were added (FIFO). after is passed arguments O and R (M's return value). If the call to a wrapper's after returns a non-null value then this return value, R', will override R in the remaining wrapper's calls to after, else R' is set to R.

  5. The value R' is returned to S.

Warning

While nothing will stop you as an IWrapper author from writing the following at design-time, it should be noted that these practices will most likely cause errors and headaches at run-time and are considered really bad practice:

  • In before: changing the types of arguments in A*, or changing the number of arguments in A*. A* must remain such that using its elements to call method M will result in a valid method call with the arguments M expects.

  • In before: returning a value of any type other than M could be expected to return.

  • In after: returning a value R' of any type other than M could be expected to return.

At runtime each wrapper is an instantiated object. In production mode these objects are deserialized on every request. Reducing the number-of wrappers is a boost to performance in time (extra method calls are expensive) and space so Recess gives IWrapper authors a simple way to combine similar wrappers. Imagine you've just created a !Required annotation that application developers can place on properties of a Model to denote they are required for insert and update. Beyind the scenes you've written a RequiredWrapper that takes the name of a property and in the before method checks to make sure the property's value is non-null. Each annotation would thus expand to wrap insert and update with a new instance of RequiredWrapper for every property on the model. That could mean a lot of IWrapper objects to call before and after on to check requiredness! (It would also mean you couldn't check more than one field for requiredness because of short-circuit returns!)

When wrappers are applied to a WrappedMethod using addWrapper the WrappedMethod first iterates through each of the existing wrappers and calls their combine method, passing in the new wrapper. If the existing wrapper determines it can combine its state with the new wrapper's state it will do so and return true which indicates to the WrappedMethod "do not add this new wrapper to your list, I've taken on its duties". If all existing wrapper's combine method returns false the new wrapper will be added to the list of registered wrappers. Let's take a look at an example:


1

We'll store the list of required property names in $this->properties.

2

Here we short-circuit return false, so that the wrapped method will not get called. In this naive wrapper we're simply printing the error message in code.

3

Returning null is not necessary, it is the same as not returning, shown to illustrate that if all required fields are non-null the call will pass through to the wrapped call just fine.

4

Here we combine the state of two RequiredWrappers after checking for type sameness.

5

If we can combine we return true, and $that is not added to the list of wrappers because we have combined its state with $this.

6

If we cannot combine we return false.

The result of this code is that there will be two RequiredWrapper instances, one for insert and the other for update. The RequiredWrapper for insert will contain two properties in its $properties array. It is important to note that new instances of wrappers should be wrapped for each method, for example, if the same instance of a new RequiredWrapper('fieldB') had been wrapped around insert and update then fieldA would be required for update as well because of combine. (Note: This doesn't pass the sniff test and exposes too much guts. Maybe we could change the implementation of addWrapper in WrappedMethod to clone the Wrapper before adding it.)

Annotations can be introduced by extending the abstract class recess.lang.Annotation. User defined annotation classes must end in the word 'Annotation'. For example: to have a !Protected annotation the classname must be ProtectedAnnotation. There are four abstract methods which must be implemented by custom annotations: usage, isFor, validate, and expand. These methods are used by the framework to make working with user-defined annotations feel like a first-class PHP construct. Following are descriptions of the purpose for each annotation:

usage - Returns a string representation of the intended usage of an annotation.

isFor - Returns an integer representation of the type(s) of PHP language constructs the annotation is applicable to. Use the Annotation::FOR_* consts to return the desired result.


validate($class) - Validate is called just before expansion. Because there may be multiple constraints of an annotation the implementation of validate should append any error messages to the protected $errors property. Commonly used validations helper methods are provided as protected methods on the Annotation class.

expand($class, $reflection, $descriptor) - The expansion step of an annotation gives it an opportunity to manipulate a class' descriptor by introducing additional metadata, attach methods, and wrap methods. Parameters: $class the classname the annotation is applied to. $reflection The PHP Reflection(Class|Method|Property) object the annotation is located on. $descriptor is the ClassDescriptor that the annotation is being expanded on.

The power of annotations comes in the expand step. An annotation can modify a class' descriptor which allows for methods to be attached to a class and available on all instances of a class, as well as "wrap" methods of a class marked as !Wrappable

To demonstrate authoring a custom annotation, let's create an annotation for methods on a Controller that should be protected by a protected cookie key of "secret" and value of "password". Our goal is to be able to place !CookieProtected on a method in a controller and redirect users to an optionally specified path (else, "/") if they do not have the necessary cookie. We'll craft the annotation in two-steps, first we'll implement the abstract methods of Annotation, then we'll take combine the annotation with the previously discussed WrappedMethods to finish off the functionality of the CookieProtectedAnnotation by wrapping a Controller's serve method.


The full list of helper methods for validate is: acceptedKeys, requiredKeys, acceptedKeylessValues, acceptedIndexedValues, acceptedValuesForKey, acceptsNoKeylessValues, acceptsNoKeyedValues, validOnSubclassesOf, minimumParameterCount, maximumParameterCount, exactParameterCount. To understand the meaning of 'keys', 'indexed values', 'keyless values', you must understand the way recess interprets annotations. Recess parses an annotation by doing the following: 1) find an annotation by looking for an !Bang followed by whitespace, "!Bang". 2) Convert everything after the start of an annotation into a parameters array, !Bang foo, key: bar becomes array("foo", "key" => "bar"). 3) Instantiate the class named BangAnnotation and pass the parameters into the BangAnnotationinstance's init method. Thus, every subclass of Annotation has a $parameters property which is this array. The helper methods provide convenient ways of checking the contents of this array during validate.

Once validate has been run, if errors are found in the annotation's $errors property a RecessErrorException is thrown. If no errors are found, then the final step before expand is called is to make all keyed values in the $parameters array properties of the annotation instance and to append all keyless values of $parameters to the $values property. For example, the annotation !Bang foo, Key: bar becomes: $bang = new BangAnnotation(); $bang->init(array('foo', 'Key' => 'bar')); Finally, after Recess calls expandAnnotation (which, in turn, calls your user-defined expand), your expand can reference $this->values[0] to find 'foo' and $this->key to get 'bar'.



[1] This parameter a result of PHP < 5.3's lack of late static binding. Even though the static method is invoked on the class we are attempting to attach the method to, MyRecessObject, until PHP 5.3 there is no means for determining the sub-class it was called on. After PHP5.3 this limitation has been fixed.

[2] IWrapper implementations must not depend on the order in which they are applied to a wrappable method.

Your controller has done all the heavy lifting and taken care of the "business logic", now it's time to get back to your client with a meaningful response. Where controllers are all about serving the client by doing and fetching, views are all about responding by presenting and rendering.

How you actually respond likely depends on: 1) what the HTTP client asks for "I want /person/1 in JSON", "Ok, the controller gave me the data for Person 1, here it is in JSON", and 2) the best way for you to get the job done: maybe it's using Smarty templates, maybe it's an automatic response, or maybe it's plain old PHP.

This brings us to the design goals of Recess' View system, which have been revamped in 0.20:

Before diving into specifics let's take a leading example of creating the view components for a hypothetical listing of blog posts. Suppose we have a Post model that has properties: title, author, and body. Our controller code will look like this:


We'll get into the details of the relevant annotations later, for now just take our word that the view class rendering the response will be LayoutsView, and it will be looking for the view template post/index.html.php found in the apps/[appname]/views/ sub-directory. The variable $postSet will be available to this template which represents a set of Post models.

Our first-pass, naive template implementation of post/index.html.php may look like this:


This works, but as our application grows in complexity we will want to remove redundant HTML to layouts shared by many views. Let's try creating a layout that this simple view can extend to remove common HTML.



As you can see, we've extracted the redundant HTML to a master layout. You'll notice that the master layout specifies its inputs. The child/parent templates do not share scope, the parent must define which inputs it requires and the type the variable should be. This improves predictability because you know exactly what variables a parent layout is expecting. If your child template fails to provide a variable required by the parent you will get a simple error message notifying you of the problem instead of an obscure 'variable not defined' message from somewhere deep in the parent template.

Unfortunately, our listing template has regressed. Storing the output of the list of posts in a string is painful. This is where Buffer'ing and Block save the day! Buffer is a class that uses PHP's output buffering to fill Blocks. The buffer fills a block. Let's take a look:


Now we don't have to worry about string concatenation, we let Buffer fill our $body Block. If we were to run this code we would get a type check error in the master layout: $body is expected to be a string, but now it is an instance of HtmlBlock which is a sub-class of Block. Why not just have Buffer fill strings? Shortly we'll see how Block's type-hierarchy enables really powerful features. The immediate benefit, though, is that it allows layouts to specify they are expecting a block of HTML, not just a string. Let's update our master layout.


Easy enough! Notice all we needed to change was the expected type on the input. We can echo a Block instance just like we can a string. Imagine we had some other places in our application where we'd really like to print out the list-item format of a Post. Enter: Parts to save the day! Parts are kind of like partial templates you may have used in other frameworks. Let's take a look at how we would define a part for post.


Notice the similarity with a layout: parts and layouts define their inputs. The term we coined for this style of a template is an Assertive Template. By being assertive about the inputs a template expects we can make working with these templates much more pleasant. Let's take a look at how we would use this part in post/index.html.php.


We can 'draw' a Part by passing the path to the part in the views directory, minus '.part.php', and the rest of the inputs in the order specified by the part. You pass a part inputs just like you call a function with arguments. Notice that the name of the variable passed to draw and the name of the input do not have to match, again, like functions. This is contrasted by most PHP partial libraries that would require calling the template with an array like array('aPost' => $post).

You'll also notice we're no longer buffering $body. But the code still works! What's going on? By default, if your child template does not specify a $body block, any output will automatically create a Block named $body that will be passed to its parent layout.

Let's say we wanted to make it possible to append another class to the post/li part. We can create an additional input that is optional by passing a third argument to Part::input which is the default value of an input.


Now, by default, the only class will be 'post', but others could be appended by passing an additional input to the part. Let's go back to our post/index.html.php template and make the additional class name of 'odd' be appended to every other item in our list. This way we can style every other post differently using CSS.


You can see by passing an additional input to post/li we are now appending the 'odd' class to odd posts. Suppose that throughout our project we use this even/odd classname technique in a number of places. Could we do any better and eliminate this redundancy? Yes, we can! We'll simply create a part for it.

Now, take a deep breath and hold on. Here comes the sexy stuff that makes our parts different from everyone else's partials. Earlier we alluded to there being some 'power' in passing around instances of Block instead of strings. You saw an example of how Buffer filled an HtmlBlock. There is a special Block for Parts, too, called PartBlock. Before we summon a PartBlock, though, let's first create the higher-order part that abstracts toggling between two blocks.


There are two interesting things going on here. First, notice that we're passing in two Block instances named $even and $odd. Second, notice that we're using the draw method of Block. Every Block has two methods: __tostring and draw. For an HtmlBlock created using Buffer, draw doesn't take any arguments (but won't complain if you give them). For a PartBlock, though, passing arguments to draw will apply those arguments where you left off in creating the PartBlock. Well, then, how do you create a PartBlock?


So, by using the block method instead of draw, the method returns a PartBlock with the parameters you've passed stored. You can think of this like currying in functional languages like Scala / OCaml. For the astute reader you'll notice we have a problem on our hands, though. In order to use our 'each-toggle' part $post must be the final argument passed to draw. We can solve this in one of two ways, first we could do the obvious and re-order the inputs so that our 'post/li' is passed a class string first and a Post second. That makes things ugly, though, because we really want class to be an optional parameter. Recess has a mechanism for assigning optional arguments to a PartBlock after it has been created. Let's take another look.


This style of assignment is inspired by the jQuery library and uses method chaining to make it easier to specify multiple optional arguments. Notice that the 'class' method corresponds to the $class input of the 'post/li' part. Now we're finally equipt to use our higher-order 'each-toggle' template! Let's take a look:


Voila! Simple and beautiful. If we wanted to be really pedantic we could even make a part for a list of posts. In this case it's a little excessive, but let's do it just to demonstrate how parts can be composed. Let's start with the code we'd like to end up with in post/index.html.php template and design the part from it.



This wraps up our leading tutorial of the new view system in Recess 0.2! Blocks, Parts, and Layouts are the keywords. Blocks are chunks of HTML that haven't been rendered yet and can be static with HtmlBlock or wrap around parts with PartBlock. Layouts are advanced includes that safely transfer variables from a child template to a parent layout. This is possible because parent layouts specify their inputs. Parts, kind of like partials, also specify their inputs. Parts and Layouts are considered to be Assertive Templates for this reason. Parts can become blocks, kind of like functions can become lambdas, to enable powerful higher-order part templating.

If you've programmed presentation logic in a PHP application you've likely dealt with include a good amount. When designing applications that have common UI it is a good practice to extract common parts of the UI to their own script files. The problem with simple includes is that they share scope. This makes includes difficult to reason about, shown in the following example, even if you know yourguess.php isn't going to halt, you don't know whether "Hello World?" will get printed, or some other string, or perhaps a notice error that temp is not defined:


Using includes can lead to spaghetti-code where you must understand the entirety of every include before you can understand a single script that uses includes. Included files which expect certain variables to be available (perhaps $title is used to fill in the <title> tag) require the includee to wade through the script and determine which variables to have available in the context. For these reasons Recess, as of version 0.20 encourages not using includes in your templates and instead using Assertive Templates.

Assertive templates are a name given to a certain style of template: one that asserts the presence and type of every input variable at the top of the script. Here is an example:


Layouts and Parts use Assertive Templates to address the problem to make presentation logic more predictable. Here is a similar snippet to the first example using the Part helper:


Views have two fundamental jobs:

The Recess Framework includes a web app to aid development called 'Recess Tools'. Generating new Models for an application and creating corresponding tables in the database is quick work. By browsing to your application and selecting 'new' Model you'll be taken to the new Model helper. After providing a name, table information, and properties the model and, if needed, table will be generated.

A quick peak at the code generated for Post:


Lots of annotations! Why so many? Being explicit is a good thing- especially when you don't have to do any of the extra writing. Starting from the top: the Database annotation is what allows Recess to have Models from multiple data sources in a single app. The Table annotation is straightforward: the name of the table in the database the Model maps to. Following is a HasMany relationship using a join table with the Through argument. For Rails folks this should look decently familiar. More to come on relationships.

Each property uses a !Column annotation to provide additional semantic typing information. Specifying properties and column mappings is optional in Recess but it is encouraged for three reasons. One, you can look at a Model's code and know exactly which properties are available. This is different from Rails or Cake models. Two, Recess checks to ensure your annotations and the database types match. Three, Recess can regenerate tables from Models marked up with annotations.

In Recess Models use a variation on the ActiveRecord pattern to provide an Object-Relational Mapping facility in the Recess Framework.

The Recess unit tests are written for PHPUnit

In order to run the unit tests for Recess take the following steps:

Figure 19.1. Setting up PHPUnit for Recess

  1. Install PEAR - Typically this is done by executing the go-pear script in your PHP installation directory.

  2. Install PHPUnit

    1. First add the PHPUnit channel to PEAR: pear channel-discover pear.phpunit.de

    2. Next install PHPUnit with pear install phpunit/PHPUnit

  3. Setup MySQL & DSN for Database Tests

    1. The default MySQL test DSN is 'localhost,dbname=recess, user=recess, password=recess'

    2. To use settings other than default modify recess/test/recess/database/PdoDsnSettings.php

  4. At a command prompt, navigate to recess/test/

  5. Run the Unit Tests: phpunit --bootstrap bootstrap.php AllTests.php


To contribute unit tests to Recess fork the source on GitHub, commit your unit tests to the fork, and request a pull from Recess. Happy testing!

A

Application
create manually, Creating a New Application Manually
create with Recess Tools, Starting an Application with Recess Tools
directory structure, The Structure of Recess Applications

C

Controller, The Controller & View
Basics, The Controller & View
Relationship with Views, The Controller-View Relationship
urlTo method, The urlTo Helper

F

ForwardingResponse (see Response)

R

recess-conf.php
RecessConf::$applications, Starting an Application with Recess Tools
Recess Tools, Starting an Application with Recess Tools
Routing, Recess Tools & Routing
Relationships, Relationships Between Models
!BelongsTo (see !BelongsTo)
!HasMany (see !HasMany)
!HasMany, Through (see !HasMany, Through)
Naming Conventions, Naming Conventions
Querying, A Preview
Request Object, The Request Object
Response, The Response
ForwardingResponse, The Response
RouteAnnotation, What is routing?
Routing, Routing Requests
Implicit, Implicit Routes
Mutltiple per method, Multiple Routes per Method
Parameters, Parametric Routes
Parametric, Parametric Routes
Performance, Routing Performance
Relative vs. Absolute, Relative Routes

U

Unit Testing
Recess, Setting up PHPUnit for Recess
urlTo (see Controller)