PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Discuss Subscribe to PHP Subscribe to Newsletters

Three-Tier Development with PHP 5
Pages: 1, 2

Smarty files

It's time to create several files for Smarty:

include.php
1 <?
2   require('Smarty.class.php');
3   $smarty = new Smarty;
4   $smarty->template_dir = 'templates/';
5   $smarty->compile_dir  = 'templates_c/';
6   $smarty->config_dir   = 'configs/';
7   $smarty->cache_dir    =  'cache/';
?>

This script instantiates a new Smarty object for the application.

index.php
1 <? 
2  require("include.php");
3  $smarty->assign('TITLE','ACCESS MySQL DATABASE IN THREE TIERS WITH PHP');
4  $smarty->assign('HEADER','WHAT WISH DO ?');
5  $smarty->display('index.tpl');
?>

This script shows how to assign values to variables with Smarty. It calls include.php on line 2.

insert.php
1  <? 
2  require("include.php"); 
3  $smarty->assign('TITLE','INSERT DATA'); 
4  $smarty->assign('HEADER','Insert Data'); 
5  $smarty->assign('data1','First Name');
6  $smarty->assign('data2','Last Name');
7  $smarty->assign('data3','email');
8  $smarty->display('insert.tpl'); 
?>

Much like the previous script, this adds variables that will appear in the insert.tpl template.

save.php
1   <?
2   require_once('DB/DataObject.php');
3   require('configDB.php');
4   $user = DB_DataObject::factory('user');
5   $user->first_Name = $x;
6   $user->last_Name  = $y;
7   $user->email      = $z;
8   $user_Id = $user->insert();
9   $user->update();
10  echo "<script>location.href='index.php'</script>";
11 ?>
This script saves data by using a PEAR::DataObject for the user table. Line 2 loads the class DataObject, and line 3 calls configdb.php to connect to the database. Line 4 creates an instance of a user object (see User.php). Lines 5 through 7 pass the variables collected from the form in insert.tpl ($x, $y, and $z) in order to save the data in the database. The primary key of the table is an autoincrement column, so it doesn't need a value there. Line 8 inserts the object, and line 9 carries out an update.
view.php
1  <? 
2   require_once('DB/DataObject.php');
3   require('configDB.php');
4   require("include.php");
5   $user = DB_DataObject::factory('user');
6   $user->find();
7   while ($user->fetch()) {
8      $smarty->append('users', array(
          'ID'        => $user->user_Id,
          'FIRSTNAME' => $user->first_Name,     
          'LASTNAME'  => $user->last_Name,     
          'EMAIL'     => $user->email,     
       ));
    }
9   $smarty->assign('TITLE','List Users');
10  $smarty->assign('HEADER','List User');
11  $smarty->assign('data0','User_Id');
12  $smarty->assign('data1','First Name');
13  $smarty->assign('data2','Last Name');
14  $smarty->assign('data3','email');
15  $smarty->display('view.tpl');
16  ?>

This script displays all of the data stored in the user table. It loads PEAR::DataObject and include.php (to assign variables of Smarty) that to be shown in the template view.tpl. Line 5 creates a factory of user objects. Line 6 issues a find, which is equivalent to SELECT * FROM user. After selecting the data, it's time to store it for the template via fetch(). This returns one record at a time, which the code stores in a template variable named users, append()ing each row, named by the keys ID, FIRSTNAME, LASTNAME, and EMAIL.

Lines 9 through 14 assign values to other Smarty variables.

All of these .php files should go in the dataobjects directory.

Now for the templates, there are index.tpl, list.tpl, and save.tpl. Here is their code:

index.tpl
1  <html>
2   <head>
3    <title>{$TITLE}</title>
4     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5   </head>
6   <table align="center">    
7    <tr> 
8     <td>
9       <b>{$HEADER}</b>
10    </td>
11   </tr>
12  </table>    
13  <table width="250" border="1" align="center" >
14   <tr> 
16     <td align="center">
17       <input type="button" name="insert" value="Insert"    
           onclick="javascript:location.href='insert.php';">
18    </td>
19   </tr>
20   <tr> 
21     <td align="center">
22      <input type="button" name="view" value="View" 
          onclick="javascript:location.href='view.php';">
23   </td>
24   </tr>
25  </table>
26  </body>
27 </html>

This template is the main page of the system. It shows two variables, $TITLE and $HEADER, in lines 3 and 9, respectively. These values of the variables come from index.php.

