Oracle and PHP
Oracle and PHP
Zend Technologies
Library Zend Whitepaper PHP and Oracle
2
Zend Background Paper
http://framework.zend.com/roadmap/ The first thing we added is the require_once in line 3. This in-
Controller: RoadmapController cludes the source file in which the Model is defined. Then, in the
Action : indexAction init() function which is called when the controller object is
created, an instance of the HRModel is made and stored in the
http://framework.zend.com/ instance variable hrModel that was previously declared. The
Controller: IndexController PHPDoc comment before the variable declaration gives the Zend
Action : indexAction Studio IDE the information needed to provide code completion
for the instance variable hrModel. After this, an hrModel object
More Action Controllers is present in the IndexController and can be used by any
Now other Action Controllers can be written and placed in the ActionMethod by referencing $this->hrModel. We try this in the
controller directory. They are all built in the same way as the indexAction: We call the helloWorld Method we have implemented
IndexController described above. For more information on making in our hrModel and output the returned value to the browser
the assignment from URLs to controllers more flexible see the using the echo command of php (later we will render all output
documentation at http://framework.zend.com via so called views to separate logic from layout but for now this
should do).
Creating a Model If we now call the home page of our web application, the output
In MVC, all the actual work the application is supposed to do is will be as follows:
implemented in a special class called 'Model' (the 'M' in MVC). Browser:
This includes all database operations. The Action Controller http://www.myserver.com/
instantiates a Model and then calls functions on it. To visualize Result:
this, let us first start with creating an empty Model class: Hello World
.../models/HRModel.php:
Connecting the DB
<?php Since our application will display database content, we will need
class HRModel { a database connection to get to the required information. As an
function helloWorld() { example we use the predefined HR schema that comes with
return 'Hello World'; Oracle XE and the normal Oracle installation as an example
} schema. (Please make sure to unlock the Oracle user called HR
} first and assign it the password hr.)
?> To connect to a DB from Zend Framework, we use a class called
DB Adapter. It can be found in the Package Zend_Db in the
Now we have a (very simple) Model with a function that returns
Framework distribution. We will also need some credentials to
something that can be output to the browser. So let us use it in
connect to the database. We assume that we use the DB on the
the Controller. Since we will probably have many methods in our
local host and login with username and password 'hr'. So where
controller that are all very likely to call methods on our Model,
do we put the connection code? Since the Model will use the DB
we instantiate the Model right at the beginning of the lifetime
connection in most of its methods, it makes sense to open a
of our controller and store it for later use in an instance variable
connection whenever the Model is instantiated. Therefore we
for the action controller object:
put the connection code into the constructor of the Model and
.../app/controllers/IndexController.php: store the connection in an instance Variable of our Model. To
check if the connection was successful, we implement a new
<?php
Method in our Model that fetches the Sysdate from the oracle
require_once('Zend/Controller/Action.php');
instance and replace our nice but useless helloWorld function
require_once('models/HRModel.php');
with it:
.../models/HRModel.php:
{
<?php
/**
require_once('Zend/Db.php');
* @var HRModel
*/
class HRModel {
protected $hrModel;
/**
* @var Zend_Db $db public function init() {
*/ $this->hrModel = new HRModel();
protected $db = null; }
6
Zend Background Paper
<tr> statement. The bracket notation could also be used here but the
<td align="right">$EMPLOYEE_ID</td> alternative notation seems better inside templates.
<td>$EMPLOYEE_NAME</td> The foreach block is executed once per row in the employeeList
<td>$JOB_TITLE</td> variable, meaning once per result row. Inside the block, the
<td>$HIRE_DATE</td> current row can be referenced via the variable $emp. The
<td align="right">$SALARY</td> individual columns of the result row could now be referenced by
<td align="right">$COMMISSION_PCT</td> using their names as an index to the array $emp. For example
<td align="right">$DEPARTMENT_NAME</td> $emp['EMPLOYEE_NAME'] would reference the name column from
</tr> the current row.
END; To make references to the fields of the result row simpler, we
endforeach; use the extract() command of php on $emp. This command creates
?> one local variable for every key in the given array and copies the
</table> associated value in this new variable. Instead of using
</body> $emp['EMPLOYEE_NAME'] it is then possible to reference the name
</html> by simply using $EMPLOYEE_NAME.
After the extract command we use the HEREDOC syntax of PHP
In addition to the basic view script that only displays the sysdate, to echo one table row to the browser. This notation allows multi
some changes were introduced here. At first, we added a link to line strings in which variables are automatically replaced by their
a style sheet named style.css that improves the layout a little: values. Also, quotation marks and other special characters can
.../htdocs/styles.css: be used without the need to escape them inside a string. The
string to echo ends with and END marker at the beginning of a
body { new line. Calling our home page now results in a employee list:
background: #CCCCFF; Browser:
color: #000000; http://www.myserver.com/
font-family: Arial, sans-serif; Result:
}
h1 {
border-bottom: solid #334B66 4px;
font-size: 160%;
}
table {
width: 100%;
font: Icon;
border: 1px Solid ThreeDShadow;
background: Window;
color: WindowText;
}
td {
padding: 2px 5px;
vertical-align: top;
text-align: left;
}
th {
border: 1px solid; Editing an Employee
border-color: ButtonHighlight ButtonShadow Now that we have a list, we might want to display a record in
ButtonShadow ButtonHighlight; detail and edit its contents. For example we could want to add
cursor: default; a commission or to change department, job title or telephone
padding: 3px 4px 1px 6px; number. To do so, we first need a link to a new action called
background: ButtonFace; editForm in the List. When the user clicks on the id of an employee,
} he gets to a form with the details of the according user. So first
Further, we integrated a HTML table that will show the result we add the new link. This can be done in the View Script:
list. This table has a first row with column titles in plain HTML.
Then for the output of the actual row content, we switch to PHP
mode in the view script (<?php). Using the foreach control structure
of PHP, we iterate over the employeeList array which had been
stored in the view object by the Controller Action before.
To make the loop more visible inside the HTML fragments in this
file, we do not use the normal bracket notation to denote the
foreach-block but we use an alternative format. This format
starts the block with a colon and ends it with the endforeach
7
Zend Background Paper
.../app/controllers/IndexController.php: At first, we switch to PHP mode in this view script to extract the
associative array from $this->employeeDetail into the local scope.
<?
This way, all the different fields of the currently edited record
require_once ...
are accessible via variables with the name of the according DB
class IndexController extends Zend_Controller_Action
field (as seen already in the employeeList). The we start with
{
linking our style sheet again and opening a normal HTML form.
...
The form action will be index/save, a new action that we must
public function editAction() {
integrate in our IndexController. The rest of the page is all like
$id = (int)$this->_getParam('id');
a normal HTML form with the exception that all the input fields
$view = new Zend_View(array('scriptPath' =>
are generated dynamically via so called View Helpers. These
<pathToMyApp>/app/views'));
helpers are a library of methods that the Zend_View provides for
$view->employeeDetail = $this->hrModel->findRecord($id);
rendering certain HTML tags. In this example we use $this-
echo $view->render('edit.phtml');
>formHidden() to generate a hidden field and $this->formText()
}
to generate normal text input fields. The first parameter to these
}
Helpers is always the name of the input field and the second
?>
parameter is the current value. Information about other field
The action method now stores the result of the findRecord call types can be obtained from the Zend Framework Website.
in the view object and then uses the view script called 'edit.phtml' Now we code the saveAction to store the changed values in the
to render the form. Now we code edit.phtml: database. This is done again in the IndexController. In order to
do this we must first add an update function to the hrModel. This
.../app/views/edit.phtml:
will take an EMPLOYEE_ID and an associative array of fieldnames
<?php and values and generate an update query.
extract($this->employeeDetail);
.../app/models/HRModel.php
?>
<HTML> <?php
<head> require_once...
<link rel="stylesheet" type="text/css" href="/style.css" /> class HRModel {#
</head> ...
<body> /**
<form method="post" action="/index/save"> * update all fields that are present in the assoc array
<?= $this->formHidden('EMPLOYEE_ID',$EMPLOYEE_ID) ?> * $row for the employee given in $eid
<table> *
<tr> * @param int $eid
<td>First Name</td> * @param array $row
<td><?= $this->formText('FIRST_NAME',$FIRST_NAME) ?></td> * @return int Number of affected rows
</tr> */
<tr> public function update($eid, $row) {
<td>Last Name</td> $where = $this->db->quoteInto('EMPLOYEE_ID = ?', $eid);
<td><?= $this->formText('LAST_NAME',$LAST_NAME) ?></td> return $this->db->update('employees', $row, $where);
</tr> }
<tr> }
<td>E-Mail</td> ?>
<td><?= $this->formText('EMAIL',$EMAIL) ?></td>
To accomplish this task, we use the update function of the
</tr>
Zend_DB Adapter. It requires a table name, an associative array
<tr>
of key/value pairs for the updated values and a where clause to
<td>Hiredate</td>
determine which records to update. The where clause must first
<td><?= $this->formText('HIRE_DATE',$HIRE_DATE) ?></td>
be generated by inserting the given employee-id into a query
</tr>
fragment with placeholders. The where clause is generated this
<tr>
way to enable the DB Adapter to quote the value of $eid correctly
<td>Salary</td>
for the given database. This prevents SQL injection attacks in the
<td><?= $this->formText('SALARY', $SALARY) ?></td>
where clause. The other values are quoted in the update method
</tr>
of the DB adapter.
<tr>
After we have added the needed functionality to the Model, we
<td>Commission (%)</td>
can now extend our IndexController to fetch the data from the
<td><?= $this->formText('COMMISSION_
HTML form, store it in the array that the update function needs
PCT',$COMMISSION_PCT) ?></td>
and call the update function in the Model:
</tr>
</table>
<input type="submit" value="Save" name="save">
<input type="submit" value="Cancel" name="cancel">
</form>
</body>
</HTML>
9
Zend Background Paper
.../app/controllers/IndexController.php Epliogue
<? We have seen in this session how to install Zend Framework and
require_once ... how to build a simple web application with it based on the HR
class IndexController extends Zend_Controller_Action schema that comes with every Oracle installation as an example
{ database schema. Our sample application lists all employees and
... offers a way to edit and save employee records with a simple
function saveAction() { form. This shows some of the basic functions and components of
// read input variables (should be checked in real application) Zend Framework. To turn this rough example into a usable
$row = array(); application, a number of additional things would be needed:
$row['FIRST_NAME'] = $_POST['FIRST_NAME'];
$row['LAST_NAME'] = $_POST['LAST_NAME']; - First of all the save method needs to be extended to do input
$row['EMAIL'] = $_POST['EMAIL']; validation on the submitted fields.
$row['HIRE_DATE'] = $_POST['HIRE_DATE']; - Some fields from the database were left out in this example
$row['SALARY'] = $_POST['SALARY']; application because they require some more coding. These
$row['COMMISSION_PCT'] = are the fields DEPARTMENT_ID and JOB_ID which should be
number_format($_POST['COMMISSION_PCT']/100,2,',','.'); implemented as drop down boxes with all rows from the
$this->hrModel->update($_POST['EMPLOYEE_ID'],$row); according database tables as options.
$this->indexAction(); - There is a trigger in the database that requires to update the
}} field HIRE_DATE to the current date whenever JOB_ID or
?> DEPARTMENT_ID are changed. This logic would also need to
be implemented.
Please note that this action contains no input filtering or validation. - Apparently, a function to add new Employees would be needed
In a real world application you would use the Zend_Validate and and a delete function would also make sense.
Zend_Filter or other components to check all the data fields from - The structure could be further optimized by extracting the
the $_POST array with a white list approach before using them SCRIPT_PATH variables from the source code lines in which
in the application to prevent hacking. And also you would want view objects are instantiated. These path information as well
to check if the values submitted by the user and re-display the as the Controller Path in the index.php should be taken from
form with according error message if the user entered invalid an ini file.
data or left required fields blank. This has been left out here to
keep the example simple. In the current preview release of Zend Although there is much room for improvement, this little example
Framework there is no standard form component in Zend shows how a structured PHP application can be built with the
Framework yet that helps you with this part. Such a component help of Zend Framework. The standard application structure and
is under development and will be available in future versions of naming conventions help to build the application in the right
Zend Framework. After copying all input values from the POST way. This gives other developers the chance to start quickly into
request to the new associative array $row, the action method application development when they join the project later and
passes this array along with the EMPLOYEE_ID to the update makes maintenance and extending the project much easier and
Method of the hrModel. After a successful update the index action more efficient.
is called which results in re-displaying the Employee-List.
For further details about Zend Framework look at
http://framework.zend.com
10
Zend Background Paper