Phramework
Table of Contents
License....................................................................................................................................................................... 1
Introduction................................................................................................................................................................ 2
Installation.................................................................................................................................................................. 2
index.php................................................................................................................................................................ 2
config.properties...................................................................................................................................................... 2
Concept...................................................................................................................................................................... 2
Main Methods.............................................................................................................................................................. 2
import($path).......................................................................................................................................................... 2
Classes....................................................................................................................................................................... 3
Action class............................................................................................................................................................. 3
execute() Method.................................................................................................................................................. 3
ActionResult class..................................................................................................................................................... 3
ActionResult($mapping, $data) Constructor............................................................................................................. 3
View class............................................................................................................................................................... 3
processView($data) Method................................................................................................................................... 3
ViewPlugin class....................................................................................................................................................... 3
init($params) Method............................................................................................................................................ 4
destroy() Method.................................................................................................................................................. 4
processView($viewValue, $data) Method................................................................................................................ 4
PropertiesParser class.............................................................................................................................................. 4
getProperty($key, $default=null, $split=false) Method.............................................................................................. 4
containsKey($key)................................................................................................................................................. 4
Configuration.............................................................................................................................................................. 4
config.properties (revisited)....................................................................................................................................... 4
Replacement Areas............................................................................................................................................... 4
Phramework Specific Properties............................................................................................................................. 4
phramework.config.files................................................................................................................................. 4
phramework.classpath................................................................................................................................... 5
phramework.import.extensions....................................................................................................................... 5
phramework.page.identifier............................................................................................................................ 5
Action Properties.................................................................................................................................................. 5
View Properties.................................................................................................................................................... 5
ViewPlugin Properties............................................................................................................................................ 5
.extensions property...................................................................................................................................... 5
.initparams property...................................................................................................................................... 6
User Defined Properties......................................................................................................................................... 6
Examples.................................................................................................................................................................... 6
Hello World Example (Part 1)..................................................................................................................................... 6
Hello World Example (Part 2)..................................................................................................................................... 8
Setup.................................................................................................................................................................. 9
Application........................................................................................................................................................... 9
Conclusion................................................................................................................................................................ 13
Appendix I: Tips And Tricks........................................................................................................................................ 13
Make Use Of Phramework's Classpath...................................................................................................................... 14
Phramework Copyright (C) 2005 GodsArmor.com
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to theFree Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Phramework is a PHP framework that follows the MVC framework for web applications. It very loosely follows the Struts framework in its terminology and was developed so that there would only be two mandatory files that would need to be included for the framework. This makes the code slightly less readable, but makes installation a breeze.
There are two files that need to be included for Phramework to be a complete installation. The first is called index.php and the second is config.properties
This file contains the actual Phramework code, acts as the controller for the web application and is the entry point for every request that should be handled by Phramework. This file contains a number of classes and utility functions that can be used by other parts of the web application.
This file contains all the configuration information about the web application including Phramework actions, views, plugins and other web application specific configuration data. This will be explained later.
Phramework initially started out as a very simple method of creating PHP namespaces. I wanted an ‘import’ function that I could pass a fully qualified class name and ‘require_once’ that class. As I got more and more into it, I found I needed more and more configuration information. One thing led to another and Phramework was born.
Phramework uses an MVC architecture where Phramework is the controller, and you the developer build the model and view. When Phramework receives a request, it determines which Action class it should send the request to based on information in the config.properties file. The Action returns an ActionResult object which contains data and a view mapping. Phramework then matches the view mapping to a value in the config.properties file and calls the class that should render the view. This class either extends the View object or can be a ViewPlugin. ViewPlugins have been written so that other view methods can be used, such as static html, Smarty templates, XSLT, etc.
This method is not part of any class and is available to any class. It is used to import classes into the web application. It uses the same constructs as importing a Java class. You can import a class by calling import with the path to the class as a string variable to the method. For example if you call import(‘com.myname.myclasses.AClass’) import will attempt to look in the ‘com/myname/myclasses’ directory for a class called AClass.php (extension configurable; see phramework.import.extensions in the configuration section). The import method heavily utilizes the ‘import_path’ ini variable which means that you can put your classes in a secured area outside of your web site and include that path in the ‘import_path’ ini variable. Phramework will append the subpath (i.e. ‘com/myname/myclasses’) to import_path items and attempt to find the AClass.php file. Once found, the import method will ‘require_once’ the class and return its name to the caller. The main constraints of this method is that the $path must exist in the ‘include_path’ and that the name of the class must be the same as the name of the file. So, AClass.php must contain a class called AClass. Otherwise the require_once will fail. See the phramework.classpath configuration property for more information.
The following are classes that are used by Phramework in a request lifecycle.
The action class handles processing the request from the browser. This is the first non-Phramework class that gets called. It’s job is to process the request and then send the result (in an ActionResult class) back to Phramework. Any action defined in the config.properties file must extend the Action class.
Phramework will call the no argument constructor for the subclass of the Action class and then call its execute() method.
The execute method is called by Phramework. It has no parameters. The Action class should access GET or POST variables via the $_GET, $_POST or $_REQUEST global variables. I prefer $_REQUEST since is doesn’t require that the user know the method of the request.
Once the execute method has done its processing it should return an object of type ActionResult.
The ActionResult class is nothing more than a placeholder for data returned by a subclass of the Action class as well as a mapping for the view. There is no need to subclass this class. Instead, the execute method of the Action class should create a new instance of this class, passing in the data to return to the user as well as a string value identifying a mapping for the action in order for the view to be generated.
The constructor for the ActionResult class takes a $mapping which is a string that maps to a specific view for this action as well as any data that the view class needs to process it’s view. The data is not of any type. It can be an array, a string of XML a set of objects, even null. In this way, the controller is not tied to any particular method of generating a view. The model knows what type of data its view needs in order to show a proper page to the user. In fact, multiple methods can be used in the same web application.
There are two ways to generate a view. The first way is via a PHP class. The class must extend the View class. Its job would be to take the data from the ActionResult class and echo output to the browser (most likely HTML). Phramework will create an instance of the View subclass via its no argument constructor and call its processView($data) method.
This is the method that will process the view that is sent back to the browser. At the point of this method call, no headers have been sent to the browser, so if necessary it can be done here. Phramework doesn’t have any idea as to what this method will echo to the browser and frankly doesn’t care. It could be HTML, text, XML, pig latin, whatever. The $data is the same data that was passed to Phramework from the Action subclass via the ActionResult class.
I later found out that using a class to output HTML to the browser was not the smartest method of output because it coupled PHP with HTML in a reverse method of how it is generally done. I wanted to decouple the view from the code further, so I created the ViewPlugin class. View plugins are subclasses of the ViewPlugin class and define a method of generating a view depending on the value of the mapping result. Phramework will look at the extension of the view mapping value and then look for a plugin that would handle the view for that extension. For example, you could define a SmartyPlugin in your configuration file and assign it to be used whenever the view mapping has a .tpl extension. Or you could define an XsltPlugin and assign it to be used whenever the view mapping has a .xslt extension. It’s up to you. I have defined reusable plugins for static HTML, Smarty and XSLT, but other plugins could be defined.
Phramework will create a new instance of the plugin using its no argument constructor, call its init($params) method to initialize the plugin, call its processView($viewValue, $data) method to generate the view and finally call its destroy method for any cleanup that the plugin should do.
This method is used to initialize the plugin. You define initialization parameters in the configuration file for the plugin and those parameters are passed into this method. More information can be found in the configuration section.
This method is used to do any cleanup that the plugin should do after it has generated the view. This could include unsetting any variables, etc.
This method does the work for creating the view. The $viewValue variable contains the value that was found for the view mapping. Again it is up to the view and the action as to what is contained in this value, but for example, in a SmartyPlugin, this would most likely contain the template to generate. The $data variable contains the data that was passed back to Phramework by the Action in the ActionResult object.
This class is used to parse the properties file. Once the file(s) have been parsed, an instance of this object is put into $GLOBALS["properties"] so any part of the web application can get to it. This allows you to put application configuration information in the properties file for your convenience such as database connectivity information, timestamp formatting, etc.
This method will return the value of a key in the properties file passed in the $key variable. If the $key property is not found, the $default value will be returned. Finally, the configuration file can contain pipe separated (|) values. If the $split variable contains true, the value of the property will be split on the pipe separator (|) and will be returned as an array of values. The default is false which means the value found for the property will be returned as a string value.
This method returns true if there is a property in the properties file with the value of $key or false if not.
The config.properties file is where all the configuration information goes for your entire web application. In addition to Phramework specific information it also allows global accessibility to your web classes via $GLOBALS["properties"]. This means you can put application specific data in your config.properties file and grab it via the PropertiesParser class. You can also have multiple config.properties files in different locations. The only mandatory file is config.properties and it must reside in the same directory as index.php. Inside config.properties you can define the location of other properties files and they will be read in and appended to the list of properties.
You can also define replacement areas where the results of one property will replace a portion of the value of another property. The delimiters for a replacement area is ${ and } Suppose I had a property called ‘my.first.property’ with a value of ‘abc’. Then suppose I had another property called ‘a.different.property’ with a value of ‘${my.first.property}def’. When accessing the ‘a.different.property’ key, the value returned would be the result of replacing the ${…} with the value of that property. Thus the returned value for ‘a.different.property’ would be ‘abcdef’. It is not necessary for the replacement property to be defined before the property to be replaced.
Phramework allows you to have multiple configuration files for an individual application. The benefits to this are twofold. First, it allows you to separate application configuration from Phramework configuration. This, for example, means you could have database access information stored in its own configuration file that could be used by multiple applications. Second, it allows for a more secure application because you could store sensitive information outside of the application's web path and tell Phramework where to access that information.
Tip: For a very secure application, only put this configuation parameter in the config.properties file and have it point to multiple files outside of your web path to gather the remaining information. If a user decides to look at your config.properties file, all he will be able to see is the path to the other configuration files.
Phramework heavily utilizes the ‘include_path’ which has been re-coined classpath in this instance. All classes, files, images, etc. should be accessible via the ‘include_path’ PHP ini variable. Phramework looks for each class in a subdirectory of its set of ‘include_path’s. So if you are including a class ‘com.myclasses.someapp.AClass’, Phramework assumes that there will be a file called AClass.php (extension configurable; see phramework.import.extensions) in the com/myclasses/someapp subdirectory and the ‘com’ directory must be at the root of one of the ‘include_path’ entries. It’s almost exactly how Java handles including classes and namespaces. This allows you to put your application classes in a secured area outside of the web site and still access the code. It only requires that the root directory is on the ‘include_path’.
This allows you to define what extensions are valid for filenames when using the import($path) method. It can be a pipe separated (|) set of values. For example, if you have this property set to ‘php|class.php|inc.php|class’ and try to import a class ‘com.myclasses.someapp.AClass’ the Phramework will look for files in the ‘com/myclasses/someapp’ directory called either AClass.php, AClass.class.php, AClass.inc.php or AClass.class. The first one it finds will be used as the file to import. For performance reasons, it would be best to limit the number of extensions as much as possible.
This configuration options defines the request variable that should be queried to find out what Action class should be called. If set to ‘action’ for example, Phramework will look in $_REQUEST[‘action’] for the identifier of the Action subclass that should be used.
All actions must have an action property associated with them. Based on the value of the phramework.page.identifier key the framework will choose an action to perform. For example if the action request variable is 'editPage' the phramework will search for an action called ‘action.editPage’ and run the class on that action. If no action request variable is passed in to the page, Phramework will run the action.default action. So, action.default should always be defined to execute some action. Actions must extend the Action class defined by the phramework. See the Action Class section earlier.
When an action has completed its processing, it needs to forward information to a particular view by passing a "mapping" value back to Phramework. This value is a string that will be appended to the action request variable and searched for as a key in this config file. For example, if the action is 'editPage' and the class for edit page returned 'success', Phramework look for a view called view.editPage.success. If it could not be found, Phramework will then look for global.view.success. An action specific view will always take precedence over a global view. Views must extend the View class defined by Phramework. See the View Class section earlier.
View plugins allow views to be generated by methods other than php classes. By default and if there are no plugins defined the view for the action will imported into Phramework as a PHP class that extends the View class defined by Phramework and its processView method will be executed. If view plugins are defined and the extension of the view mapping matches the extension for the plugin, the plugin will be imported and loaded and its processView method will be called. View plugins must extend the ViewPlugin class defined by Phramework. Each plugin must also define the extensions that it will handle. That is how Phramework knows to pass the view to the plugin. You can also pass in initialization parameters to the plugin which will be passed in to the plugin via the init($params) method of the ViewPlugin subclass. See the ViewPlugin Class section earlier.
These are the extensions that this plugin will process. It can be a pipe separated list of extensions without the ‘.’. If the plugin name is ‘smarty’, the plugin property would be defined as viewplugin.smarty and its extensions would be defined in the viewplugin.smarty.extensions property.
These are the initialization parameters that should be passed to the plugin when the init($params) method is called. They will be passed in as an array of key value pairs where the key is the item after ‘iniparams’ and the value is the value of the property. For example if the plugin name is ‘smarty’, the plugin property would be defined as viewplugin.smarty and a sample initialization parameter would be defined as viewplugin.smarty.initparams.template_dir. In the associative array passed to the init($params) method, the key would be ‘template_dir’ and the value would be the value of the property found in ‘viewplugin.smarty.initparams.template_dir’. All initparams must contain a key. So, ‘viewplugin.smarty.initparams’ is invalid but ‘viewplugin.smarty.initparams.template_dir’ is valid.
As long as they do not conflict with any of the above properties, any other key/value pair is valid in the configuration file. Your application can access these variables via the getProperty method of the $_GLOBALS[“properties”] global variable. See the getProperty($key, $default=null, $split=false) section described above.
For me, the easiest way to learn something is to have an example, so let’s jump in with the classic Hello World example. This example will display a page for the user to type in his name and then will display a hello <name> message. A working version of this example can be found at http://www.godsarmor.com/phramework/example1. The code for this example can be found at http://www.godsarmor.com/phramework/example1/example1.zip. To get it working on your server, simply unzip the file to a location on your web server and change the value of the 'example.path' configuration property in config.properties to the full path where you unzipped the files.
We will make the following assumptions:
The first thing we need to do is define what identifier should be used to determine the action to perform. Let’s use ‘action’. To do this change (or add) the phramework.page.identifier configuration property in config.properties and set it to the value ‘action’ (i.e. phramework.page.identifier=action).
We next need to tell Phramework which extensions it should look for when importing class files. In our case we will name all files with a .php extension just to make it simple. To do this create a key in the properties file called 'phramework.import.extensions' and set the value equal to 'php'. Do not include the '.'. Just include the extension.
Next we need to define what class should be called when the default action (or no action) is passed in. Let’s create a class called DefaultAction and put it in the following location relative to your public_html directory; classes/com/example1/actions/DefaultAction.php. We know this page will just be a static html page, so we don’t need to do anything in the Action class, we can just hand it off to the View class. So the class is very skeletal. Here’s an example of what the DefaultAction could look like:
|
<?php class DefaultAction extends Action {
function DefaultAction() {}
function execute() { $mapping = "success"; $data = null;
return new ActionResult($mapping, $data); } } ?> |
What does that $mapping = “success” line mean? Good question. Let’s put that on the back burner for later. Save the file and we are done with the action.
Now let’s create a view that will display the default page. Let’s put this in classes/com/example1/views/DefaultView.php. This again will just spit out some very generic code and can look something like this:
|
<?php class DefaultView extends View { function DefaultView() {} function processView($data) { echo "<html><head><title>Hello World Example 1</title></head><body>"; echo "<form action=\"index.php\" method=\"POST\">Type your name: <input type=\"text\" name=\"name\"/>"; echo "<input type=\"hidden\" name=\"action\" value=\"showHello\"</form>"; echo "</body></html>" } } ?> |
Take note of the hidden input variable. This variable has a name of “action” and a value of “showHello”. These will be used later.
Now we need to set up the config.properties file so that the classes we just created are in Phramework's classpath and so Phramework can call the correct classes for the appropriate actions. Since we put all of our classes in /home/user/public_html/classes, we need to add that path to our phramework.classpath property. Then when Phramework attempts to import 'com.example1.views.DefaultView, it will find it correctly.
In this case we are dealing with the default action (an request with no action property is defined as the default action) so we need to set up the default action to call the 'com.example1.actions.DefaultAction' class. Therefore, set the 'action.default' key to 'com.example1.actions.DefaultAction'.
If we look back at the DefaultAction class shown earlier, we see that the ActionResult passed back has a $mapping equal to 'success'. What this means is that Phramework should look for a 'success' view mapping for the default action mapping. So Phramwork will look for a view.default.success key in the properties file and call the class that it corresponds to. In order to make this mapping, add a key of 'view.default.success' with a value of 'com.example1.views.DefaultView'.
This is enough right now to run the application. If you open your browser and navigate to the index.php Phramework page, you should get a page similar to the one below.
![]() |
Looking at the source of the page we notice two things that are important. The first is the hidden form field called action with a value of 'showHello' and the text input with a name of 'name'.
Next we need to write the classes to handle when the user submits the form. Let's create a class in the com/example1/actions subfolder. And let's call it SubmitFormAction. Below is an example of what the class would look like:
|
<?php class SubmitFormAction extends Action {
function SubmitFormAction() {}
function execute() { $mapping = "success"; $data = $_REQUEST['name'];
return new ActionResult($mapping, $data); } } ?> |
Notice that we are setting the $data variable to the value that the user typed in and that we are setting the $mapping variable to 'success' (again).
We can also create a new class called SubmitFormView which will display write out the web page to the browser. So, we'll create another class in the com/example1/views directory called SubmitFormView.php. Below is an example of the view class.
|
<?php class SubmitFormView extends View { function SubmitFormView() {} function processView($data) { echo "<html><head><title>Hello World Example 1</title></head><body>Hello $data!</body></html>"; } } ?> |
Notice that we are using the value that the action class set the $data variable to to print out the typed in information.
To set up the configuration, we need to add another action and view. From viewing the source of the initial page, we see that the action is going to be called 'showHello'. So we need to set up an action called 'action.showHello' and set its value equal to 'com.example1.actions.SubmitFormAction'.
The SubmitFormAction maps to a view called 'success'. Therefore we need to set up a view with a key of 'view.showHello.success' and set its value to 'com.example1.views.SubmitFormView'.
After filling out the form and hitting the return key, you should see a page similar to the following:
![]() |
This should give a good start in creating web applications using Phramework. Continue on to Example 2 to replace the view classes with ViewPlugin classes.
In this example we will create the same example from Part 1 and replace the View classes with ViewPlugin classes. A working version of this example can be found at http://www.godsarmor.com/phramework/example2. The code for this example can be found at http://www.godsarmor.com/phramework/example2/example2.zip. To get it working on your server, simply unzip the file to a location on your web server and change the value of the 'example.path' configuration property in config.properties to the full path where you unzipped the files. This example uses view plugins to generate the view and specifically uses an HTML view plugin and a Smarty view plugin. The zip file not only contains the example, but it also contains the Smarty template engine for ease of setup.
Again, like in example 1, we will make the following assumptions:
Let's do some initial setup for Smarty to begin with. Download Smarty (http://smarty.php.net) and unzip it to a temporary folder. In a folder called 'lib/Smarty' in '/home/user/public_html/example2' take the contents of the 'lib' directory from your temporary folder and upload it. Underneath the '/home/user/public_html/example2/lib/Smarty' directory there should be two other directories, 'internals' and 'plugins' as well as the actual Smarty classes.
Next we need to set up the location of the compiled Smarty templates and cache files. In '/home/user/public_html/example2' create subdirectories called 'smartyfiles/cache', 'smartyfiles/config' and 'smartyfiles/templates_c'.
Smarty should be set up properly at this point and we can get on to the real application.
Let's start by creating the HTML page that should be shown when the user opens his browser and navigates to the example2 directory. This is just a static HTML page and could look like the example below:
|
<html> <head><title>Hello World Example</title></head> <body> <form action="index.php" method="POST">Type your name: <input type="text" name="name"/> <input type="hidden" name="action" value="showHello"></form> </body> </html> |
Put this file in '/home/user/public_html/example2/pages/html' and call it helloWorld.html.
Next we need to create a class that extends the Phramework ViewPlugin class whose job it is to display html pages. The class could look like the example below.
|
class HtmlPlugin extends ViewPlugin { function HtmlPlugin(){}
function processView($viewValue, $data) { readfile($viewValue, true); } } |
Notice that all this class does is take the value of $viewValue and try to write the contents of the file out to the browser. Put this file in '/home/user/public_html/example2/classes/com/example2/plugins' and call it 'HtmlPlugin.php'.
Next, we need to create an action that will handle the default an incoming request from the browser. Since we are just going to be displaying a static HTML page, let’s create a static page action which does nothing but forward the request to the view. It could look like the class below:
|
class StaticPageAction extends Action {
function StaticPageAction() {}
function execute() { $mapping = "success";
$data = null;
return new ActionResult($mapping, $data); } } |
Put this file in '/home/user/public_html/example2/classes/com/example2/actions' and call it 'StaticPageAction.php'.
Finally, let’s configure Phramework to display the static HTML page to the browser when the user navigates to the example2 subdirectory. In order to do this, we need to do a number of things.
Let’s set up some user defined configuration properties in config.properties that correspond to the paths we’ve defined above as well as some we will need for Smarty, it’s file locations and it’s template locations:
|
example.path=/home/user/public_html/example2
classes.path=${example.path}/classes smarty.path=${example.path}/lib/Smarty smarty.templates.path=${example.path}/pages/templates smarty.files.path=${example.path}/smartyfiles html.pages.path=${example.path}/pages/html
phramework.classpath=${classes.path}|${smarty.path}|${html.pages.path}|${smarty.templates.path}|${smarty.files.path} |
In this configuration section we are setting up the classpath so Phramework knows where to find all of the resources it needs. Notice how we used properties defined earlier ('example.path') to define other properties ('smarty.path', 'html.pages.path', etc).
Next, as in example 1, we need to define the extensions that Phramework will import when 'require_once'ing a class. In example 1, we only defined 'php' as an extension, but Smarty uses 'class.php' as it’s extension, so we have to allow that extension also. Here we also define the request identifier that will tell us which action to perform. Add this to your config.properties file:
|
phramework.import.extensions=php|class.php
phramework.page.identifier=action |
Before setting up the actions and views, let’s define the Phramework view plugin that we created for showing static HTML pages in the config.properties file. This plugin requires no initialization parameters, so the configuration is pretty simple. We need to tell Phramework which class should be called when a specific extension is found in the view for a particular action. Here we are telling Phramework that the 'com.example2.plugins.HtmlPlugin' class should be called when the extension of the view is 'html'.
|
viewplugin.html=com.example2.plugins.HtmlPlugin viewplugin.html.extensions=html |
The format for a plugin is 'viewplugin.<someidentifier>'. The <someidentifier> piece is not important, but groups a view plugin with it’s extension and initialization parameters. Later, we will set up another view plugin for Smarty which is slightly more complicated.
Finally, we need to set up the default action and view. As you remember from example 1, the 'action.default' is the action that will be called when the request property defined by the 'phramework.page.identifier' is not found in the request. You will also remember that every action has a view defined by 'view.<action identifier>.<mapping>' where <action identifier> is the action id (in our case, 'default') and the <mapping> is the view mapping that should be performed. If you look at the StaticPageAction class again, the mapping will be 'success'. So based on that information, our action and view mapping for the static page would look like this:
|
action.default=com.example2.actions.StaticPageAction
view.default.success=helloWorld.html |
At this point, you have a working application that will display a page similar to the beginning page from example 1 above. This page will have a text box where you can enter your name. Next we need to handle displaying the name in the browser when the user submits the page. In order to make this example slightly more complicated for learning purposes, we will use Smarty to generate the response back to the user.
Start by creating a Smarty template which will display the name entered from the previous static HTML form. I’ll assume you are familiar with Smarty. So here is the template.
|
<html> <head><title>Hello World Example2 ({$appName})</title></head> <body> Hello {$name}! </body> </html> |
Put this page in '/home/user/example2/pages/templates' and call it helloWorldResponse.tpl. Notice we gave it an extension of 'tpl'.
Next, create an action to handle the form being submitted. This will take the request property and put it into an array that Smarty can handle.
|
class ShowHelloAction extends Action {
function ShowHelloAction() {}
function execute() { $config = $GLOBALS["properties"];
$mapping = "success";
$data['name'] = 'no name'; if (isset($_REQUEST['name'])) { $data['name'] = $_REQUEST['name']; }
return new ActionResult($mapping, $data); } } |
Put it in '/home/user/example2/classes/com/example2/actions' and call it ShowHelloAction.php.
Now let’s create the Smarty view plugin. This is very similar to the HtmlPlugin class we created earlier, however Smarty does require some initialization information. This information is passed to the view plugin via the 'init($params)' method of the class and is an array of key/value pairs.
|
import('Smarty');
class SmartyPlugin extends ViewPlugin { var $smarty;
function SmartyPlugin() { $this->smarty = new Smarty(); }
function init($params) { $this->smarty->template_dir = $params['template_dir']; $this->smarty->compile_dir = $params['compile_dir']; $this->smarty->config_dir = $params['config_dir']; $this->smarty->cache_dir = $params['cache_dir'];
if (array_key_exists('plugins_dir', $params)) { if (strlen(trim($params['plugins_dir'])) > 0) { // append this list of plugins directories to the current one // placing the ones in the configuration file first $arrPluginsDir = explode('|', $params['plugins_dir']); $arrPluginsDir[] = $this->smarty->plugins_dir[0]; $this->smarty->plugins_dir = $arrPluginsDir; } }
if (array_key_exists('caching', $params)) { $this->smarty->caching = $params['caching']; } else { $this->smarty->caching = 0; }
$this->setAssigns($params); }
function destroy() { unset($this->smarty); }
function processView($viewValue, $data) { $this->setAssigns($data); $this->smarty->display($viewValue); }
function setAssigns($params) { if (is_array($params)) { $arrKeys = array_keys($params); foreach($arrKeys as $key) { $this->smarty->assign($key, $params[$key]); } } } } |
Put this file in '/home/user/example2/classes/com/example2/plugins' and call it SmartyPlugin.php. Notice we are importing Smarty which is doable because the Smarty library files have been defined on the Phramework classpath.
Finally we need to set up the configuration for when the user submits the page. When looking at the static HTML page, we can see that there is a hidden property called 'action' with a value of 'showHello'. This corresponds to our action identifier, so our action and view will be 'showHello'. You can also see from our ShowHelloAction class that the view mapping returned to Phramework is 'success'. And when we see the success view, we want to pass the information to the Smarty template called 'helloWorldResponse.tpl'. Based on that information, our config.properties entries for the action and view would be the following:
|
action.showHello=com.example2.actions.ShowHelloAction
view.showHello.success=helloWorldResponse.tpl |
This can be placed in the config.properties file.
Now how does Phramework know to display the 'helloWorldResponse.tpl' file through Smarty. Well, just like we did with the HTML view plugin, we need to configure the Smarty view plugin and tell Phramework that it should handle all views that end in the 'tpl' extension. Smarty also requires some initialization information regarding where it should compile templates, where it’s cache is, etc. We do that through the 'initparams' part of the view plugin configuration. Anything after the 'initparams' piece will be a key to an array that is passed to the view plugin. The value of the key will be the value of the configuration parameter. Based on that, we can set up the Smarty view plugin like so:
|
viewplugin.smarty=com.example2.plugins.SmartyPlugin viewplugin.smarty.extensions=tpl viewplugin.smarty.initparams.template_dir=${example.path}/pages/templates/ viewplugin.smarty.initparams.compile_dir=${smarty.files.path}/templates_c/ viewplugin.smarty.initparams.config_dir=${smarty.files.path}/configs/ viewplugin.smarty.initparams.cache_dir=${smarty.files.path}/cache/ viewplugin.smarty.initparams.caching=0 viewplugin.smarty.initparams.plugins_dir=${smarty.plugins.path} viewplugin.smarty.initparams.appName=Phramework Example |
Notice that it has a different identifier than the HTML plugin had. Also notice that we are telling Phramework that the class 'com.example2.plugins.SmartyPlugin' should handle any views where the view value in the configuration property has an extension of 'tpl'.
Below is the full config.properties file with everything configured.
|
example.path=/kunden/homepages/41/d89035854/htdocs/phramework/example2
classes.path=${example.path}/classes smarty.path=${example.path}/lib/Smarty smarty.templates.path=${example.path}/pages/templates smarty.files.path=${example.path}/smartyfiles html.pages.path=${example.path}/pages/html
phramework.classpath=${classes.path}|${smarty.path}|${html.pages.path}|${smarty.templates.path}|${smarty.files.path}
phramework.import.extensions=php|class.php
phramework.page.identifier=action
action.default=com.example2.actions.StaticPageAction action.showHello=com.example2.actions.ShowHelloAction
view.default.success=helloWorld.html view.showHello.success=helloWorldResponse.tpl
viewplugin.smarty=com.example2.plugins.SmartyPlugin viewplugin.smarty.extensions=tpl viewplugin.smarty.initparams.template_dir=${example.path}/pages/templates/ viewplugin.smarty.initparams.compile_dir=${smarty.files.path}/templates_c/ viewplugin.smarty.initparams.config_dir=${smarty.files.path}/configs/ viewplugin.smarty.initparams.cache_dir=${smarty.files.path}/cache/ viewplugin.smarty.initparams.caching=0 viewplugin.smarty.initparams.plugins_dir=${smarty.plugins.path} viewplugin.smarty.initparams.appName=Phramework Example
viewplugin.html=com.example2.plugins.HtmlPlugin viewplugin.html.extensions=html |
You should be able to run this application and it should behave exactly the same as example 1 above. This is slightly overkill for such a simple application, but it gives you an idea of the versatility and power of Phramework.
This concludes the Phramework user guide. Hopefully it has give you a better idea of what Phramework can do for you. In the future there will be a full application that can be analyzed to understand some of the more complex concepts better.
This sections contains tips and tricks that can be used to either enhance security of your application or speed up development time. It will expand as more items are added (of course).
As long as the files you are trying to access are in Phramework's classpath, Phramework does not care where in your file system the files physically reside. This goes for any type of file, whether they are classes, HTML files, Smarty templates, XSLT stylesheets, other configuration files, whatever. What this means to you is you can create a library of reusable classes, common stylesheets or common HTML files for example and use them across multiple applications.
As an example, let's take the case of database access. Phramework allows you to create multiple configuration files and link to them through the 'phramework.config.files' configuration parameter in your main config.properties file. You could store a number of database parameters in a separate file (called db.properties for example) outside of your web directory so no one could gain access to it. Then in your config.properties file, add the full path and filename to the 'phramework.config.files' configuration property. Phramework will read the db.properties file and add it to its list of properties. Since these properties are accessible to any class via the $GLOBALS['properties'] global variable, you could write a Phramework aware database layer that uses the configuration properties to create a connection to your database. The exciting thing about that is that your database layer could also be completely abstracted outside of the application so that any application using Phramework could have a database connection without any recoding.