Modify Views Inherited Views In other frameworks, the controllers are clustered together in one place, the views in another, and the layouts in yet another. In Solar, the views and layouts for a controller are in a subdirectory of that controller class. Solar lets controllers inherit from other controllers; the view and layout scripts are inherited as well. The make-vendor command created Acme_Controller_Page as our base page-controller class, which has a default layout. The Acme_Controller_Bread class inherits from the Page class, and has a series of default views. The Acme_App_Blog class, which we created with make-app using a --model-name=posts option, inherits from the Acme_Controller_Bread class. Override the Default Read View The default "read" view doesn't look very blog-like. Let's create an override to the default view to make it look different. Change to the View directory for our blog controller and create a file called read.php. (In this example we use the vim editor, but you can use anything you like.) $ cd SYSTEM/source/acme/Acme/App/Blog/View $ vim read.php Add the following PHP code to the empty read.php view and save it. escape(ucwords($this->controller)); ?>

escape($this->item->title); ?>

nl2p($this->item->body); ?> action( "{$this->controller}/browse", "ACTION_BROWSE" ); ?> ]]>
Refresh your browser on the Read page, and you will see a much more blog-like view. Why did we have to create a "read.php" view? Where was the view code coming from before we created this file? As noted earlier, Solar controllers inherit their views from their parent classes. Since Acme_App_Blog extends Acme_Controller_Bread, the default view is at SYSTEM/source/acme/Acme/Controller/Bread/View/read.php.
Explanation of the Override Code There's a lot happening in that short piece of code. Here's some explanation of what's going on. The $this variable refers to the Solar_View object inside which the view script is being executed. All public variables from the controller are populated into the view object automatically when the controller reaches its "render" phase. The generic Acme_Controller_Bread class has a property $list for a collection of records and a property $item for an individual record. Thus, in our read.php view, we can access the individual post as $this->item. The columns of the record are themselves accessed as properties of $this->item. In addition to using $this to access properties, you can also use $this to access helper methods. For example, $this->escape() is a helper to prevent cross-site scripting security flaws by escaping output correctly for XHTML. The $this->nl2p() helper converts consecutive newlines into paragraph tags, and escapes the paragraphs for XHTML. The $this->action() helper creates an link to another action in the application, using a locale string key as the text of the link. It too is automatically escaped for you. You can see a list of all the default Solar view helpers in the SYSTEM/source/solar/Solar/View/Helper directory. Override The Default Browse View Let's modify the "Browse" view as well. You should be there already from modifying the "read" view, but if not, change to the View directory for our blog controller. Then create a file called browse.php. $ cd SYSTEM/source/acme/Acme/App/Blog/View $ vim browse.php Add the following PHP code to the empty browse.php view and save it. escape(ucwords($this->controller)); ?>

getText('HEADING_BROWSE'); ?>

list as $item): ?>
getText('TH_ID'); ?> getText('TH_TITLE'); ?> getText('TH_CREATED'); ?> getText('TH_STATUS'); ?> getText('TH_ACTIONS'); ?>
escape($item->title);?> escape($item->title);?> timestamp($item->created); ?> escape($item->status);?> action( "{$this->controller}/read/{$item->id}", "ACTION_READ" ); echo " "; echo $this->action( "{$this->controller}/edit/{$item->id}", "ACTION_EDIT" ); echo " "; echo $this->action( "{$this->controller}/delete/{$item->id}", "ACTION_DELETE" ); ?>
]]>
Refresh your browser on the Browse page, and you will see a listing of blog entries. But wait! The table-heading text looks ugly. This is because we did the right thing and used locale string keys instead of literal text. To correct this, we need to provide translations in the application locale file.