Later comes a table with two buttons, Insert and View, which have those respective actions. If the user clicks on Insert, the server invokes insert.php (see line 17). If the user clicks on View, this calls view.php (see lines 3 and 4 of that script).

insert.tpl
1 <html>
2  <head>
3    <title>{$TITLE}</title>
4     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5  </head>
6  <body>
7     <form name="form1" action="save.php" method="post">
8       <table width="300" border="1" align="center" >
9        <tr>
10          <td align="center">
11            <b>{$HEADER}</b>
12         </td>
13       </tr>
14       <tr>
15         <td>
16           {$data1}
17            <input type="text" name="x">
18         </td>
19       </tr>
20       <tr>
21         <td>
22           {$data2}
23            <input type="text" name="y">
24         </td>
25       </tr>
26       <tr>
27         <td>
28           {$data3}
29            <input type="text" name="z">
30         </td>
31       </tr>
32       <tr>
33          <td align="center">
34            <input type="submit" name="Submit" value="Add">
35            <input type="button" name="Reset" value="Return/Cancel"
                 onclick="javascript:location.href='index.php';">
36          </td>
37        </tr>
38      </table>
39    </form>
40  </body>
41 </html>

This template has a form and two buttons, Add and Return/Cancel.

The user enters data for the first name, last name, and email fields (lines 16, 22, and 28). insert.php expects to receive this information in variables named x, y, and z (lines 17, 23, and 29). Clicking on the Add button calls save.php (see line 7) to perform the save. In the contrary case, if the user clicks on Return/Cancel, it executes index.php (line 35).

view.tpl
1 <html>
2  <head>
3    <title>{$TITLE}</title>
4  </head>
5  <body>
6   <table align="center">
7      <tr>
8         <td align="center">
9         <b>{$HEADER}</b>
10       </td>
11     </tr>
12     </table>
13   <table width="500" border="1" align="center">
14   <tr>
16        <td align="center">
17         <b>{$data0}</b>
18       </td>
19        <td align="center">
20         <b>{$data1}</b>
21       </td>
22        <td align="center">
23         <b>{$data2}</b>
24       </td>
25     <td align="center">
26         <b>{$data3}</b>
27       </td>
28     </tr>
29  {section name=display loop=$users}
30     <tr>
31       <td>
32         {$users[display].ID}
33       </td>
34       <td>
35         {$users[display].FIRSTNAME}
36       </td>
37       <td>
38         {$users[display].LASTNAME}
39       </td>
40       <td>
41         {$users[display].EMAIL}
42       </td>
43     </tr>
44     {/section}
45     <br>
46   </table>
47   <br>
48    <table align="center">
49     <tr>
50        <td align="center">
51          <input name="vol" type="button" value="Return"  
               onclick="javascript:location.href='index.php';">
52       </td>
53     </tr>
54   </table>
55  </body>
56 </html>

This template is able to display all of the data stored in the database example.

The first table shows the HEADER of the table, and the second shows data with its respective header (see lines 17, 20, 23, and 26, with the values coming from view.php). Line 29 shows the extraction of data by looping over the users array from view.php to show the values of the user, ID, FIRSTNAME, LASTNAME, and EMAIL fields (lines 32, 35, 38, and 41).

Finally, the Return button sends users back to the home page.

All of the template files (*.tpl) must go in the templates directory.

Conclusion

Working in three tiers with PHP saves repetitive work and makes for maintainable code, partly due to object oriented programming. It's easy to use the powerful Smarty and PEAR::DB_DataObject together.

Luis Yordano Cruz is a systems engineer in Trujillo PERU with more than five years of experience developing web-based applications with PHP, Java/J2EE, and JavaScript.


Return to the PHP DevCenter.


Have you any other techniques for improving application design? Let us know here.
You must be logged in to the O'Reilly Network to post a talkback.
Post Comment
Full Threads Oldest First

