Difference between revisions of "Workshop - week 03"

From mi-linux
Jump to navigationJump to search
Line 5: Line 5:
 
We can think of the [http://framework.zend.com/docs/quickstart/create-a-layout layout page] as a template that defines a consistent look and feel for all pages within the MVC application. The controllers provide views that fill in what is unique about a particular page. Combined together, they provide us with a complete HTML/XHTML page. As the tutorial suggests, this is the reason why the layout is a good place to set up headers and footers that we want to remain the same for all our pages.
 
We can think of the [http://framework.zend.com/docs/quickstart/create-a-layout layout page] as a template that defines a consistent look and feel for all pages within the MVC application. The controllers provide views that fill in what is unique about a particular page. Combined together, they provide us with a complete HTML/XHTML page. As the tutorial suggests, this is the reason why the layout is a good place to set up headers and footers that we want to remain the same for all our pages.
  
===5. Configuration and Registry===
+
You may have noticed that the view scripts in the previous sections were HTML fragments- not complete pages. This is by design; we want our actions to return content only related to the action itself, not the application as a whole.
  
In older web programming methodologies, programmers would often create a file to be 'included' by all pages that needed access to database connections. This had many disadvantages, such as providing all the code for database connectivity often to every page, even when a database connection was not required for the page. There was also the security considerations of having a file with all the database connection details in a location where it may be accessible by anonymous users.
+
Now we must compose that generated content into a full HTML page. We'd also like to have a consistent look and feel for the application. We will use a global site layout to accomplish both of these tasks.
  
A more modern take on the concept is to have a [http://framework.zend.com/docs/quickstart/create-a-configuration-and-registry registry / configuration file], and classes to provide access to the data. It works much like an .ini file for desktop applications - providing a place to store application-wide settings, such as database connection strings. It works much like a hashtable, where data can be retrieved by key name. [http://framework.zend.com/docs/quickstart/create-a-configuration-and-registry We need to create] our app.ini file, and modify the boostrap.php file to include a reference to the app.ini. In the case of our QuickStart application, we will then be able to access the database settings from any page we choose.
+
There are two design patterns that Zend Framework uses to implement layouts: Two Step View and Composite View. Two Step View is usually associated with the Transform View pattern; the basic idea is that your application view creates a representation that is then injected into the master view for final transformation. The Composite View pattern deals with a view made of one or more atomic, application views.
  
===6. Model and Database===
+
In Zend Framework, Zend_Layout combines the ideas behind these patterns. Instead of each action view script needing to include site-wide artifacts, they can simply focus on their own responsibilities.
  
See [http://framework.zend.com/docs/quickstart/create-a-model-and-database-table here].
+
Occasionally, however, you may need application-specific information in your site-wide view script. Fortunately, Zend Framework provides a variety of view placeholders to allow you to provide such information from your action view scripts.
  
====Database====
+
To get started using Zend_Layout, first we need to make some modifications to our bootstrap.php file:
  
=====Database Connection=====
+
<source lang="php">
 +
// application/bootstrap.php
 +
//
 +
// Add the following code prior to the comment marked "Step 5" in
 +
// application/bootstrap.php.
 +
//
 +
// LAYOUT SETUP - Setup the layout component
 +
// The Zend_Layout component implements a composite (or two-step-view) pattern
 +
// With this call we are telling the component where to find the layouts scripts.
 +
Zend_Layout::startMvc(APPLICATION_PATH . '/layouts/scripts');
  
Next, we need somewhere to store our data. We modify the app.ini file to include the database connection details (We are setting up a SQLite database - it is not a database you will necessarily be familiar with. Rather than having a database program running on a server, SQLite can have an entire database stored within a file - like using an XML file, but with all the benefits of SQL queries.)
+
// VIEW SETUP - Initialize properties of the view object
 +
// The Zend_View component is used for rendering views. Here, we grab a "global"
 +
// view instance from the layout object, and specify the doctype we wish to  
 +
// use. In this case, XHTML1 Strict.
 +
$view = Zend_Layout::getMvcInstance()->getView();
 +
$view->doctype('XHTML1_STRICT');
  
We then need to modify the bootstrap.php file, to include the new connection details to the database we are about to create.
+
// CLEANUP - remove items from global scope
 +
// This will clear all our local boostrap variables from the global scope of
 +
// this script (and any scripts that called bootstrap). This will enforce
 +
// object retrieval through the applications's registry.
 +
unset($view);
 +
</source>
  
=====Database Schema=====
+
Calling startMvc() registers a plugin with the front controller, allowing layouts to work seamlessly and without further interaction in most cases. An action helper is registered, as is a view helper, in case you do need to interact with the layout object.
  
We then create two SQL script files - one that defines the structure of the database that we want to set up, and another with some initial test data to be inserted into the new database.
+
Note the call to the doctype() view helper; this is one of the placeholders mentioned above. By setting this in the bootstrap, we can assure that other doctype-aware view helpers know the selected doctype.
  
=====Setup Script=====
+
Now that we've initialized Zend_Layout, let's create our site-wide layout:
  
This PHP file will be run just once, and will create our database by executing the first script, and fill it with data as outlined by our second script. Once scripts/load.sqlite.php has been executed successfully, the file can be deleted - but don't do so until you have a fully working application, in case you need to execute the database setup again.
+
<source lang="php">
 +
<? /* application/layouts/scripts/layout.phtml
  
'''Pro Tip:''' Remember that the directories that the database is being set up within - data/db/ - need to have the correct permissions set. At this stage, CHMOD it to 777 (read, write and execute for all) to help get the application running.
+
      This line outputs the doctype we set in the bootstrap */ ?>
 +
<?= $this->doctype() ?>
 +
<html xmlns="http://www.w3.org/1999/xhtml">
 +
<head> 
 +
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 +
  <title>Zend Framework Quickstart Application</title>
 +
  <?= $this->headLink()->appendStylesheet('/css/global.css') ?>
 +
</head>
 +
<body>
  
====Coding====
+
<!--
 +
    Layouts are a great place to put header and footer content that will be
 +
    needed on all pages that share the same layout.  To understand fully what
 +
    having layouts inside a MVC application mean, check out the Zend_Layout
 +
    section of the manual.
 +
    http://framework.zend.com/manual/en/zend.layout.html
 +
    -->
 +
<div id="header" style="background-color: #EEEEEE; height: 30px;">
 +
    <div id="header-logo" style="float: left">
 +
        <b>ZF Quickstart Application</b>
 +
    </div>
 +
    <div id="header-navigation" style="float: right">
 +
        <!-- To keep urls consistent with the applications router (right now we
 +
            are using the default router), we will employ the use of the url
 +
            view helper
 +
            http://framework.zend.com/manual/en/zend.view.helpers.html
 +
            -->
 +
        <a href="<?= $this->url(
 +
            array('controller'=>'guestbook'),
 +
            'default',
 +
            true) ?>">Guestbook</a>
 +
    </div>
 +
</div>
  
=====Data Connector=====
+
<!-- This next call will now include any content that was generated in the
 +
    dispatching of a controllers action (or series of actions).  -->
  
Now we need a small class to define how our normal database queries (update, insert, delete) should be handled. In our system, we only require an insert method, as we'll be only allowing inserts into the guestbook. However, to follow best practice we include an update method, but set it so that it will throw an exception error if the update is called. Our insert method with automatically add the date and time of the insert to the database.
+
<?= $this->layout()->content ?>
  
 +
<!-- If your application requires it, this would be a great place to put a
 +
    footer for all pages. -->
  
=====Set-up Model File=====
+
</body>
 +
</html>
 +
</source>
  
The model is what establishes business rules within our application. All methods relating to how our page does what it does should be defined here. We need to be able to retrive records from our database, so that the guestbook can display entries. It includes a function to return one entry, all entries - as well as a function that uses the insert we just set up to save new entries to the database.
+
We grab our application content using the layout() view helper, and accessing the "content" key. You may render to other response segments if you wish to, but in most cases, this is all that's necessary.
  
We have one more line that needs changing in here:
+
Note also the use of the headLink() placeholder. This is an easy way to generate the HTML for <link> elements, as well as to keep track of them throughout your application. If you need to add additional CSS sheets to support a single action, you can do so, and be assured it will be present in the final rendered page.
  
<pre>    protected function _getGuestbookForm()
+
====Checkpoint====
    {
 
        require_once APPLICATION_PATH . '/forms/GuestBook.php';
 
        $form = new Form_GuestBook();
 
        $form->setAction($this->_helper->url('sign'));
 
        return $form;
 
    }
 
</pre>
 
  
Should become:
+
Now go to http://mi-linux.wlv.ac.uk/~YourStudentNumber/QuickStart/public ; and check out the source. You should see your xhtml header, head, title, and body sections.
  
<pre>
 
    protected function _getGuestbookForm()
 
    {
 
        require_once APPLICATION_PATH . '/forms/GuestBook.php';
 
        $form = new Form_GuestBook();
 
        $form->setAction($this->_request->getBaseUrl() . $this->_helper->url('sign'));
 
        return $form;
 
    }
 
</pre>
 
  
=====Guestbook Controller=====
+
===5. Configuration and Registry===
  
[http://framework.zend.com/docs/quickstart/create-a-form In our final steps], we need to create a form through which entries can be inserted.  
+
In older web programming methodologies, programmers would often create a file to be 'included' by all pages that needed access to database connections. This had many disadvantages, such as providing all the code for database connectivity often to every page, even when a database connection was not required for the page. There was also the security considerations of having a file with all the database connection details in a location where it may be accessible by anonymous users.
To tie all the functionality together we have just implemented, we need our guestbook controller. This will call functions in the data connector class we just completed, so that data to be saved can be passed to it, and retrieved records can be displayed through our view.
 
  
=====Guestbook View=====
+
A more modern take on the concept is to have a [http://framework.zend.com/docs/quickstart/create-a-configuration-and-registry registry / configuration file], and classes to provide access to the data. It works much like an .ini file for desktop applications - providing a place to store application-wide settings, such as database connection strings. It works much like a hashtable, where data can be retrieved by key name. [http://framework.zend.com/docs/quickstart/create-a-configuration-and-registry We need to create] our app.ini file, and modify the boostrap.php file to include a reference to the app.ini. In the case of our QuickStart application, we will then be able to access the database settings from any page we choose.
 
 
And as we have our guestbook controller, we need a guestbook view. This will be used to display our guestbook records, as well as offering a link to set our guestbook action to sign, so that a record can be inserted.
 
 
 
 
===7. Form===
 
 
 
We now [http://framework.zend.com/docs/quickstart/create-a-form need a form]; somewhere our users can actually insert their entry. We create a function to initialize the class, which includes all the controls needed for the form, such as the text boxes and the captcha. As can be seen, a captcha control exists within the Zend Framework - we simply state what kind we want, how many letters should be displayed, and what the timeout is before it becomes invalid.
 
 
 
We then modify our GuestbookController to include a sign action; providing users with a means of signing our guestbook.
 
 
 
And as we know by know - new code in the Controller giving us something new to process = new view, so we create a new view for our signing action.
 
 
 
And with the signing view complete, we should have a fully working GuestBook application. Load it up and test it out.
 

Revision as of 10:47, 28 January 2009

Main Page >> Web Frameworks >> Web Frameworks - Workbook >> Workshop - week 03

4. Creating the Layout

We can think of the layout page as a template that defines a consistent look and feel for all pages within the MVC application. The controllers provide views that fill in what is unique about a particular page. Combined together, they provide us with a complete HTML/XHTML page. As the tutorial suggests, this is the reason why the layout is a good place to set up headers and footers that we want to remain the same for all our pages.

You may have noticed that the view scripts in the previous sections were HTML fragments- not complete pages. This is by design; we want our actions to return content only related to the action itself, not the application as a whole.

Now we must compose that generated content into a full HTML page. We'd also like to have a consistent look and feel for the application. We will use a global site layout to accomplish both of these tasks.

There are two design patterns that Zend Framework uses to implement layouts: Two Step View and Composite View. Two Step View is usually associated with the Transform View pattern; the basic idea is that your application view creates a representation that is then injected into the master view for final transformation. The Composite View pattern deals with a view made of one or more atomic, application views.

In Zend Framework, Zend_Layout combines the ideas behind these patterns. Instead of each action view script needing to include site-wide artifacts, they can simply focus on their own responsibilities.

Occasionally, however, you may need application-specific information in your site-wide view script. Fortunately, Zend Framework provides a variety of view placeholders to allow you to provide such information from your action view scripts.

To get started using Zend_Layout, first we need to make some modifications to our bootstrap.php file:

<source lang="php"> // application/bootstrap.php // // Add the following code prior to the comment marked "Step 5" in // application/bootstrap.php. // // LAYOUT SETUP - Setup the layout component // The Zend_Layout component implements a composite (or two-step-view) pattern // With this call we are telling the component where to find the layouts scripts. Zend_Layout::startMvc(APPLICATION_PATH . '/layouts/scripts');

// VIEW SETUP - Initialize properties of the view object // The Zend_View component is used for rendering views. Here, we grab a "global" // view instance from the layout object, and specify the doctype we wish to // use. In this case, XHTML1 Strict. $view = Zend_Layout::getMvcInstance()->getView(); $view->doctype('XHTML1_STRICT');

// CLEANUP - remove items from global scope // This will clear all our local boostrap variables from the global scope of // this script (and any scripts that called bootstrap). This will enforce // object retrieval through the applications's registry. unset($view); </source>

Calling startMvc() registers a plugin with the front controller, allowing layouts to work seamlessly and without further interaction in most cases. An action helper is registered, as is a view helper, in case you do need to interact with the layout object.

Note the call to the doctype() view helper; this is one of the placeholders mentioned above. By setting this in the bootstrap, we can assure that other doctype-aware view helpers know the selected doctype.

Now that we've initialized Zend_Layout, let's create our site-wide layout:

<source lang="php"> <? /* application/layouts/scripts/layout.phtml

     This line outputs the doctype we set in the bootstrap */ ?>

<?= $this->doctype() ?> <html xmlns="http://www.w3.org/1999/xhtml"> <head>

 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
 <title>Zend Framework Quickstart Application</title>
 <?= $this->headLink()->appendStylesheet('/css/global.css') ?>

</head> <body>


<?= $this->layout()->content ?>


</body> </html> </source>

We grab our application content using the layout() view helper, and accessing the "content" key. You may render to other response segments if you wish to, but in most cases, this is all that's necessary.

Note also the use of the headLink() placeholder. This is an easy way to generate the HTML for <link> elements, as well as to keep track of them throughout your application. If you need to add additional CSS sheets to support a single action, you can do so, and be assured it will be present in the final rendered page.

Checkpoint

Now go to http://mi-linux.wlv.ac.uk/~YourStudentNumber/QuickStart/public ; and check out the source. You should see your xhtml header, head, title, and body sections.


5. Configuration and Registry

In older web programming methodologies, programmers would often create a file to be 'included' by all pages that needed access to database connections. This had many disadvantages, such as providing all the code for database connectivity often to every page, even when a database connection was not required for the page. There was also the security considerations of having a file with all the database connection details in a location where it may be accessible by anonymous users.

A more modern take on the concept is to have a registry / configuration file, and classes to provide access to the data. It works much like an .ini file for desktop applications - providing a place to store application-wide settings, such as database connection strings. It works much like a hashtable, where data can be retrieved by key name. We need to create our app.ini file, and modify the boostrap.php file to include a reference to the app.ini. In the case of our QuickStart application, we will then be able to access the database settings from any page we choose.