Difference between revisions of "Workshop - week 03"

From mi-linux
Jump to navigationJump to search
(New page: Text here Back to Web Frameworks - Workbook)
 
m
 
(13 intermediate revisions by 6 users not shown)
Line 1: Line 1:
Text here
+
[[Main Page]] >> [[CP2132|Web Frameworks]] >> [[Web Frameworks - Workbook|Workbook]] >> Workshop - week 03
  
Back to [[Web Frameworks - Workbook]]
+
===Creating the Layout===
 +
 
 +
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.
 +
 
 +
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:
 +
 
 +
<pre>
 +
// 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);
 +
</pre>
 +
 
 +
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:
 +
 
 +
<pre>
 +
<? /* 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('https://mi-linux.wlv.ac.uk/~<YourStudentNumber>/QuickStart/public/css/global.css') ?>
 +
</head>
 +
<body>
 +
 
 +
<!--
 +
    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>
 +
 
 +
<!-- This next call will now include any content that was generated in the
 +
    dispatching of a controllers action (or series of actions).  -->
 +
 
 +
<?= $this->layout()->content ?>
 +
 
 +
<!-- If your application requires it, this would be a great place to put a
 +
    footer for all pages. -->
 +
 
 +
</body>
 +
</html>
 +
</pre>
 +
 
 +
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.
 +
 
 +
 
 +
===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 [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.
 +
 
 +
 
 +
===Create a Configuration and Registry===
 +
Application configurations are an important part of creating modular and configurable applications. This is where Zend_Config comes into play. First we will create an application configuration file and put it inside application/config/app.ini.
 +
<pre>
 +
;; application/config/app.ini
 +
;;
 +
;;This is a sample app.ini file.  Your application will dictate the format and the
 +
;;type of sections and data that can be found in this ini file.  It will also dictate
 +
;;how many ini files will be contained in your config/ directory.  For the puropose
 +
;;of our application, this one file makes the most sense.
 +
 
 +
;;We always have our "production" section first, because it will define ALL of the
 +
;;keys that our application is expecting to see, and reduce deployment issues
 +
;;resulting from configuration.
 +
 
 +
[production]
 +
 
 +
[development : production]
 +
 
 +
[testing : production]
 +
</pre>
 +
 
 +
Zend_Config has several adapters for parsing configuration files; each returns an object with which you can then access the values in the configuration using an object-oriented interface. In this case, we will use Zend_Config_Ini.
 +
Now, what if we want to access this configuration object elsewhere in our application? The standard design pattern used in such situations is the Registry. Zend_Registry is Zend Framework's implementation of this pattern.
 +
In this next code sample, we will instruct our bootstrap file to load the proper section of the config file and add it to our application registry.
 +
 
 +
<pre>
 +
// application/bootstrap.php
 +
//
 +
// CONFIGURATION - Setup the configuration object
 +
// The Zend_Config_Ini component will parse the ini file, and resolve all of
 +
// the values for the given section.  Here we will be using the section name
 +
// that corresponds to the APP's Environment
 +
$configuration = new Zend_Config_Ini(
 +
    APPLICATION_PATH . '/config/app.ini',
 +
    APPLICATION_ENVIRONMENT
 +
);
 +
 
 +
// REGISTRY - setup the application registry
 +
// An application registry allows the application to store application
 +
// necessary objects into a safe and consistent (non global) place for future
 +
// retrieval.  This allows the application to ensure that regardless of what
 +
// happends in the global scope, the registry will contain the objects it
 +
// needs.
 +
$registry = Zend_Registry::getInstance();
 +
$registry->configuration = $configuration;
 +
 
 +
// 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($frontController, $view, $configuration, $registry);
 +
</pre>
 +
 
 +
==References==
 +
 
 +
All work relating to the QuickStart tutorial is © 2006 - 2009 by Zend Technologies Ltd. All rights reserved.
 +
 
 +
http://framework.zend.com/docs/quickstart/
 +
 
 +
http://www.johnmee.com/2008/11/zend-framework-quickstart-tutorial-deploy-to-a-subdirectory-instead-of-web-root/
 +
 
 +
== Ready to move on? ==
 +
 
 +
When you're happy you understand what you've done here, take a look at the [[Workshop_-_week_04|Week 4 Workshop]]

Latest revision as of 07:14, 23 July 2009

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

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:

// 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);

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:

<? /* 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('https://mi-linux.wlv.ac.uk/~<YourStudentNumber>/QuickStart/public/css/global.css') ?>
</head> 
<body>

<!-- 
    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>

<!-- This next call will now include any content that was generated in the
     dispatching of a controllers action (or series of actions).  -->

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

<!-- If your application requires it, this would be a great place to put a
     footer for all pages. -->

</body>
</html>

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.


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.


Create a Configuration and Registry

Application configurations are an important part of creating modular and configurable applications. This is where Zend_Config comes into play. First we will create an application configuration file and put it inside application/config/app.ini.

;; application/config/app.ini
;; 
;;This is a sample app.ini file.  Your application will dictate the format and the
;;type of sections and data that can be found in this ini file.  It will also dictate
;;how many ini files will be contained in your config/ directory.  For the puropose
;;of our application, this one file makes the most sense.

;;We always have our "production" section first, because it will define ALL of the 
;;keys that our application is expecting to see, and reduce deployment issues
;;resulting from configuration.

[production]

[development : production]

[testing : production]

Zend_Config has several adapters for parsing configuration files; each returns an object with which you can then access the values in the configuration using an object-oriented interface. In this case, we will use Zend_Config_Ini. Now, what if we want to access this configuration object elsewhere in our application? The standard design pattern used in such situations is the Registry. Zend_Registry is Zend Framework's implementation of this pattern. In this next code sample, we will instruct our bootstrap file to load the proper section of the config file and add it to our application registry.

// application/bootstrap.php
//
// CONFIGURATION - Setup the configuration object
// The Zend_Config_Ini component will parse the ini file, and resolve all of
// the values for the given section.  Here we will be using the section name
// that corresponds to the APP's Environment
$configuration = new Zend_Config_Ini(
    APPLICATION_PATH . '/config/app.ini', 
    APPLICATION_ENVIRONMENT
);

// REGISTRY - setup the application registry
// An application registry allows the application to store application 
// necessary objects into a safe and consistent (non global) place for future 
// retrieval.  This allows the application to ensure that regardless of what 
// happends in the global scope, the registry will contain the objects it 
// needs.
$registry = Zend_Registry::getInstance();
$registry->configuration = $configuration;

// 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($frontController, $view, $configuration, $registry);

References

All work relating to the QuickStart tutorial is © 2006 - 2009 by Zend Technologies Ltd. All rights reserved.

http://framework.zend.com/docs/quickstart/

http://www.johnmee.com/2008/11/zend-framework-quickstart-tutorial-deploy-to-a-subdirectory-instead-of-web-root/

Ready to move on?

When you're happy you understand what you've done here, take a look at the Week 4 Workshop