Showing messages 1 through 20 of 20.

  • Good article but "magic" code
    2006-06-09 03:31:07  goa103 [Reply | View]

    Thanks for writing such an interesting article. The articles referenced at the beginning were also very enlightening. Here are some comments.

    First I wonder what happened to the example database schema, I had to manually create it when we can read in the "Creating the database" section : « Don't worry about the schema yet; that will come later. ». Here is the database schema exported from PhpMyAdmin :

    CREATE TABLE `user` (
    `user_Id` int(11) NOT NULL auto_increment,
    `first_Name` varchar(30) NOT NULL default '',
    `last_Name` varchar(40) NOT NULL default '',
    `email` varchar(100) NOT NULL default '',
    PRIMARY KEY (`user_Id`)
    ) TYPE=MyISAM AUTO_INCREMENT=5 ;


    Next I found the HTML code a bit messy. Templates should include a global header and footer, and some developers would probably enjoy a cleaner code, without the obsolete tags and tables (even if XHTML/CSS is out of topic). There's even JavaScript code when hyperlinks should be used.

    I also think using "magic" variable names is inappropriate : x and data1 instead of first_Name for example. I think explicit names like first_Name should be used all along, from the database table fields and PHP variables to HTML attributes. It's like magic numbers, magic variable names should be avoided at all cost (3.14 instead of PI for example).

    Let's just say the article is magic :).
  • Better Example
    2005-10-14 01:00:41  bfioca [Reply | View]

    This article, while helpful for learning the intricacies of DB_DataObjects and Smarty, isn't particularly useful for much more than simple projects.

    For much larger scale apps, and true encapsulation of mode, view, and controllers, check out WASP

    http://wasp.sourceforge.net

    For those who don’t yet know, WASP is a lightweight but powerful framework written in the spirit of (but rather different than) Ruby on Rails. The purpose, really, is to utilize all of the enhancements made to PHP in version 5 to build a reusable framework for large applications.
  • Error! Help
    2005-07-26 03:39:37  xfactorx [Reply | View]

    Hello,

    I tried out the tutorials and I had the following errors when I clicked on save and view. Here are the errors:


    Notice: Constant DB_DATAOBJECT_FETCHMODE_ASSOC already defined in C:\php\pear\Db\DataObject.php on line 98

    Notice: Constant DB_DATAOBJECT_INT already defined in C:\php\pear\Db\DataObject.php on line 108

    Notice: Constant DB_DATAOBJECT_STR already defined in C:\php\pear\Db\DataObject.php on line 109

    Notice: Constant DB_DATAOBJECT_DATE already defined in C:\php\pear\Db\DataObject.php on line 111

    Notice: Constant DB_DATAOBJECT_TIME already defined in C:\php\pear\Db\DataObject.php on line 112

    Notice: Constant DB_DATAOBJECT_BOOL already defined in C:\php\pear\Db\DataObject.php on line 113

    Notice: Constant DB_DATAOBJECT_TXT already defined in C:\php\pear\Db\DataObject.php on line 114

    Notice: Constant DB_DATAOBJECT_BLOB already defined in C:\php\pear\Db\DataObject.php on line 115

    Notice: Constant DB_DATAOBJECT_NOTNULL already defined in C:\php\pear\Db\DataObject.php on line 118

    Notice: Constant DB_DATAOBJECT_MYSQLTIMESTAMP already defined in C:\php\pear\Db\DataObject.php on line 119

    Notice: Constant DB_DATAOBJECT_ERROR_INVALIDARGS already defined in C:\php\pear\Db\DataObject.php on line 133

    Notice: Constant DB_DATAOBJECT_ERROR_NODATA already defined in C:\php\pear\Db\DataObject.php on line 134

    Notice: Constant DB_DATAOBJECT_ERROR_INVALIDCONFIG already defined in C:\php\pear\Db\DataObject.php on line 135

    Notice: Constant DB_DATAOBJECT_ERROR_NOCLASS already defined in C:\php\pear\Db\DataObject.php on line 136

    Notice: Constant DB_DATAOBJECT_ERROR_INVALID_CALL already defined in C:\php\pear\Db\DataObject.php on line 137

    Notice: Constant DB_DATAOBJECT_WHEREADD_ONLY already defined in C:\php\pear\Db\DataObject.php on line 143

    Fatal error: Cannot redeclare class db_dataobject_overload in C:\php\pear\Db\DataObject.php(215) : eval()'d code on line 2

    somebody help pls. Btw did anybody got this to work?
  • This is...
    2005-07-03 19:43:12  gremlinx [Reply | View]

    ..quite literally trash.

    The author has includes under the webroot.
    (It would be best if your application directory sat PARALLEL to your template folder, include folders and class files. Also a /conf & a /ini directory PARALLEL to the application pages would be logical.)

    He encourage illogical include practices.
    (Smarty should not need to be copied to your application directory. Easier.. toss it in a folder under your php install and add the path to your include_path setting in php.ini.)

    Second encouraging a user to turn register globals on instead of fixing your code is downright retarded. As is, your examples don't work on any system with short tags off and register globals off.. which in my experience is almost all hosts.

    If anyone wants a zip copy of this in a working fashion with .sql dumps and the table schemas feel free to email me @ Abba.Bryant AT gmail.com
    • This is...
      2005-11-26 23:20:39  infolock [Reply | View]

      ignorance is bliss...

      obviously, this article isn't only meant for advanced users and production sites. It's meant as a stepping stone, not as a "DO THIS AND ONLY THIS".

      Retards like you are why I never post tutorials. Because you are just looking for anything to say "HEY, LOOK AT ME! I can bash people without even considering my thoughts!"

      Write an article, then come back. Because when you do, you can rest-assure that I will be bashing you homie.
  • Not very infomative
    2005-05-23 23:51:31  dxxchung [Reply | View]

    Thank you for such excellent work.
    I am a beginner. This is a very good case. I have not seen any other tutorials that chain up the input, view, save sreens and the codes together using php and mysql. But I cannot follow some of the codes not in linux format in autobuilding a database schema ie generating User.php. All I have to say is that your work is very informative.
    • Not very infomative
      2005-05-31 23:57:14  dxxchung [Reply | View]

      I finally found out what had been missing in your model.

      Firstly, add the following lines to pass variables in save.php
      $x=$_POST["x"];
      $y=$_POST["y"];
      $z=$_POST["z"];
      Secondly, add a program, which I called schemagen.php.
      <?php
      //
      // Builds the DataObjects classes
      $_SERVER['argv'][1] = 'example.ini';
      require_once 'DB/DataObject/createTables.php';
      ?>
      I have seen this article translated and posted in simplified Chinese in several sites. Anyway, your model will become the backbone of my first commercial project.
  • Not very infomative
    2005-05-05 14:53:19  mattneedles [Reply | View]

    This article is vague and not very informative. The author dwells on displaying header, footer, cancel button but does not clearly state how the initial setup is done. For that mattter, "Simplify Business Logic with PHP DataObjects" by Darryl Patterson is more informative and easy to understand:

    http://www.onlamp.com/pub/a/php/2004/08/05/dataobjects.html

    Is there a way to unplug the DB object as it is only an abstraction layer for the database to address situations where the database vendor is changed in future? The chances of switching the database is mostly nil and the additional DB layer only slows down the process. Despite the DB_DataObjects being built on top of DB object, it seems like we still have to construct our own result set in the above example which is redundant:

    $user->find();
    while ($user->fetch()) {
    $smarty->append('users', array(
    'ID' => $user->user_Id,
    'FIRSTNAME' => $user->first_Name,
    'LASTNAME' => $user->last_Name,
    'EMAIL' => $user->email,
    ));

    I wish this article on DB_DataObjects was written by Darryl Patterson as he said he might write it in future.
    • Not very infomative
      2005-05-06 07:58:54  lycruzc [Reply | View]

      Excuse me, but you cannot say that is vague this article, for which I see You are a novice in PHP and does not know : The Framework PEAR, Smarty and the Development in Three Tier.
      • Not very infomative
        2005-05-06 14:34:38  mattneedles [Reply | View]

        You haven't any idea as to who I'm, what I do or what I've achieved with Smarty and 3-tier architecture. I've successfully unplugged the DB from DB_DataObjects to use raw PHP functions for MySQL database access for improving performance on high-traffic sites.

        Forget about the PEAR framework, Smarty, 3-tier... how about the basic PHP? Advising another user to set:

        register_globals=OFF => register_globals= ON

        does not make you a guru in PHP in the first place.


        Here is the usage documentation on DB_DataObjects:

        http://pear.activeventure.com/package/package.database.db-dataobject.html


        I wonder who has approved your article on OnLamp.

        Excuse you!
        • Not very infomative
          2007-01-31 07:14:21  greenphpcoder [Reply | View]

          Thats brill but why do all that, everyone knows that HTML, its the future!
        • Not very infomative
          2005-11-26 23:24:27  infolock [Reply | View]

          "You haven't any idea as to who I'm, what I do or what I've achieved with Smarty and 3-tier architecture. I've successfully unplugged the DB from DB_DataObjects to use raw PHP functions for MySQL database access for improving performance on high-traffic sites."


          If you did what you are saying you did, you obviously are a novice. Novices use the approach of raw php functinos for mysql database access. Thus why you get haxx0red by the kiddies.

          You remind me of gremlin. He seems to have the same mentality as you : mind-numbing.
        • Not very infomative
          2005-05-06 18:46:51  lycruzc [Reply | View]

          The best form to say you know is to show it; not alone saying that know it. Then it writes an article and shows what you know for OnLamp; utilizing PHP 5.

          Excuse you!
  • Sorry to be picky but...
    2004-12-28 02:59:06  HarryF [Reply | View]

    Like the article overall and great to see layered application design being encouraged. Have to scratch some itches though...

    Please modify the examples on the second page so they use full PHP processing instruction declarations i.e.;


    <?php
    </code>

    not;


    <?
    </code>

    In php.ini there's an option called "short_open_tag". The later form; <?</code> is only possible when short_open_tag is On, so the examples will not work for those that have it switched off, potentially reducing the portability of the code, across different PHP installations.

    Also include, require, require_once etc. are language constructs not functions so although the parenthesis is allowed, it's generally better form to write;


    include 'somefile.php';


    It's also better practice (ignoring any performance issues) to always use require_once when including class files, to take care of the situations where, say, multiple child classes in seperate files all attempt to include the same parent class script.
  • use _POST for x, y, z
    2004-12-15 10:50:59  yasheshb [Reply | View]

    in the file save.php use _POST to reference the form variables. using $x, $y, $z did not work for me.

    5 $user->first_Name = $_POST['x'];
    6 $user->last_Name = $_POST['y'];
    7 $user->email = $_POST['z'];
    • use _POST for x, y, z
      2004-12-15 15:41:08  lycruzc [Reply | View]

      Hi friend, for that work without _POST; You should activate the var :

      register_globals=OFF => register_globals= ON

      This variable this in the file of configuration of PHP (php.ini).
      • use _POST for x, y, z
        2005-03-14 12:08:48  eriksays [Reply | View]

        no no no no.

        register_globals = ON is a SERIOUS SECURITY VIOLATION that can allow a user to hijack the session data with their own variables.

        keep register_globals = OFF and just use $_POST or $_GET to grab your form variables.
        • use .htaccess for x, y, z
          2006-06-09 02:56:40  goa103 [Reply | View]

          I second your remark but for this article it's possible to avoid modifying a single line of code by using a simple .htaccess file with the following lines in it :
          php_flag magic_quotes_gpc off
          php_flag register_globals on
  • Smarty LGPL
    2004-12-13 17:07:58  sameon [Reply | View]

    Smarty is LGPL and not GPL. I think this tutorial can be done in PHP 4.

    Smarty, PEAR_DB and DB_DataObject support PHP 4
  • PHP5?
    2004-12-12 05:24:15  Shurik [Reply | View]

    This article, PEAR::DB_DataObject, Smarty does not deal with PHP5.


Tagged Articles

Post to del.icio.us

This article has been tagged:

php

Articles that share the tag php:

Understanding MVC in PHP (477 tags)

The PHP Scalability Myth (123 tags)

The Dynamic Duo of PEAR::DB and Smarty (53 tags)

PHP Form Handling (43 tags)

Very Dynamic Web Interfaces (39 tags)

View All

webdev

Articles that share the tag webdev:

Rolling with Ruby on Rails (351 tags)

Very Dynamic Web Interfaces (163 tags)

Understanding MVC in PHP (96 tags)

A Simpler Ajax Path (93 tags)

Ajax on Rails (61 tags)

View All

programming

Articles that share the tag programming:

Rolling with Ruby on Rails (1374 tags)

Very Dynamic Web Interfaces (279 tags)

Ajax on Rails (231 tags)

Understanding MVC in PHP (202 tags)

A Simpler Ajax Path (186 tags)

View All

pear

Articles that share the tag pear:

The Dynamic Duo of PEAR::DB and Smarty (37 tags)

Programming eBay Web Services with PHP 5 and Services_Ebay (12 tags)

Three-Tier Development with PHP 5 (6 tags)

PHP's PEAR on Mac OS X (6 tags)

Caching PHP Programs with PEAR (6 tags)

View All

php5

Articles that share the tag php5:

Understanding MVC in PHP (17 tags)

Programming eBay Web Services with PHP 5 and Services_Ebay (5 tags)

Three-Tier Development with PHP 5 (5 tags)

Using PHP 5's SimpleXML (4 tags)

Why PHP 5 Rocks! (2 tags)

View All

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com