Professional Documents
Culture Documents
ZFC Study Guide v1 PDF
ZFC Study Guide v1 PDF
CERTIFICATION
STUDY GUIDE
The certification was designed by the Zend Framework Education Advisory Board, an
elite, global set of web application development experts (across a variety of companies)
who established the criteria for knowledge and job task competencies and developed
the related questions that assess Zend Framework expertise.
The Process
In order to become certified in the use of Zend Framework (ZF), you will need to
successfully pass an examination. The exam is administered world-wide by Pearson
Vue. You will be required to take the exam at one of their Vue Testing Centers, available
in over 3500 locations around the world. The exam is taken in an isolated room, using a
specially configured computer, and is closed-book, so you will not be able to consult
any reference material or use the Internet while taking it.
The Exam
The ZF Certification exam itself is very similar to most other IT exams offered, including
the exam for Zend PHP 5 Certification. The exam is composed of approximately 75
randomly-generated questions, which must be answered in 90 minutes. Each question
can be formulated in one of three ways:
As a multiple-choice question with only one right answer
As a multiple-choice question with multiple correct answers
As a free-form question for which the answer must be typed in
The 14 areas of expertise created by the ZF Certification Education Advisory Board are:
The Guide therefore presents a concise treatment of the 14 required knowledge areas
for certification, with reminders and hints on some essential aspects of the
components. It is by no means a complete discussion of the entire framework, nor a
complete presentation of everything you might find on the exam. It is a guide to the
types of facts and coding practices that are considered essential for passing the exam.
Guide Structure:
Each of the 14 topic areas tested by the ZF Certification exam will have three associated
sections within the Study Guide.
First is the Topic Snapshot view, which provides a visual framework of the sub-topics
considered required knowledge for each major topic, and highlighted knowledge areas
within each. They serve as guides, or hints do you understand how these elements
relate to the topic? Could you answer basic to advanced questions on these?
Next follows a more in-depth discussion of these various target areas (Focus section).
In order to avoid repetition, and make the discussion more logical, the content is
presented in an integrated fashion. So, the content for areas that are listed multiple
times under the sub-topics (Ex: Front Controllers) will appear only once.
Finally, at the end of each topic will be a couple of representative questions, similar to
those you will find on the examination. You might choose to take these questions after
looking at the Snapshot, if you feel confident that you know the exam topic well, or you
can take these questions as a wrap-up to your studying the Focus area content.
If, in working through this guide, you discover that you are weak in some areas, you
should utilize the online Programmers Reference Guide to Zend Framework, available
at http://framework.zend.com/manual. This extensive documentation presents highly
detailed discussions on various topics along with multiple code examples. Please note
that any suggestion within this guide to consult the "Reference Guide" is referring to
this document.
If you would like more practice in answering questions about the exam, including
taking a simulated exam, and have a live instructor to answer your questions and guide
your preparation studies, consider taking Zends online Zend Framework Certification
course.
Zend_Auth
Zend_Acl
Rules
First, it is important that you are able to distinguish between the two functions:
Authentication is the process of verifying a users identity against some set of pre-
determined criteria are they who they claim to be?
Authorization is the process of assigning rights to the user based on their identity
they are entitled to do the following actions because of who they are
Zend Framework provides components for both functions Zend_Auth and Zend_Acl.
ZEND_AUTH
Zend_Auth provides an API for authentication and includes adapters for the most commonly
used scenarios.
o Singleton pattern means only one instance of the class is available at any one time
o The new operator and the clone keyword will not work with this class use
Zend_Auth::getInstance() instead
The adapters authenticate against a particular service, like LDAP, RDBMS, etc.; while their
behavior and options will vary, they share some common actions:
o return results
Identity Persistence
An important aspect of the authentication process is the ability to retain the identity, to have
it persist across requests in accordance with the PHP session configuration. This is
accomplished in ZF with the method Zend_Auth::authenticate(). The default storage
class is Zend_Auth_Storage_Session (which uses Zend_Session ). A custom class can
be used instead by creating an object that implements Zend_Auth_Storage_Interface
and passing it to Zend_Auth::setStorage().
Persistence can be customized by using an adapter class directly, foregoing the use of
Zend_Auth entirely.
ZEND_AUTH
Authentication Results
Zend_Auth adapters return an instance of Zend_Auth_Result with authenticate() to
represent the results of an authentication attempt. The Zend_Auth_Result object exposes the
identity that was used to attempt authentication.
ZEND_ACL
Zend_Acl provides a lightweight and flexible Access Control List (ACL) feature set along with
privileges management, generally via the use of request objects and protected objects.
Zend_Acl can be easily integrated with ZF MVC components through use of an Action Helper
or Front Controller Plugin. Keep in mind that this component is only involved with authorizing
access, and does not in any way verify identity (that process is authentication, in ZF
accomplished with Zend_Auth).
By using an ACL, an application controls how request objects (Roles) are granted access to
protected objects (Resources). Rules can be assigned according to a set of criteria see
Assigning Rules via Assertions later in this document. Combining the processes of
authentication and authorization is commonly called access control.
Creating An ACL
Creating an ACL utilizing Zend_Acl is easy, as shown in the sample code below:
<?php
require_once 'Zend/Acl.php';
Creating Resources
Creating a resource is a simple process - a class needs only implement the
Zend_Acl_Resource_Interface, consisting of the single method getResourceId(), in
order for Zend_Acl to consider the object a Resource. Zend_Acl_Resource is provided as
a basic implementation for extensibility.
ZEND_ACL
Creating Roles
In a process similar to Resource creation, a class only has to implement the
Zend_Acl_Role_Interface, consisting of the single method getRoleId(), for
Zend_Acl to consider the object a Role. Zend_Acl_Role is provided as a basic
implementation for extensibility.
Inheritance - Resources
Zend_Acl provides a tree structure onto which multiple resources can be added. Queries on
a specific resource will automatically search the Resources hierarchy for rules assigned to its
parent Resources, allowing for simple inheritance of rules.
Note that a Resource can inherit from only one parent Resource, although that parent can
trace back to its own parent, and so on.
Inheritance - Roles
Unlike Resources, in Zend_Acl a Role can inherit from one or more Roles to support the
inheritance of rules. While this ability can be quite useful at times, it also adds complexity to
inheritance. In the case of multiple inheritance, if a conflict arises among the rules, the order
in which the Roles appear determine the final inheritance - the first rule found via query is
imposed.
a. cyclic
b. multiple
c. no
d. single
a. True
b. False
a. cyclic
b. multiple
c. no
d. single
a. True
b. False
Coding Conventions
You should know general coding standards for using PHP (Ex: tags, code demarcation, syntax
for strings, & arrays, ) as well as accepted naming conventions.
You should know the rules, guidelines, and code standards established for the Zend
Framework.
Never use the closing tag ?> for files that contain only PHP code this prevents trailing
whitespace from being included in the output
Maximum line length is 120 characters, with the goal limit of 80 characters for clarity
Lines should be terminated with a linefeed (LF, ordinal 10, hexadecimal 0x0A), not a
carriage return or a carriage return/linefeed combination
Naming Conventions
Class Names
Multiple-word names: in general, each word contains a capitalized first letter, with the
remaining letters lowercase (Ex: Zend_Pdf); there are exceptions, as when a word is an
acronym or somehow non-standard (Ex: Zend_XmlRpc)
Classes authored by ZF or its Partners must start with Zend_ and must be stored under
the Zend/ directory hierarchy; conversely, any code not authored by Zend or its
Partners must never start with Zend_
Interfaces
Interface classes must follow the same conventions as other classes (outlined above),
and end with the word "Interface" (Ex: Zend_Log_Adapter_Interface)
Filenames
For all files, only alphanumeric characters, underscores, and the hyphen character ("-")
are permitted; spaces are prohibited
Any file that contains any PHP code should end with the extension ".php", with the
exception of View Scripts
Function Names
Can only contain alphanumeric characters; underscores are not permitted; numbers are
discouraged
Multi-word names: the first letter of the first word is lowercase, the first letter of each
subsequent word must be capitalized, known as "camelCase"
(Note: use of functions in the global scope are discouraged; wrap these functions in a
static class instead)
Method Names
For methods declared with a private or protected construct, the first character of the
variable name must be a single underscore (the only time an underscore is permitted in a
method name)
Variable Names
Can only contain alphanumeric characters; underscores are not permitted; numbers are
discouraged
Must always start with a lowercase letter and follow the camelCase formatting rules
For class member variables declared with a private or protected construct, the first
character of the variable name must be a single underscore (the only time an underscore
is permitted in a variable name)
Constants
Can contain alphanumeric characters, underscores, and numbers
Multi-word names: must separate each word with an underscore (Ex: EMBED_SUPPRESS)
Coding Style
PHP code must be delimited by the full-form, standard PHP tags: <?php and ?>
Strings - Literals
When a string is literal (containing no variable substitutions), the apostrophe or "single
quote" must be used to demarcate the string (Ex: $a = Example String; )
When a literal string itself contains apostrophes, the string can be demarcated with
quotation marks ; this is especially encouraged for SQL statements
Strings - Concatenation
Strings may be concatenated using the "." operator; a space must always be added
before and after the "." operator to improve readability (Ex: 'Zend'.' '.'Tech')
Can break the statement into multiple lines to improve readability; each successive line
should be padded with whitespace so that the "."; operator is aligned under the
"=" operator (Example: $sql = "SELECT 'id', 'name' FROM 'people' "
. "WHERE 'name' = 'Susan' "
. "ORDER BY 'name' ASC ";
Can start with a non-negative number, but discouraged; better to use a base index of 0
When declared with the array construct, a trailing space must be added after each
comma delimiter for readability (Example: $anyArray = array(1, 2, 'Zend');)
For multi-line indexed arrays using the array construct, each successive line must be
padded with spaces so that the beginning of each line aligns as shown:
Arrays - Associative
When declared with the array construct, the statement should be broken into multiple
lines; each successive line must be padded with whitespace so that both the keys and
the values are aligned, as shown:
Classes - Declaration
The brace is always written on the line underneath the class name ("one true brace" form)
Placing additional code into a class file is discouraged; if utilized, two blank lines must
separate the class from additional PHP code in the file (Example: Class Declaration)
/**
* Documentation Block Here
*/
class SampleClass
{
// entire content of class must be indented four spaces
}
Member variables must be named following variable naming conventions (see Naming
section)
Variables declared in a class must be listed at the top of the class, prior to declaring any
methods
The var construct is not permitted; member variables always declare their visibility by
using one of the private, protected, or public constructs
Methods inside classes must always declare their visibility by using one of the private,
protected, or public constructs
The brace is always written on the line underneath the function name ("one true brace"
form) ; no space between the function name and the opening argument parenthesis
/**
* Documentation Block Here
*/
class Foo
{
/**
* Documentation Block Here
*/
public function bar()
{
// entire content of function
// must be indented four spaces
}
}
Functions arguments are separated by a single trailing space after the comma delimiter
For functions whose arguments permit arrays, the function call may include the "array"
construct and can be split into multiple lines to improve readability;; standards for
writing arrays still apply; Ex:
Control statements based on the if and else if constructs must have a single space
before the opening parenthesis of the conditional, and a single space after the closing
parenthesis
The opening brace is written on the same line as the conditional statement; closing brace
is always written on its own line; any content within braces must be indented four spaces
if ($a != 2) {
$a = 2;
}
For "if" statements that include "else if " or "else", the formatting conventions are
as shown in the following examples:
if ($a != 2) { if ($a != 2) {
$a = 2; $a = 2;
} else ( } else if ($a == 3) {
$a = 7; $a = 4;
} } else {
$a = 7;
}
Switch
Control statements written with the "switch" construct must have a single space before
the opening parenthesis of the conditional statement, and a single space after the
closing parenthesis
All content within the "switch" statement must be indented four spaces; content under
each "case" statement must be indented an additional four spaces
All source code files written for Zend Framework or that operate with the framework
must contain a "file-level" docblock at the top of each file and a "class-level" docblock
immediately above each class
Every file that contains PHP code must have a header block at the top of the file that
contains these phpDocumentor tags at a minimum:
/**
* Short description for file
*
* Long description for file (if any)...
*
* LICENSE: Some license information
*
* @copyright 2005 Zend Technologies
* @license http://www.zend.com/license/3_0.txt PHP License 3.0
* @version $Id:$
* @link http://dev.zend.com/package/PackageName
* @since File available since Release 1.2.0
*/
Similar to Files, every class must have a docblock that contains these phpDocumentor
tags at a minimum - Descriptions, @copyright, @license, @version,
@link, @since, @deprecated
Every function, including object methods, must have a docblock that minimally contains:
a function description; all the arguments; all possible return values
Not necessary to use the @access tag because the access level is already known from
the public, private, or protected construct used to declare the function
Zend_Db_Table
Zend_Db
Zend_Db_Statement
Zend_Db_Select
Zend_Db_Table
You should be able to create and work with Zend_Db component extensions, such as
_Adapter, _Statement, _Table, and _Library.
You should know how to connect to a database, in particular using constructor arguments
and lazy connections.
You should know how to specify database configurations within a Configuration file.
You should be able to fetch data in rows, columns, and individually, and be able to utilize
different fetch modes. This includes the ability to fetch data from content returned by
executing a statement. You should know how to construct complex queries.
You should be able to manipulate data within a database (insert, modify, delete).
You should know what a Fluent Interface is, including how and when to use it.
Methods:
You should know how to insert application logic into the appropriate method.
You should know how and when to use the quoteIdentifier method.
ZEND_DB
Zend_Db and its related classes provide a simple SQL database interface for Zend Framework.
Connecting to a Database
<?php
require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
Using Zend_Db::factory
The Factory method of connection is an alternative to the use of the Constructor. Instead, the
Adapter instance is created using the static method Zend_Db::factory(), which
dynamically loads the Adapter class file on demand utilizing
Zend_Loader::loadClass().
<?php
require_once 'Zend/Db.php';
ZEND_DB
If you create your own class that extends Zend_Db_Adapter_Abstract, but you do not
name your class with the "Zend_Db_Adapter" package prefix, you can use the factory()
method to load your Adapter, providing you specify the leading portion of the adapter class
with the 'adapterNamespace' key in the parameters array.
<?php
require_once 'Zend/Config.php';
require_once 'Zend/Db.php';
$db = Zend_Db::factory($config->database);
ZEND_DB
<?php
$options = array(
Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
);
$params = array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test',
'options' => $options
);
To force the Adapter to connect to the RDBMS, use the getConnection() method,
which returns an object for the connection represented by the required PHP database
extension. For example, using any of the Adapter classes for PDO drivers will result in
getConnection() returning the PDO object, after initiating it as a live connection to
the specific database. Forcing a connection can be a useful tool in capturing
exceptions thrown by RDBMS connection failures (Ex: invalid account credentials).
It can be useful to force the connection if you want to catch any exceptions it throws
as a result of invalid account credentials, or other failure to connect to the RDBMS
server. These exceptions are not thrown until the connection is made, so it can help
simplify your application code if you handle the exceptions in one place, instead of at
the time of the first query against the database.
ZEND_DB
Fetching Data
(Note: examples in this section use the ZF Sample Bug-Tracking Database, shown in the Programmers Guide)
You can run a SQL SELECT query and retrieve its results in one step using the fetchAll()
method. The first argument to this method is a string containing a SELECT statement.
Alternatively, the first argument can be an object of class Zend_Db_Select. The Adapter
automatically converts this object to a string representation of the SELECT statement.
<?php
Zend_Db::FETCH_BOTH
returns data in an array of arrays; the keys are strings used in the FETCH_ASSOC mode, and
integers as used in the FETCH_NUM mode
Zend_Db::FETCH_COLUMN
returns data in an array of values, where each value is returned by one column of the result
set; by default, the first column is used and indexed by 0
Zend_Db::FETCH_OBJ
returns data in an array of objects; the default class is the PHP built-in class stdClass;
columns of the result set are available as public properties of the object
ZEND_DB
<?php
$db->setFetchMode(Zend_Db::FETCH_OBJ);
Inserting Data
New rows can be added to a table in the database using the insert() method. The first
argument is a string naming the table, the second argument an associative array mapping
column names to data values. Example:
<?php
$data = array(
'created_on' => '2007-03-22',
'bug_description' => 'Something wrong',
'bug_status' => 'NEW'
);
$db->insert('bugs', $data);
ZEND_DB
Using quote()
The quote() method accepts a single argument, a scalar string value returned with special
characters escaped according to the RDBMS being used, and surrounded by string value
delimiters. The SQL string value delimiter for MySQL is the single-quote (').
<?php
$name = $db->quote("O'Reilly");
echo $name;
// 'O\'Reilly'
echo $sql;
// SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
Using quoteInto()
You can use the quoteInto() method to interpolate a PHP variable into a SQL
expression or statement. It takes two arguments: the first is a string containing a
placeholder symbol (?), and the second is a value or PHP variable that should be
substituted for that placeholder.
The placeholder symbol is the same symbol used by many RDBMS brands for
positional parameters, but the quoteInto() method only emulates query
parameters. The method simply interpolates the value into the string, escapes special
characters, and applies quotes around it. True query parameters maintain the
separation between the SQL string and the parameters as the statement is parsed in
the RDBMS server.
<?php
$sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?",
"O'Reilly");
echo $sql;
ZEND_DB
Using quoteIdentifier()
As with values, if PHP variables are used to name tables, columns, or other identifiers
in SQL statements, the related strings may need to be quoted. By default, SQL
identifiers have syntax rules like PHP and most other programming languages. For
example, identifiers should not contain spaces, certain punctuation or special
characters, or international characters. Also certain words are reserved for SQL syntax,
and should not be used as identifiers.
However, SQL has a feature called delimited identifiers, which allows broader choices
for the spelling of identifiers. If you enclose a SQL identifier in the proper type of
quotes, you can use identifiers with spellings that would be invalid without the
quotes. Delimited identifiers can contain spaces, punctuation, or international
characters. You can also use SQL reserved words if you enclose them in identifier
delimiters.
The quoteIdentifier() method works like quote(), but applies the identifier
delimiter characters to the string according to the type of Adapter used. For example,
standard SQL uses double-quotes (") for identifier delimiters, and most RDBMS brands
use that symbol. MySQL uses back-quotes (`) by default. The quoteIdentifier()
method also escapes special characters within the string argument. SQL-delimited
identifiers are case-sensitive, unlike unquoted identifiers. Therefore, the use of
delimited identifiers require that the identifier is spelled exactly as it is stored in the
schema, including the case of the letters.
In most cases where SQL is generated within Zend_Db classes, the default is that all
identifiers are delimited automatically; this default can be changed by using
Zend_Db::AUTO_QUOTE_IDENTIFIERS when instantiating the Adapter.
<?php
// we might have a table name that is an SQL reserved word
$tableName = $db->quoteIdentifier("order");
echo $sql
// SELECT * FROM "order"
ZEND_DB
ZEND_DB_STATEMENT
Like the methods fetchAll()and insert(), a statement object can be used to gain
more options for running queries and fetching result sets. Zend_Db_Statement is
based on the PDOStatement object in the PHP Data Objects extension.
Creating a Statement
Typically, a statement object is returned by the query() method of the database Adapter
class. This method is a general way to prepare any SQL statement. The first argument is a
string containing an SQL statement. The optional second argument is an array of values to
bind to parameter placeholders in the SQL string. The statement object corresponds to a SQL
statement that has been prepared and executed once with the bind-values specified. If the
statement was a SELECT query or other type of statement that returns a result set, it is now
ready to fetch results. A statement can be created with its constructor, but this is less typical.
Note: there is no factory method to create this object.
<?php
$stmt = $db->query('SELECT * FROM bugs WHERE reported_by = ? AND
bug_status = ?', array('goofy', 'FIXED'));
Executing a Statement
If a statement is created using its constructor, or if a statement is to be executed multiple
times, then the statement object needs to be executed. Use the execute() method of the
statement object. The single argument is an array of values to bind to parameter placeholders
in the statement.
If positional parameters, or those that are marked with a question mark symbol (?), are used,
pass the bind values in a plain array. If named parameters, or those that are indicated by a
string identifier preceded by a colon character (:), pass the bind values in an associative array.
The keys of this array should match the parameter names. Execution (positional) example:
<?php
$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND
bug_status = ?';
ZEND_DB
Fetching Content
You can call methods on the statement object to retrieve rows from SQL statements
that produce a result set for example, SELECT, SHOW, DESCRIBE, EXPLAIN.
INSERT, UPDATE, and DELETE are examples of statements that do not produce a result
set these SQL statements can be executed using Zend_Db_Statement,but cannot
have results fetched by method calls. Code Example: fetch() in a loop
<?php
$stmt = $db->query('SELECT * FROM bugs');
while ($row = $stmt->fetch()) {
echo $row['bug_description'];
}
ZEND_DB_SELECT
The Zend_Db_Select object represents a SQL SELECT query statement. The class has
methods for adding individual parts to the query. Some parts of the query can be
specified using PHP methods and data structures, and the class will form the correct
SQL syntax. After the query is built, it can be executed as if written as a string.
Important features of this component include:
Object-oriented methods for specifying SQL queries in a piece-by-piece manner
Database-independent abstraction of some parts of the SQL query
Automatic quoting of metadata identifiers in most cases, to support identifiers
containing SQL reserved words and special characters
Quoting identifiers and values, to help reduce risk of SQL injection attacks
<?php
$db = Zend_Db::factory( ...options... );
$select = $db->select();
ZEND_DB
<?php
// Create the Zend_Db_Select object
$select = $db->select();
<?php
$select = $db->select()
->from( ...specify table and columns... )
->where( ...specify search criteria... )
->order( ...specify sorting criteria... );
Add FROM Clause: Specify the table name as a simple string; Zend_Db_Select
applies identifier quotes around the table name so that special
characters can be used.
<?php
// Build this query:
// SELECT *
// FROM "products"
$select = $db->select()
->from( 'products' );
ZEND_DB
Specify Schema: Some RDBMS brands support a schema specifier for a table.
Specify the table name as schemaName.tableName, where
Zend_Db_Select quotes each part individually; alternatively
specify the schema name separately. A schema name
specified in the table name takes precedence over a schema
provided separately in the event that both are presented.
<?php
// Build this query:
// SELECT *
// FROM "myschema"."products"
$select = $db->select()
->from( 'myschema.products' );
// or
$select = $db->select()
->from('products', '*', 'myschema');
Add Column: The columns to be selected from a table can be specified in the
second argument of from(). The default is the wildcard *,
meaning all columns.
<?php
// Build this query:
// SELECT p."product_id", p."product_name"
// FROM "products" AS p
$select = $db->select()
->from(array('p' => 'products'),
array('product_id', 'product_name'));
ZEND_DB
Add Table: Many useful queries involve using a JOIN to combine rows
from multiple tables; tables can also be added to a
Zend_Db_Select query using the join() method.
Using this method is similar to the from() method except a
condition can also be specified in most cases.
The second argument to join() is a string that is the join
condition, an expression that declares the criteria by
which rows in one table match rows in the the other table.
<?php
// Build this query:
// SELECT p."product_id", p."product_name", l.*
// FROM "products" AS p JOIN "line_items" AS l
// ON p.product_id = l.product_id
$select = $db->select()
->from(array('p' => 'products'),
array('product_id', 'product_name'))
->join(array('l' => 'line_items'),
'p.product_id = l.product_id');
Add WHERE clause: The where() method can specify criteria for restricting rows
of the result set. The first argument of this method is a SQL
expression, which is used in a SQL WHERE clause in the query.
<?php
// Build this query:
// SELECT product_id, product_name, price
// FROM "products"
// WHERE price > 100.00
$select = $db->select()
->from(
'products',
array('product_id', 'product_name', 'price'))
->where('price > 100.00');
ZEND_DB
<?php
// Build this query:
// SELECT p."product_id", COUNT(*) AS line_items_per_product
// FROM "products" AS p JOIN "line_items" AS l
// ON p.product_id = l.product_id
// GROUP BY p.product_id
// ORDER BY "line_items_per_product" DESC, "product_id"
$select = $db->select()
->from(array('p' => 'products'),
array('product_id'))
->join(array('l' => 'line_items'),
'p.product_id = l.product_id',
array('line_items_per_product' => 'COUNT(*)'))
->group('p.product_id')
->order(array('line_items_per_product DESC', 'product_id'));
<?php
// Build this query:
// SELECT p."product_id", p."product_name"
// FROM "products" AS p
// LIMIT 10, 20
$select = $db->select()
->from(array('p' => 'products'), array('product_id',
'product_name'))
->limit(10, 20);
ZEND_DB
ZEND_DB_TABLE
The Zend_Db_Table class is an object-oriented interface to database tables. It provides
methods for many common operations on tables. The base class is extensible, allowing the
addition of custom logic. The Zend_Db_Table solution is an implementation of the Table
Data Gateway pattern and includes a class that implements the Row Data Gateway pattern.
<?php
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
}
<?php
class Bugs extends Zend_Db_Table_Abstract
{
//table name matches class name, by default
}
ZEND_DB
<?php
class Bugs extends Zend_Db_Table_Abstract
{
protected function _setupTableName()
{
$this->_name = 'bugs';
parent::_setupTableName();
}
}
_setupDatabaseAdapter()
checks that an adapter has been provided; gets a default adapter from the
registry if needed. By overriding this method, you can set a database adapter
from some other source.
_setupTableName()
defaults the table name to the name of the class. By overriding this method,
you can set the table name before this default behavior runs.
_setupMetadata()
sets the schema if the table name contains the pattern "schema.table"; calls
describeTable() to get metadata information; defaults $_cols array to the
columns reported by describeTable(). Override this method to specify the
columns.
_setupPrimaryKey()
defaults the primary key columns to those reported by describeTable();
checks that the primary key columns are included in the $_cols array.
Override this method to specify the primary key columns.
Zend_Log
Zend_Debug
You should be able to explain when and how you would use Zend_Log, including the
creation and destruction of Log objects.
You should understand how backends, filters, and formatters work within the Framework.
In addition, you should understand the difference between using Zend_Log and
Zend_Debug, and when it is appropriate to use each.
ZEND_LOG
The Zend_Log component supports multiple log backends, formatting messages sent to the
log, and filtering messages from being logged. These functions are divided into the following
objects:
Create a Log
To create a log, instantiate a Writer (using Zend_Log_Writer_Stream) and then pass it on
to a Log instance. More Writers can be added with addWriter(); one is required. Ex:
<?php
$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('php://output');
Logging Messages
Call the log() method of a Log instance and pass it the message with a corresponding
priority; the first parameter is a string message; the second, an integer priority. Ex:
<?php
$logger->log('Informational message', Zend_Log::INFO);
ZEND_LOG
Destroy a Log
Set the variable containing it to null to destroy it; this will automatically call the
shutdown() instance method of each attached Writer before the Log object is destroyed:
<?php
$logger = null;
Priorities Built-In
Priorities Custom
User-defined priorities can be added at runtime using the Log's addPriority() method.
Example: Create Priority called FOO and log the priority
<?php
$logger->addPriority('FOO', 8);
<?php
$logger->log('Foo message', 8);
ZEND_LOG
Writers
A Writer is an object that inherits from Zend_Log_Writer_Abstract, and is responsible
for recording log data to a storage backend.
Writing to Streams
Zend_Log_Writer_Stream sends log data to a PHP stream. To write log data to the PHP
output buffer, use the URL php://output. To write to file, use a Filesystem URL. By default,
the stream opens in the append mode for another mode, provide an optional second
parameter to the constructor.
Alternatively, you can send log data directly to a stream like STDERR (php://stderr). Ex:
<?php
$writer = new Zend_Log_Writer_Stream('php://output');
$logger = new Zend_Log($writer);
Writing to Databases:
Zend_Log_Writer_Db writes log information to a database table using Zend_Db. The
constructor of Zend_Log_Writer_Db receives a Zend_Db_Adapter instance, a table name,
and a mapping of database columns to event data items. Ex:
<?php
$params = array ('host' => '127.0.0.1',
'username' => 'malory',
'password' => '******',
'dbname' => 'camelot');
$db = Zend_Db::factory('PDO_MYSQL', $params);
$logger->info('Informational message');
ZEND_LOG
Writers (CONTINUED)
<?php
$mock = new Zend_Log_Writer_Mock;
$logger = new Zend_Log($mock);
$logger->info('Informational message');
var_dump($mock->events[0]);
// Array
// (
// [timestamp] => 2007-04-06T07:16:37-07:00
// [message] => Informational message
// [priority] => 6
// [priorityName] => INFO
// )
ZEND_LOG
FORMATTERS
AFormatterisanobjectthatisresponsiblefortakinganeventarraydescribingalogeventand
outputtingastringwithaformattedlogline.
SomeWritersarenotlineorientedandcannotuseaFormatter(Ex:theDatabaseWriter,which
insertstheeventitemsdirectlyintodatabasecolumns).ForWritersthatcannotsupporta
Formatter,anexceptionisthrownifyouattempttosetaFormatter.
SimpleFormatting
Zend_Log_Formatter_Simpleisthedefaultformatter.Itisconfiguredautomaticallywhen
youspecifynoformatter.Thedefaultconfigurationisequivalenttothefollowing:
<?php
$format = '%timestamp% %priorityName% (%priority%):
%message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);
AformatterissetonanindividualWriterobjectusingtheWriter'ssetFormatter()method:
FormattingtoXML
Zend_Log_Formatter_XmlformatslogdataintoXMLstrings.Bydefault,itautomatically
logsallitemsintheeventdataarray.
$writer = new Zend_Log_Writer_Stream('php://output');
$formatter = new Zend_Log_Formatter_Xml();
$writer->setFormatter($formatter);
$logger = new Zend_Log();
$logger->addWriter($writer);
$logger->info('informational message');
ItispossibletocustomizetherootelementaswellasspecifyamappingofXMLelementstothe
itemsintheeventdataarray.TheconstructorofZend_Log_Formatter_Xmlacceptsastring
withthenameoftherootelementasthefirstparameter,andanassociativearraywiththe
elementmappingasthesecondparameter:
ZEND_LOG
Filters
A filter object blocks a message from being written to the log.
<?php
$logger = new Zend_Log();
// blocked
$logger->info('Informational message');
// logged
$logger->emerg('Emergency message');
When you add one or more Filters to the Log object, the message must pass through all of the
Filters before any Writers receives it.
<?php
$logger = new Zend_Log();
ZEND_DEBUG
Dumping Variables
The $var argument specifies the expression or variable about which the
Zend_Debug::dump() method outputs information.
<?php
Zend_Debug::dump($var, $label=null, $echo=true);
Also consider the Zend_Log component when writing more permanent debugging code. Ex:
use the DEBUG log level and the Stream log writer, to output the string returned by
Zend_Debug::dump().
b. ob_start();
Zend_debug::dump($var, 'var', false);
ob_end_flush();
d. Zend_Debug::dump($var, 'var');
a. Zend_Log_Formatter_Db
b. Zend_Log_Formatter_Simple
c. Zend_Log_Formatter_Text
d. Zend_Log_Formatter_Xml
b. ob_start();
Zend_debug::dump($var, 'var', false);
ob_end_flush();
d. Zend_Debug::dump($var, 'var');
a. Zend_Log_Formatter_Db
b. Zend_Log_Formatter_Simple
c. Zend_Log_Formatter_Text
d. Zend_Log_Formatter_Xml
Zend_Filter
Filter Chains
Zend_Validate
Validator Chains
You should be able to create and work with Filters, while understanding their role within an
application.
ZEND_FILTER
Filters, in the general sense, function to produce some subset of the original input, based on
some criteria or transformation. Within web applications, filters are used to remove illegal
input, trim unnecessary white space, and perform other functions.
A common transformation applied within web application is to escape HTML entities (see
Security section for more information on this sub-topic).
Zend_Filter provides a set of commonly needed data filters for web applications. It also
provides a simple filter chaining mechanism by which multiple filters can be applied to a
single datum in a user-defined order.
Zend_Filter_Interface provides the basic functionality for the component, and requires
a single method filter(), to be implemented by a filter class. You can also use the static
method Zend_Filter::get() as an alternative.
<?php
require_once 'Zend/Filter/HtmlEntities.php';
Standard Filters
ZF offers a set of standard filter classes with the framework the list is provided below.
Information on each option can be found in the Programmers Guide you should know how
to utilize each.
Alnum Alpha
BaseName Digits
Dir HtmlEntities
Int RealPath
StringToLower StringToUpper
StringTrim StripTags
ZEND_FILTER
Filter Chains
When using multiple filters, it will often be necessary to impose them in a specific order,
known as chaining. Zend_Filter provides a simple way to chain filters together.
Filters are run in the order in which they were added to the component.
<?php
// Provides filter chaining capability
require_once 'Zend/Filter.php';
<?php
require_once 'Zend/Filter/Interface.php';
return $valueFiltered;
}
}
ZEND_FILTER
Zend_Filter_Input
Zend_Filter_Input provides a declarative interface to associate multiple filters and
validators, apply them to collections of data, and retrieve input values after they have been
processed by the filters and validators. Values are returned in escaped format by default for
safe HTML output.
Filters transform input values, by removing or changing characters within the value.
The goal is to "normalize" input values until they match an expected format
Validators check input values against criteria and report whether they passed the test
or not. The value is not changed, but the check may fail
For further information about these steps, see the online Reference Guide
ZEND_VALIDATE
Validators examine input against some set of requirements and produces a boolean result
(True or False) as to whether it passed. It can also provide further information about which
requirement(s) the input did not meet in the event of validation failure.
Zend_Validate provides a set of commonly needed validators for web applications. It also
provides a simple validator chaining mechanism by which multiple validators can be applied
to a single datum in a user-defined order.
isValid()performs validation upon the input value, returning TRUE for success in
meeting the criteria, FALSE for failure. In the latter case, the next method is used.
getMessages()returns an array of messages explaining the reason(s) for validation
failure. The array keys identify the reasons with string codes, and the array values
provide readable string messages. These key-value pairs are class-dependent, and
each class also has a const definition that matches each identifier for a validation
failure cause.
Note that each call to isValid() overwrites the previous call. Therefore, each
getMessages() output will apply to only the most recent validation.
<?php
require_once 'Zend/Validate/EmailAddress.php';
if ($validator->isValid($email)) {
// email appears to be valid
} else {
// email is invalid; print the reasons
foreach($validator->getMessages()as $messageId => $message) {
echo "Validation failure '$messageId': $message\n";
}
}
ZEND_VALIDATE
You can also use the static method Zend_Validate::is() as an alternative. The first
argument would be the data input value, passed to the isValid() method, and the second
argument would be the string that corresponds to the basename of the validation class,
relative to the Zend_Validate namespace. The is() method automatically loads the class,
creates an instance, and applies the isValid() method to the data input.
<?php
require_once 'Zend/Validate.php';
if (Zend_Validate::is($email, 'EmailAddress')) {
// Yes, email appears to be valid
}
Customizing Messages
Validate classes provide a setMessage() method with which you can specify the format of
the message returned by getMessages() upon validation failure.
The first argument contains a string with the error message itself. Tokens can be incorporated
within the string to customize the message with relevant data. The token %value% is
supported by all validators, while other tokens are supported on a case-by-case basis,
according to the validation class.
The second argument contains a string with the validation failure template to be set, used
when a validation class defines more than one cause for failure.
If the second argument is missing, setMessage() assumes the message specified should be
used for the first message template declared in the validation class. As many validation classes
have only one error message template defined, there is no need to specify which template to
change. Sample Code provided below:
<?php
require_once 'Zend/Validate/StringLength.php';
$validator->setMessage(
'The string \'%value%\' is too short;
it must be at least %min% characters',
Zend_Validate_StringLength::TOO_SHORT);
if (!$validator->isValid('word')) {
$messages = $validator->getMessages();
echo current($messages);
ZEND_VALIDATE
Validation Chains
When using multiple validations, it will often be necessary to impose them in a specific order,
known as chaining. Zend_Validate provides a simple way to chain them together.
Validators are run in the order in which they were added to Zend_Validate .
Ex: validating whether a username is between 6 and 12 alphanumeric characters.
<?php
// Provides validator chaining capability
require_once 'Zend/Validate.php';
ZEND_VALIDATE
As mentioned earlier, validation results are returned as Boolean values, possibly along with
information as to why the validation failed (useful for usability analysis).
Zend_Validate_Abstract is used to implement the basic validation failure message
functionality, which can be extended. The extending class would utilize the isValid()
method logic and define message variables and message templates that correspond to the
types of validation failures that can occur.
Generally, the isValid() method will not throw any exceptions unless it is impossible to
determine whether or not the input value is valid (Ex: an LDAP server cannot be contacted, a
file cannot be opened, a database unavailable, etc.)
a. Zend_Validate::is($email, 'EmailAddress');
b. Zend_Validate::isValid($email, 'EmailAddress');
d. $validator = new
Zend_Validate_EmailAddress($email);
if ($validator->isValid()) {
// email appears to be valid
}
<a href="http://example.com">Click</a>
a. Zend_Filter_StripTags
b. Zend_Text
c. Zend_Uri
d. Zend_View
b. Zend_Validate::isValid($email, 'EmailAddress');
<a href="http://example.com">Click</a>
a. Zend_Filter_StripTags
b. Zend_Text
c. Zend_Uri
d. Zend_View
Forms - Validation
Forms - Filtering
Filtering
Forms - Decorators
Forms - Elements
Elements Options
Array Notation
Forms Configuration
Forms Internationalization
You should know the basics of a form what problems does it solve, what plugins does it use,
what role does metadata play with forms, what methods are available and what do they
control?
You should be able to explain the purpose of validators, and know how to utilize them (create,
add and retrieve from elements, ).
You should be able to explain the role of filters, and know how to utilize them (create, chain,
add and retrieve from elements, ).
You should know the purpose of decorators and how to manipulate them.
You should understand the relationship between a form and its elements.
You should know what a display group is, as well as a sub-form, and understand the difference
between the two. You should know how they interact with decorators, and various use cases
for each.
You should understand how to create a config object with form or element options, how to
pass options, and how to pass a config object to a form or element.
Finally, you should know how to internationalize a form what elements can be altered, how
to connect a translate object to a form or element, and how to translate form error messages.
ZEND_FORM
Zend_Form simplifies form creation and handling in your web application. It accomplishes
the following goals:
Element input filtering and validation
Element ordering
Element and Form rendering, including escaping
Element and form grouping
Element and form-level configuration
It heavily leverages other Zend Framework components to accomplish its goals, including
Zend_Config, _Validate, _Filter, _Loader_PluginLoader, and optionally
_View
<?php
$form = new Zend_Form;
It is a best practice to specify the form action and method; you can do this with the
setAction() and setMethod() accessors.
<?php
$form->setAction('/resource/process')
->setMethod('post');
ZEND_FORM
There are several options for adding elements: (1) instantiate concrete elements, pass in these
objects; (2) pass in the element type, have Zend_Form instantiate an object of the correct
type; (3) use createElement() and then attach the element to the form using
addElement(); (4) use configuration to specify elements for Zend_Form to create.
By default, these do not have any validators or filters. Therefore, you will need to configure
your elements with validators, and potentially filters
(b) via configuration options passed in when creating an element via Zend_Form, or
(c) by pulling the element from the form object and configuring it after the fact.
In this example, you can either pass in Zend_Validate_* objects, or the name of a validator
to use in the latter case, the validator can accept constructor arguments, which can be
passed in an array as the third parameter:
$username->addValidator('regex', false, array('/^[a-z]/i'));
ZEND_FORM
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]/'))
->setRequired(true)
->addFilter('StringToLower');
// or, more compactly:
$username->addValidators(
array('alnum',
array('regex', false, '/^[a-z]/i')
))
->setRequired(true)
->addFilters(array('StringToLower'));
Render a Form
Most elements use a Zend_View helper to render themselves, thereby requiring a view
object. Alternatively, you can either use the form's render() method, or simply echo it.
By default, Zend_Form and Zend_Form_Element will attempt to use the view object
initialized in the ViewRenderer, negating the need to set the view manually when using the
Zend Framework MVC. However, if you are not using the MVC view renderer you will need to
provide a Zend_View object to render the form elements. This is because
Zend_Form_Element objects use the View helpers for rendering. Printing the form in a view
script is then simple: <?= $this->form ?>
ZEND_FORM
When a form is assessed for validity, each element is checked against the data provided. If a
key matching the element name is not present, and the item is marked as required, validations
are run with a null value. The data sources are standard ($_GET, $_POST, Web Services, etc.).
if ($form->isValid($_POST)) {
// success!
} else {
// failure!
}
Partial Forms: Ajax requests may allow for checking on a single element or groups.
isValidPartial() will validate a partial form but, in contrast to isValid(), if a particular
key is not present, it will not run validations for that element.
$values = $form->getValues();
$unfiltered = $form->getUnfilteredValues();
Generally, when a form fails validation, it can simply be rendered again, and the errors will be
displayed using the default decorators. To inspect the errors, either use the getErrors()
method, which returns an associative array of element names/codes (= an array of error
codes), or getMessages(), which returns an associative array of element names/messages
(= an associative array of error code/error message pairs). If a given element does not have any
errors, it will not be included in the array. Zend_Form::getMessages() returns an
associative array of associative arrays; keys (element names) point to an associative array of
code/message pairs.
FORMS FILTERS (also see the Filtering and Validation section of this guide)
It is often useful and/or necessary to perform some kind of normalization on input prior to
validation for instance, to strip out all the HTML for security, but then run your validations on
what remains to ensure the submission is valid; or, to trim empty space surrounding input so
that a StringLength validator will not return a false positive.
<? php
$filtered = $element->getValue();
<?php
// Concrete filter instance:
$element->addFilter(new Zend_Filter_Alnum());
// Fully qualified class name:
$element->addFilter('Zend_Filter_Alnum');
// Short filter name:
$element->addFilter('Alnum');
$element->addFilter('alnum');
Short names are typically the filter name minus the prefix. In the default case, this will mean
minus the 'Zend_Filter_' prefix. Additionally, the first letter need not be in upper-case.
<?php
$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter');
FORMS VALIDATORS (also see the Filtering and Validation section of this guide)
Validators examine input against a set of requirements and produce a boolean result (True or
False) as to whether the input passed. The process can also provide further information about
which requirement(s) the input either met or failed. This is especially important in a security
context (filter input, escape output).
Short names are typically the validator name minus the prefix. In the default case, this will
mean minus the 'Zend_Validate_' prefix. The first letter need not be in upper-case.
$element->addPrefixPath('My_Validator, 'My/Validator/',
'Validator');
Recall that the third argument indicates the plugin loader on which to perform the action. If a
particular validation failure should prevent later validators from firing, then pass the boolean
TRUE as the second parameter: $element->addValidator('alnum', true);
FORMS - VALIDATION
A better option is to use a Zend_Translate_Adapter with your form. Error codes are
automatically passed to the adapter by the default errors decorator - you can then specify
your own error message strings by setting up translations for the various error codes of your
validators.
You can also set multiple validators at once, using addValidators(). The basic way to
utilize this method is to pass an array of arrays, with each array containing 1 to 3 values, that
matches the addValidator()constructor.
$element->addValidators(array(
array('NotEmpty', true),
array('alnum'),
array('stringLength', false, array(6, 20)),
));
Alternatively, you can use the array keys 'validator', 'breakChainOnFailure', and
'options':
$element->addValidators(array(
array(
'validator' => 'NotEmpty',
'breakChainOnFailure' => true),
array('validator' => 'alnum'),
array(
'validator' => 'stringLength',
'options' => array(6, 20)),
));
Note the use of 'breakChainOnFailure' in the second argument. When set to 'TRUE', any
later validations in the chain are skipped.
FORMS - VALIDATION
Configure Validators
The previous example provided in the Custom Validator Error Messages section provides the
scenario for showing how to configure validators in a config file:
element.validators.notempty.validator = "NotEmpty"
element.validators.notempty.breakChainOnFailure = true
element.validators.alnum.validator = "Alnum"
element.validators.strlen.validator = "StringLength"
element.validators.strlen.options.min = 6
element.validators.strlen.options.max = 20
Note that every item has a key, whether or not it needs one. This is a limitation of using
configuration files, but it helps to clarify the purpose of each argument. Remember that any
validator options must be specified in the correct order.
if ($element->isValid($value)) {
// valid
} else {
// invalid
}
FORMS - VALIDATION
setAutoInsertNotEmptyValidator($flag)
allows you to specify whether or not a 'NotEmpty' validator will be prepended to
the validator chain when the element is required. By default, this flag is true.
addValidator($nameOrValidator, $breakChainOnFailure = false,
array $options = null)
addValidators(array $validators)
setValidators(array $validators)
overwrites all validators
getValidator($name)
retrieves a validator object by name
getValidators()
retrieves all validators
removeValidator($name)
removes validator by name
clearValidators()
removes all validators
ZEND_FORM
Plugin Loaders
Zend_Form_Element makes use of Zend_Loader_PluginLoader to specify the locations
of alternate validators, filters, and decorators. Each has its own plugin loader associated with
it, and general accessors are used to retrieve and modify each. The following loader types are
used with the various plugin loader methods (the type names are case insensitive):
validate filter decorator
getPluginLoader($type):
retrieves the plugin loader associated with $type.
addPrefixPaths(array $spec):
allows the addition of many paths at once to one or more plugin loaders. It expects
each array item to be an array with the keys 'path', 'prefix', and 'type'.
Custom validators, filters, and decorators are an easy way to share functionality among forms
and encapsulate custom functionality. The online Reference Guide provides an extensive
example for creating a custom decorator.
ZEND_FORM
Decorators
Zend_Form_Element uses "decorators", which are simply classes that have access to both
the element and a method for rendering content. These decorators can replace content,
append content, or prepend content, and have full introspection to the element passed to
them. As a result, multiple decorators can be combined to achieve custom effects. By default,
Zend_Form_Element actually combines four decorators to achieve its output. Example:
ViewHelper: specifies a view helper to use for rendering the element. The 'helper'
element attribute can be used to specify which view helper to use. By default,
Zend_Form_Element specifies the 'formText' view helper, but individual
subclasses specify different helpers.
By default, the default decorators are loaded during object initialization. You can disable this
by passing the 'disableLoadDefaultDecorators' option to the constructor:
<?php
$element = new Zend_Form_Element(
'foo',
array('disableLoadDefaultDecorators' => true)
);
This option may be mixed with any other options you pass, both as array options or in a
Zend_Config object. The initial content is created by the 'ViewHelper' decorator, which
creates the form element itself. Next, the 'Errors' decorator fetches error messages from
the element, and, if any are present, passes them to the 'FormErrors' view helper to
render. The next decorator, 'HtmlTag', wraps the element and errors in an HTML <dd> tag.
Finally, the last decorator, 'label', retrieves the element's label and passes it to the
'FormLabel' view helper, wrapping it in an HTML <dt> tag; the value is prepended to the
content by default.
ZEND_FORM
Multiple Decorators
Zend_Form_Element uses a decorator's class as the lookup mechanism when retrieving
decorators. As a result, you cannot register multiple decorators of the same type; subsequent
decorators will simply overwrite those that existed before. To get around this, you can use
aliases. Instead of passing a decorator or decorator name as the first argument to
addDecorator(), pass an array with a single element, with the alias pointing to the
decorator object or name:
<?php
// Alias to 'FooBar':
$element->
addDecorator(
array('FooBar' => 'HtmlTag'),
array('tag' => 'div')
);
In the addDecorators() and setDecorators() methods, you can either pass the
'decorator' option in the array representing the decorator, or pass it as the first element in the
decorator portion of the array:
<?php
// Add two 'HtmlTag' decorators, aliasing one to 'FooBar':
$element->addDecorators(
array(
array('HtmlTag', array('tag' => 'div')),
array(
'decorator' => array('FooBar' => 'HtmlTag'),
'options' => array('tag' => 'dd')
)
)
);
ZEND_FORM
Configuration
The Zend_Form_Element constructor accepts either an array of options or a
Zend_Config object containing options, and it can also be configured using either
setOptions() or setConfig(). Generally speaking, keys are named as follows:
If the 'set' + key refers to a Zend_Form_Element method, then the value provided will
be passed to that method.
The first letter of a config key can be either lower or upper case, but the remainder of
the key should follow the same case as the accessor method
Display Groups
Display groups are a way to create virtual groupings of elements for display purposes. All
elements remain accessible by name in the form, but when iterating over the form or
rendering, any elements in a display group are rendered together. The most common use case
for this is for grouping elements in fieldsets.
The base class for display groups is Zend_Form_DisplayGroup. While it can be instantiated
directly, it is typically best to use the Zend_Form addDisplayGroup() method to do so. This
method takes an array of elements as its first argument, and a name for the display group as
its second argument. You may optionally pass in an array of options or a Zend_Config
object as the third argument. Assuming that the elements 'username' and 'password' are
already set in the form, this code would group these elements in a 'login' display group:
ZEND_FORM
Sub Forms
Sub forms serve several purposes:
Creating logical element groups. Since sub forms are simply forms, you can validate
subforms as individual entities.
Creating multi-page forms. Since sub forms are simply forms, you can display a
separate sub form per page, building up multi-page forms where each form has its
own validation logic. Only once all sub forms validate would the form be considered
complete.
Display groupings. Like display groups, sub forms, when rendered as part of a larger
form, can be used to group elements. Be aware, however, that the master form object
will have no awareness of the elements in sub forms.
<?php
$form->addSubForm($subForm, 'subform');
You can retrieve a sub form using either getSubForm($name) or overloading using the sub
form name.
<?php
// Using getSubForm():
$subForm = $form->getSubForm('subform');
// Using overloading:
$subForm = $form->subform;
ZEND_FORM
Internationalization of Forms
By default, no internationalization (I18n) is performed. To turn on I18n features in
Zend_Form, you will need to instantiate a Zend_Translate object with an appropriate
adapter, and attach it to Zend_Form and/or Zend_Validate.
Add to the Registry - this will be picked up by Zend_Form, Zend_Validate, and
Zend_View_Helper_Translate.
<?php
// use the 'Zend_Translate' key; $translate is a
// Zend_Translate object:
Zend_Registry::set('Zend_Translate', $translate);
<?php
//Tell all validation classes to use a specific translate adapter
Zend_Validate_Abstract::setDefaultTranslator($translate);
or attach to the Zend_Form object as a global translator. This has the side effect of also
translating validation error messages.
<?php
//Tell all form classes to use a specific translate adapter, as
//well as use this adapter to translate validation error messages
Zend_Form::setDefaultTranslator($translate);
b. Zend_Validate_Abstract
c. Zend_Validate_Interface
d. Zend_Form_Validate_Interface
b. <code>
$element->attachDecorator('ViewHelper');
</code>
c. <code>
$element->addDecorator('ViewHelper');
</code>
d. <code>
$element->addDecorator('ViewHelper',
array('helper' => 'foo'));
</code>
b. Zend_Validate_Abstract
c. Zend_Validate_Interface
d. Zend_Form_Validate_Interface
b. <code>
$element->attachDecorator('ViewHelper');
</code>
c. <code>
$element->addDecorator('ViewHelper');
</code>
d. <code>
$element->addDecorator('ViewHelper',
array('helper' => 'foo'));
</code>
Zend_Config
Zend_Exception
Zend_Registry
Zend_Version
Detection
Zend_Loader
Plugins
Zend_Session
CONFIGURATION
You should be able to explain the purpose of configuration for single and multiple
environments within an MVC-based application.
You should be able to define a configuration object using an ini file, and then interact with
and utilize that configuration object; you should know how to set up an application bootstrap
file to utilize a configuration file.
EXCEPTIONS
You should know the purpose of framework-specific exceptions and what they represent; you
should also be able to create code that catches exceptions thrown by any ZF component.
REGISTRY
You should know the purpose of having a registry within an object-oriented based
application.
You should be able to assign application-wide objects to the global registry, as well as know
when and how to create an alternative to the global registry.
LOADER
You should know when to use, and when not to use, Zend_Loader within an application
and libraries, know how to utilize the autoload feature, know how Zend_Loader maps class
names to files.
SESSION
You should understand the features and benefits that Zend_Session provides, how to set
an application bootstrap file to use Zend_Session, and how to persist data between
requests.
ZEND_CONFIG
Zend_Config is designed to simplify access to, and use of, configuration data within
applications. It provides a nested object property-based user interface for accessing
configuration data within application code.
The configuration data may come from a variety of media-supporting hierarchical data
storage. Currently Zend_Config provides adapters for configuration data that are stored in
text files with Zend_Config_Ini and Zend_Config_Xml (two most commonly used).
<?php
// Given an array of configuration data
$configArray = array(
'webhost' => 'www.example.com',
'database' => array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
)
);
ZEND_CONFIG
<?php
// config.php
return array(
'webhost' => 'www.example.com',
'database' => array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
<?php
// Configuration consumption
require_once 'Zend/Config.php';
$config = new Zend_Config(require 'config.php');
ZEND_CONFIG
Zend_Config implements the Countable and Iterator interfaces in order to facilitate simple
access to configuration data, allowing the use of the count() function and PHP constructs
such as foreach upon Zend_Config objects.
Adapter classes inherit from the Zend_Config class since they utilize its functionality.
The Zend_Config family of classes enables configuration data to be organized into sections.
Zend_Config adapter objects may be loaded with a single specified section, multiple
specified sections, or all sections (if none are specified).
Zend_Config adapter classes support a single inheritance model that enables configuration
data to be inherited from one section of configuration data into another, reducing or
eliminating the need for duplicating configuration data for different purposes. An inheriting
section can also override the values that it inherits through its parent section.
Two Zend_Config objects can be merged into a single object using the merge() function.
ZEND_CONFIG
Zend_Config_Ini
Zend_Config_Ini enables developers to store configuration data in a familiar INI format
and read them in the application using nested object property syntax. The INI format is
specialized to provide both the ability to have a hierarchy of configuration data keys and
inheritance between configuration data sections.
Configuration data hierarchies are supported by separating the keys with a period character (.)
A section may extend or inherit from another section by following the section name with a
colon character (:) and the name of the section from which to inherit the data.
The configuration data may represent multiple environments (Ex: production and staging).
The developer would simply specify which environment to engage by specifying the INI file
and the specified environments section (path). In this example, the configuration data for the
staging environment is being used. Given that the configuration data is contained in
/path/to/config.ini :
<?php
$config = new Zend_Config_Ini('/path/to/config.ini', 'staging');
ZEND_CONFIG
Zend_Config_Xml
Zend_Config_Xml enables developers to store configuration data in a simple XML format
and read them via nested object property syntax. Configuration data read into
Zend_Config_Xml are always returned as strings.
The root element of the XML file is irrelevant and the first level corresponds with configuration
data sections. The XML format supports hierarchical organization through nesting of XML
elements below the section-level elements. The content of a leaf-level XML element
corresponds to the value of a configuration datum. Section inheritance is supported by a
special XML attribute named extends, and the value of this attribute corresponds with the
section from which data are to be inherited by the extending section.
Example: using Zend_Config_Xml for loading configuration data from an XML file
with multiple environments (staging and production). Given that the configuration
data is contained in /path/to/config.xml, and the application needs the staging
configuration data:
<?xml version="1.0"?>
<configdata>
<production>
<webhost>www.example.com</webhost>
<database>
<adapter>pdo_mysql</adapter>
<params>
<host>db.example.com</host>
<username>dbuser</username>
<password>secret</password>
<dbname>dbname</dbname>
</params>
</database>
</production>
<staging extends="production">
<database>
<params>
<host>dev.example.com</host>
<username>devuser</username>
<password>devsecret</password>
</params>
</database>
</staging>
</configdata>
ZEND_EXCEPTION
All exceptions thrown by Zend Framework classes should derive from the base class
Zend_Exception.
Catching Exceptions
The following example illustrates code for catching exceptions within a ZF application:
<?php
try {
Zend_Loader::loadClass('nonexistantclass');
} catch (Zend_Exception $e) {
echo "Caught exception: " . get_class($e) . "\n";
echo "Message: " . $e->getMessage() . "\n";
// other code to recover from the failure.
}
ZEND_VERSION
The class constant Zend_Version::VERSION contains a string that identifies the current
version number of Zend Framework.
<?php
// returns -1, 0 or 1
$cmp = Zend_Version::compareVersion('1.0.0');
ZEND_REGISTRY
The registry is a container for storing objects and values in the application space. By
storing the value in the registry, the same object is always available throughout your
application. This mechanism is an alternative to using global storage.
The typical usage of the registry is through static methods in the Zend_Registry
class. Alternatively, the class is an array object, so you can access elements stored
within it with a convenient array-like interface
In addition to accessing the static registry through static methods, you can create an
instance directly and use it as an object. The registry instance you access through the
static methods is simply one such instance, and it is for convenience that it is stored
statically, so you can access it from anywhere in your application.
Use a traditional new constructor to create an instance of the registry. This gives you
the opportunity to initialize the entries in the registry as an associative array.
<?php
$registry = new Zend_Registry(array('index' => $value));
After constructing this instance, you can use it using array-object methods, or you can
set this instance to become the static instance using setInstance().
<?php
$registry = new Zend_Registry(array('index' => $value));
Zend_Registry::setInstance($registry);
<?php
try {
Zend_Loader::loadClass('nonexistantclass');
} catch (Zend_Exception $e) {
echo "Caught exception: " . get_class($e) . "\n";
echo "Message: " . $e->getMessage() . "\n";
// other code to recover from the failure.
}
ZEND_LOADER
The Zend_Loader class includes methods to help you load files dynamically.
Loading Files
The static method Zend_Loader::loadFile() loads a PHP file, which may contain any
PHP code. The method is a wrapper for the PHP function include()and throws
Zend_Exception on failure.
The $filename argument specifies the filename to load it can only contain alphanumeric
characters, hyphens ("-"), underscores ("_"), or periods ("."), and must not contain any path
information. A security check is run on this.
No similar restrictions are placed on the $dirs argument, which specifies the directories to
search for the file. If it returns NULL, only the include_path is searched. If it returns a string
or array, the directory or directories specified will be searched, and then the include_path.
Loading Classes
The static method Zend_Loader::loadClass($class, $dirs) loads a PHP file and
then checks for the existence of the class. The string specifying the class is converted to a
relative path by substituting directory separates for underscores, and appending '.php'. Ex:
'Container_Tree' would become 'Container/Tree.php'.
<?php
Zend_Loader::loadClass('Container_Tree',
array(
'/home/production/mylib',
'/home/production/myapp'
)
);
ZEND_LOADER
Plugin Loader
A number of Zend Framework components are pluggable, and allow loading of dynamic
functionality by specifying a class prefix and path to class files that are not necessarily on the
include_path, or do not necessarily follow traditional naming conventions.
Zend_Loader_PluginLoader provides common functionality for this.
The basic usage of the PluginLoader follows Zend Framework naming conventions - one
class per file, using the underscore as a directory separator when resolving paths. It allows
passing an optional class prefix to prepend when determining if a particular plugin class is
loaded, and paths are searched in LIFO order (Last In, First Out). This allows for namespacing
plugins, and thus overriding plugins from paths registered earlier.
application/
modules/
foo/
views/
helpers/
FormLabel.php
FormSubmit.php
bar/
views/
helpers/
FormSubmit.php
library/
Zend/
View/
Helper/
FormLabel.php
FormSubmit.php
FormText.php
<?php
$loader = new Zend_Loader_PluginLoader();
$loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/')
->addPrefixPath('Foo_View_Helper',
'application/modules/foo/views/helpers')
->addPrefixPath('Bar_View_Helper',
'application/modules/bar/views/helpers');
ZEND_SESSION
For PHP applications, a session represents a logical, one-to-one connection between server-
side, persistent state data and a particular user agent client (e.g., a web browser).
Zend_Session helps manage and preserve session data, a logical complement of cookie
data, across multiple page requests by the same client.
Session Data
Unlike cookie data, session data are not stored on the client side and are only shared with the
client when server-side source code voluntarily makes the data available in response to a
client request. (Here, the term "session data" refers to the server-side data stored in
$_SESSION, managed by Zend_Session, and individually manipulated by
Zend_Session_Namespace accessor objects.)
Zend_Session_Namespace
Session namespaces provide access to session data using classic namespaces implemented
logically as named groups of associative arrays, keyed by strings (similar to normal PHP arrays).
Zend_Session_Namespace instances are accessor objects for namespaced slices of
$_SESSION. The Zend_Session component wraps the existing PHP ext/session with an
administration and management interface, as well as providing an API for
Zend_Session_Namespace to persist session namespaces. Zend_Session_Namespace
provides a standardized, object-oriented interface for working with namespaces persisted
inside PHP's standard session mechanism.
Support exists for both anonymous and authenticated (e.g., "login") session namespaces.
Zend_Auth, the authentication component of ZF, uses Zend_Session_Namespace to store
some information associated with authenticated users.
Since Zend_Session uses the normal PHP extension/session functions internally, all the
familiar configuration options and settings apply, with the convenience of an object-oriented
interface and default behavior that provides both best practices and smooth integration with
the Zend Framework. Thus, a standard PHP session identifier, whether conveyed by cookie or
within URLs, maintains the association between a client and session state data.
Operation
When the first session namespace is requested, Zend_Session will automatically start the
PHP session, unless already started with Zend_Session::start(). The PHP session will
use defaults from Zend_Session, unless modified by Zend_Session::setOptions().
ZEND_SESSION
Operation (continued)
To set a session configuration option, include the basename as a key of an array passed to
Zend_Session::setOptions(). The corresponding value in the array is used to set the
session option value. If no options are set, Zend_Session will utilize recommended default
options first, then default php.ini settings.
Bootstrap File
If you want all requests to have a session facilitated by Zend_Session, then start the session
in the bootstrap file. This also prevents the session from starting after headers have been sent
to the browser, which results in an exception, and possibly a broken page for website viewers.
Example: Starting the Global Session
<?php
require_once 'Zend/Session.php';
Zend_Session::start();
For more information about the right, and wrong, way to start a session, see the Programmers
Guide.
Objects persisted in the PHP session are serialized for storage, and so must be unserialized
upon retrieval but it is important to realize that the classes for the persisted objects must
have been defined before the object is unserialized. If objects are unserialized to an unknown
class, they become __PHP_Incomplete_Class_Name objects.
a. Zend_Session_Namespace::set('tree', $tree);
d. $sess = Zend_Session::getInstance()
$sess->set('tree', $tree);
a. Zend_Session_Namespace::set('tree', $tree);
d. $sess = Zend_Session::getInstance()
$sess->set('tree', $tree);
Zend_Locale
Zend_Translate
Zend_Date
Zend_Currency
Creation Output
Zend_View_Helper_Trans
Fluidity Standalone
You should be able to demonstrate a thorough knowledge of locales what they are, where
they are stored, how to create one, downgrading & checking, etc.
In addition, you should know how the translation process works, how to select and use
adapters, access different sources, change languages, etc.
Also, you should be able to work with both dates and with currency, and their corresponding
options and functions.
ZEND_LOCALE
Internationalization of a web site requires two basic processes: Localization (L10N) and
Internationalization (I18N). Many considerations go into adjusting web sites for regions, as
revealed by the various needed ZF components. For more detail, see the Programmers Guide.
Localization:
Within Zend Framework, the following components are used in the localization process the
component name reveals its role in most cases:
Zend_Locale
Zend_Translate
Zend_Date includes date and time
Zend_Currency
Zend_Locale_Format
Zend_Locale_Data
Zend Locale
A locale string or object provides Zend_Locale and its subclasses access to information
about the language and region expected by the user. Correct formatting, normalization, and
conversions are made based on this information. Locale identifier strings used in Zend
Framework are internationally defined standard abbreviations of language and region, written
as language_REGION. Both parts are abbreviated as alphabetic, ASCII characters.
Zend_Locale, unlike PHPs setlocale(), is thread-safe.
Generally, new Zend_Locale() will automatically select the correct locale, with preference
given to information provided by the user's web browser. If
Zend_Locale(Zend_Locale::ENVIRONMENT) is used, then preference will be given to the
host server's environment configuration, as shown below.
<?php
require_once 'Zend/Locale.php';
$locale = new Zend_Locale();
$locale1 = new Zend_Locale(Zend_Locale::BROWSER);
// default behavior, same as above
$locale2 = new Zend_Locale(Zend_Locale::ENVIRONMENT);
// prefer settings on host server
$locale3 = new Zend_Locale(Zend_Locale::FRAMEWORK);
// prefer framework app default settings
ZEND_LOCALE
Automatic Locales
Zend_Locale provides three "automatic" locales that do not belong to any language or
region. They have the same effect as the method getDefault() but without the negative
consequences, like creating an instance. These locales can be used anywhere, including with
standard locales, with their definition, and with their string representation. These automatic
locales offer an easy solution to a variety of situations, as when locales are provided within a
browser. Three locales have a slightly different behavior:
'browser'
Zend_Locale should work with the information provided by the user's Web browser. It is
published by PHP in the global variable HTTP_ACCEPT_LANGUAGE. If a user provides more
than one locale within the browser, Zend_Locale will use the highest quality locale. If the
user provides no locale in the browser, or the script is being called from the command line, the
automatic locale 'environment' will be used and returned.
'environment'
Zend_Locale works with the information provided by the host server, and is published by
PHP via the internal function setlocale(). If a environment provides more than one locale,
Zend_Locale will use the first locale encountered. If the host does not provide a locale, the
automatic locale 'browser' will be used and returned.
'auto'
Zend_Locale should automatically detect any locale which can be worked with. It will first
search for a users locale and then, if unsuccessful, search for the host locale. If no locale can be
detected, it will degrade to a "default" locale which is "en" when the user does not set it. This
setting can be overwritten. Options are to set a new locale manually, or define a default
location. Example: With, and Without, Auto-Detection
<?php
require_once 'Zend/Locale.php';
require_once 'Zend/Date.php';
ZEND_LOCALE
Performance Considerations
The performance of Zend_Locale and its subclasses can be boosted by the use of
Zend_Cache, specifically the static method Zend_Locale::setCache($cache).
Zend_Locale provides localized information for each locale, including local names for days
of the week, months, etc. Use object cloning to duplicate a locale object exactly and
efficiently. Most locale-aware methods also accept string representations of locales, such as
the result of $locale->toString().
If you know many objects should all use the same default locale, explicitly specify the default
locale to avoid the overhead of each object determining the default locale.
<?php
require_once 'Zend/Locale.php';
ZEND_LOCALE
<?php
require_once 'Zend/Locale.php';
Default Locales
getDefault()returns an array of relevant locales using information from the user's web
browser (if available), information from the environment of the host server, and ZF settings. As
with the constructor for Zend_Locale, the first parameter sets the preference for
consideration of information (BROWSER, ENVIRONMENT, or FRAMEWORK) . The second
parameter toggles between returning all matching locales or only the first/best match. Locale-
aware components normally use only the first locale. A quality rating is included, as available.
<?php
require_once 'Zend/Locale.php';
Use corresponding methods to obtain the default locales relevant only to the:
BROWSER getBrowser()
ENVIRONMENT getEnvironment()
ZEND_LOCALE
<?php
require_once 'Zend/Locale.php';
$locale = new Zend_Locale();
// Actual locale
print $locale->toString();
// new locale
$locale->setLocale('aa_DJ');
print $locale->toString();
ZEND_TRANSLATE
Zend_Translate is Zend Framework's solution for multilingual applications, where the content
must be translated into several languages and displayed depending on the user's language.
While PHP already offers ways to handle internationalization, they have their own issues:
inconsistent API, support only for native arrays or gettext (which is not thread-safe), no
detection of default language. Zend_Translate has none of these issues.
Choose Adapter
Gettext Qt Others
Deciding which adapter to use is often influenced by outside criteria, such as those of a
project or client consult the online Reference Guide for a in-depth discussion of the good
and bad points of using each adapter.
Utilize Adapter Example: Multi-Lingual PHP Code (more examples in Reference Guide)
<?php
$translate = new Zend_Translate('gettext', '/my/path/source-
de.mo', 'de');
$translate->addTranslation('//my/path/fr-source.mo', 'fr');
print $translate->_("Example")."\n";
print "=======\n";
print $translate->_("Here is line one")."\n";
printf(
$translate->_("Today is the %1\$s") . "\n", date("d.m.Y")
);
print "\n";
$translate->setLocale('fr');
print $translate->_("Fix language here is line two") . "\n";
usage here is line two\n";
ZEND_TRANSLATE
Performance Considerations
Using Zend_Cache internally with Zend_Translate accelerates the loading of translation
sources, useful for multiple sources or extensive source formats like XML-based files. Give a
cache object to the Zend_Translate::setCache() method, which takes a instance of
Zend_Cache as the only parameter. Direct use of an adapter allows for the use of the
setCache() method.
<?php
require_once 'Zend/Translate.php';
require_once 'Zend/Cache.php';
ZEND_TRANSLATE
Adapter Options
All adapters support various options these options are set when the adapter is created.
There is one option available to all adapters. 'clear' decides if translation data should be
added to existing content or not. The standard behavior is to add new translation data to
existing data. If the translation data is cleared, it is important to note that this step will apply
only to the selected language - all other languages will remain untouched.
If set to
Zend_Translate::LOCALE_DIRECTORY
the locale will be detected within the
directory.
If set to
Zend_Translate::LOCALE_FILENAME
the locale will be detected within the
filename.
Self-defined options can also be used with all adapters. Utilize the setOptions() method,
and provide an array with the desired options.
ZEND_TRANSLATE
Source Files
Creating CSV Source Files
CSV source files are small, readable files, easy to manage.
Source Auto-Detection:
Zend_Translate can detect translation sources automatically. It involves the same process
as initiating a single-translation source, only a directory is provided instead of a file.
ZEND_TRANSLATE
setLocale(): sets a new standard language for translation. This prevents having to
set the optional language parameter more than once to the
translate()method. If the given language does not exist, or no
translation data is available for the language, setLocale()tries to
downgrade to the language without the region, if any was given.
A language of en_US would be downgraded to en. If the
downgraded language cannot be found, an exception is thrown
getList(): used to get all the set languages for an adapter returned as an array
...
// returns the actual set language
$actual = $translate->getLocale();
...
// you can use the optional parameter while translating
echo $translate->_("my_text", "fr");
// or set a new standard language
$translate->setLocale("fr");
echo $translate->_("my_text");
// refer to base language... fr_CH is downgraded to fr and used
$translate->setLocale("fr_CH");
echo $translate->_("my_text");
...
// check if this language exist
if ($translate->isAvailable("fr")) {
// language exists
}
ZEND_TRANSLATE
ZEND_DATE
The Zend_Date component offers a detailed but simple API for manipulating dates and times.
Its methods accept a wide variety of information types , including date parts.
Zend_Date also supports abbreviated names of months in many languages. Zend_Locale
facilitates the normalization of localized month and weekday names to timestamps, which
may, in turn, be shown localized to other regions.
Internals
UNIX Timestamp
All dates and times are represented internally as absolute moments in time, as a UNIX
timestamp expressing the difference between the desired time and 1/1/1970, 00:00 GMT
PHP Functions
Where possible, Zend_Date uses PHP functions to improve performance
<?php
date_default_timezone_set('America/Los_Angeles');
// time zone for an American in California
date_default_timezone_set('Europe/Berlin');
BASIC METHODS
ZEND_DATE
Zend_Date makes it very easy to create a date from database date values. So we have one
quick and one convenient way of creating dates from database values. The standard output of
all databases is quite different even if it looks the same at first. All are part of the ISO Standard
and explained through it. So, the easiest way to create a date is to use
Zend_Date::TIMESTAMP. Zend_Date::ISO_8601 works with most formats, but is not
the most efficient way.
<?php
// SELECT UNIX_TIMESTAMP(my_datetime_column) FROM my_table
require_once 'Zend/Date.php';
Output a Date
The date in a Zend_Date object may be obtained as an integer or localized string using the
get() method. There are many available options.
Setting a Date
The set() method alters the date stored in the object, and returns the final date value as a
timestamp (not an object). There are many available options, the same for add() and sub().
Adding/Subtracting a Date
Adding two dates with add() usually involves adding a real date in time with an artificial
timestramp representing a date part, such as 12 hours.
Comparing Dates
All basic Zend_Date methods can operate on entire dates contained in the objects, or on
date parts, such as comparing the minutes value in a date to an absolute value.
<?php
require_once 'Zend/Date.php';
$date = new Zend_Date();
// Comparison of both times
if ($date->compare(10, Zend_Date::MINUTE) == -1) {
print "This hour is less than 10 minutes old";
} else {
print "This hour is at least 10 minutes old";
}
ZEND_DATE
The methods add(), sub(), compare(), get(), and set() operate generically on
dates. In each case, the operation is performed on the date held in the instance object. The
$date operand is required for all of these methods, except get(), and can be a Zend_Date
instance object, a numeric string, or an integer.
These methods assume $date is a timestamp, if it is not an object. However, the $part
operand controls which logical part of the two dates are operated on, allowing operations on
parts of the object's date, such as year or minute, even when $date contains a long form date
string, such as, "December 31, 2007 23:59:59". The result of the operation changes the date in
the object, except for compare(), and get().
<?php
require_once 'Zend/Date.php';
See the online Reference Guide for more detail on date parts, methods, and options.
Using Constants
Whenever a Zend_Date method has a $parts parameter, one of a particular set of constants
can be used as the argument for that parameter, in order to select a specific part of a date or to
indicate the date format used or desired (e.g. RFC 822). See Tables 9.7 and 9.8 in the Reference
Guide for a list of relevant constants.
ZEND_DATE
Checking Dates
Dates as input are often strings, and it is difficult to ascertain whether these strings are real
dates. Therefore, Zend_Date has an own static function to check date strings. Zend_Locale
has an own function getDate($date, $locale); which parses a date and returns the
proper and normalized date parts. As Zend_Locale does not know anything about dates
because it is a normalizing and localizing class, the components has an integrated own
function isDate($date); that checks this. isDate($date, $format,
$locale);requires one, but can take up to 3 parameters.
<?php
require_once 'Zend/Date.php';
// Checking dates
$date = '01.03.2000';
if (Zend_Date::isDate($date)) {
print "String $date is a date";
} else {
print "String $date is NO date";
}
Timezones
Timezones are integral to dates, and the default has to be set in either php.ini or by
definition within the bootstrap file.
ZEND_CURRENCY
Zend_Currency is part of the I18N core of the Zend_Framework, and handles all issues
related to currency, money representation, and formating. It also provides additional
informational methods which include localized informations on currencies, which currency is
used in which region, etc. Zend_Currency provides the following functions for handling
currency and money-related work:
Fluid Interface
Zend_Currency includes the fluid interface where possible.
<?php
// expect standard locale 'de_AT'
require_once 'Zend/Currency.php';
ZEND_CURRENCY
Script
Number Formatting
Use the setFormat() method, which takes an array containing all the options to be changed
(display position, script, format, display, precision, name, currency, symbol).
ZEND_VIEW_HELPER_TRANSLATE
Translate Helper
The display of translated content uses not only Zend_Translate, but also the Translate View
Helper. It is possible to use any instance ofZend_Translate and also any subclass of
Zend_Translate_Adapter. Ways to initiate the Translate View Helper include:
Example: Registered
<?php
// our example adapter
$adapter = new Zend_Translate('array', array( 'simple' =>
'einfach'), 'de');
Zend_Registry::set('Zend_Translate', $adapter);
ZEND_VIEW_HELPER_TRANSLATE
<?php
// within your view
$adapter = new Zend_Translate('array', array( 'simple' =>
'einfach'), 'de');
$this->translate()->setTranslator($adapter)->translate('simple');
// this returns 'einfach'
<?php
// our example adapter
$adapter = new Zend_Translate('array', array('simple' => 'einfach'
), 'de');
Adding Parameters
Parameters (single, list, array) can simply be added to the method. Example: Array of
parameters
<?php
// within your view
$date = array("Monday", "April", "11:20:55");
$this->translate('Today is %1\$s in %2\$s. Actual time:
%3\$s', $date);
// Return 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55'
<?php
// within your view
$date = array("Monday", "April", "11:20:55");
$this->translate('Today is %1\$s in %2\$s. Actual time: %3\$s',
$date, 'it');
Zend_Mail
Mail - Storage
Custom Providers
Mail - Sending
You should be able to explain the purpose of the Mail component (generating, sending,
receiving emails).
You should know how to add recipients (To, CC, BCC) and attachments to an email.
You should know how to create a multi-part message, message attachments, and ways to
change mime_part properties.
You should know which storages are supported by Zend_Mail (Mbox, Maildir, Pop3,
IMAP).
You should know which features are supported by different mail storage providers
(local/remote. folders, flags, quotas).
ZEND_MAIL
Zend_Mail provides a general feature set to compose and send both text and MIME-
compliant multi-part email messages. Mail can be sent via Zend_Mail_Transport_Smtp
or Zend_Mail_Transport_Sendmail (default).
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
$mail->setBodyText('This is the text of the mail.');
$mail->setFrom('somebody@example.com', 'Some Sender');
$mail->addTo('somebody_else@example.com', 'Some Recipient');
$mail->setSubject('TestSubject');
$mail->send();
For most mail attributes there are "get" methods to read the information stored in the mail
object. For further details, please refer to the API documentation. A special one is
getRecipients(). It returns an array with all recipient email addresses that were added
prior to the method call. For security reasons, Zend_Mail filters all header fields to prevent
header injection with newline (\n) characters.
ZF also provides a convenient fluent interface for using most methods of the Zend_Mail
object. A fluent interface means that each method returns a reference to the object on which
it was called, allowing an immediate call to another method.
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
$mail->setBodyText('This is the text of the mail.')
->setFrom('somebody@example.com', 'Some Sender')
->addTo('somebody_else@example.com', 'Some Recipient')
->setSubject('TestSubject')
->send();
ZEND_MAIL
<?php
// Load classes
require_once 'Zend/Mail.php';
// Create transport
require_once 'Zend/Mail/Transport/Smtp.php';
$transport = new Zend_Mail_Transport_Smtp('localhost');
HTML Email
To send an email in HTML format, set the body using the method setBodyHTML() instead of
setBodyText(). The MIME content type will automatically be set to text/html then. If
you use both HTML and Text bodies, a multipart/alternative MIME message will be
automatically generated.
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
$mail->setBodyText('My Nice Test Text');
$mail->setBodyHtml('My Nice <b>Test</b> Text');
$mail->setFrom('somebody@example.com', 'Some Sender');
$mail->addTo('somebody_else@example.com', 'Some Recipient');
$mail->setSubject('TestSubject');
$mail->send();
ZEND_MAIL
Sending Attachments
Files can be attached to an e-mail using the createAttachment() method. The default
behavior of Zend_Mail is to assume the attachment is a binary object (application/octet-
stream), should be transferred with base64 encoding, and is handled as an attachment. These
assumptions can be overridden by passing more parameters to createAttachment().
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
// build message...
$mail->createAttachment($someBinaryString);
$mail->createAttachment($myImage, 'image/gif',
Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_8BIT);
For more control over the MIME part generated for this attachment, use the return value of
createAttachment() to modify its attributes. The createAttachment() method
returns a Zend_Mime_Part object.
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
$at = $mail->createAttachment($myImage);
$at->type = 'image/gif';
$at->disposition = Zend_Mime::DISPOSITION_INLINE;
$at->encoding = Zend_Mime::ENCODING_8BIT;
$at->filename = 'test.gif';
$mail->send();
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail(); // build message...
require_once 'Zend/Mail/Transport/Smtp.php';
$tr1 = new Zend_Mail_Transport_Smtp('server@example.com');
$tr2 = new Zend_Mail_Transport_Smtp('other_server@example.com');
$mail->send($tr1);
$mail->send($tr2);
$mail->send(); // use default again
ZEND_MAIL
Adding Recipients
Recipients can be added in three ways:
addTo() Adds a recipient to the email with a 'To' header
addCc() Adds a recipient to the email with a 'Cc' header
addBcc() Adds a recipient to the email not visible in the header
Note: addTo() and addCc() both accept a second, optional parameter that is used to
provide a readable name for the recipient in the header.
Additional Headers
Arbitrary mail headers can be set by using the addHeader() method. It requires two
parameters containing the name and the value of the header field. A third optional parameter
determines if the header should have one or multiple values.
<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();
$mail->addHeader('X-MailGenerator', 'MyCoolApplication');
$mail->addHeader('X-greetingsTo', 'Mom', true);
// multiple values
$mail->addHeader('X-greetingsTo', 'Dad', true);
Encoding
Text and HTML message bodies are encoded with the 'quotedprintable' mechanism by
default. All other attachments are encoded via base64 if no other encoding is given in the
addAttachment()call or assigned to the MIME part object later. 7Bit and 8Bit encoding
currently only pass on the binary content data.
Zend_Mail_Transport_Smtp encodes lines starting with one dot or two dots so that the
mail does not violate the SMTP protocol.
ZEND_MAIL
Quota No Yes No No
<?php
$mail = new Zend_Mail_Storage_Pop3(array('host' =>'localhost',
'user' =>'test',
'password'=>'test'));
echo $mail->countMessages() . " messages found\n";
foreach ($mail as $message) {
echo "Mail from '{$message->from}': {$message->subject}\n";
}
<?php
$mail = new Zend_Mail_Storage_Mbox(array('filename' =>
'/home/test/mail/inbox'))
ZEND_MAIL
<?php
$message = $mail->getMessage($messageNum);
Headers can be fetched via properties, or the method getHeader() for greater control,
unusual header names, or to retrieve multiple headers with the same name as an array
(Example given below).
<?php
// get header as property the result is always a string, with
// new lines between the single occurrences in the message
$received = $message->received;
Content can be fetched using getContent(), as long as the email does not have a multi-part
message. Content is retrieved only when needed (late-fetch). To check for a multi-part
message, use the method isMultipart(). With multi-part messages, use the method
getPart() to create an instance of Zend_Mail_Part (the base class of
Zend_Mail_Message). This will make available the same methods: getHeader(),
getHeaders(), getContent(), getPart(), isMultipart and the properties for
headers.
ZEND_MAIL
<?php
// find unread messages
echo "Unread mails:\n";
foreach ($mail as $message) {
. if ($message->hasFlag(Zend_Mail_Storage::FLAG_SEEN)) {
continue;
}
// mark recent/new mails
if ($message->hasFlag(Zend_Mail_Storage::FLAG_RECENT)) {
echo '! ';
} else {
echo ' ';
}
echo $message->subject . "\n";
}
// check for known flags
$flags = $message->getFlags();
echo "Message is flagged as: ";
foreach ($flags as $flag) {
switch ($flag) {
case Zend_Mail_Storage::FLAG_ANSWERED:
echo 'Answered ';
break;
case Zend_Mail_Storage::FLAG_FLAGGED:
echo 'Flagged ';
break;
// ...
// check for other flags
// ...
default:
echo $flag . '(unknown flag) ';
}
}
ZEND_MAIL
Using Folders
All storage types except Pop3 support folders, or mailboxes. The interface implemented by
all storage-supporting folders is called Zend_Mail_Storage_Folder_Interface.
All related classes have an additional optional parameter called folder, which is the folder
selected after login, in the constructor.
The format for maildir is as defined in maildir++ (with a dot as the default delimiter).
Mbox is a directory hierarchy with Mbox files. If the Mbox file called INBOX is missing from the
Mbox base directory, set another folder in the constructor. Zend_Mail_Storage_Imap
already supports folders by default.
<?php
// Mbox with folders
$mail = new Zend_Mail_Storage_Folder_Mbox(array
('dirname' => '/home/test/mail/'));
// Mbox with default folder not called INBOX; also works for
.
// Zend_Mail_Storage_Folder_Maildir and Zend_Mail_Storage_Imap
$mail = new Zend_Mail_Storage_Folder_Mbox(array
('dirname' => '/home/test/mail/',
'folder' => 'Archive'));
ZEND_MAIL
/INBOX INBOX
/Archive/2005 2005
List.ZF.General General
The key of the current element is the local name when using the iterator. The global name is
also returned by the magic method __toString(). Some folders may not be selectable -
they cannot store messages and selecting them results in an error. This can be checked with
the method isSelectable(). Selected folders are returned by the method
getSelectedFolder() changing folders is accomplished with selectFolder() and
the global name as a parameter. (Code Example: Folder Hierarchy view)
<?php
$folders=new RecursiveIteratorIterator($this->mail->getFolders(),
RecursiveIteratorIterator::SELF_FIRST);
echo '<select name="folder">';
foreach ($folders as $localName => $folder) {
. $localName = str_pad('', $folders->getDepth(), '-',
STR_PAD_LEFT) . $localName;
echo '<option';
if (!$folder->isSelectable()) {
echo ' disabled="disabled"';
}
echo ' value="' . htmlspecialchars($folder) . '">'
. htmlspecialchars($localName) . '</option>';
}
echo '</select>';
ZEND_MAIL
Caching Instances
Zend_Mail_Storage_Mbox, Zend_Mail_Storage_Folder_Mbox,
Zend_Mail_Storage_Maildir and Zend_Mail_Storage_Folder_Maildir
implement the magic methods __sleep() and __wakeup(), which means they are
serializable. This avoids parsing the files or directory tree more than once.
The disadvantage is that the Mbox or Maildir storage should not change. Some easy checks
are done, like reparsing the current Mbox file if the modification time changes or reparsing the
folder structure if a folder has vanished this still results in an error, but a later search can be
made for another folder. A best practice is to have something like a signal file for changes and
check it before using the cached instance.
<?php
// there's no specific cache handler/class used here,
// change the code to match your cache handler
$signal_file = '/home/test/.mail.last_change';
$mbox_basedir = '/home/test/mail/';
$cache_id = 'example mail cache ' . $mbox_basedir . $signal_file;
// do stuff ...
$cache->set($cache_id, $mail);
ZEND_MAIL
Code Example: there is a need to knock different ports before connecting to POP3
<?php
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Mail_Storage_Pop3');
// initialize parent
parent::__construct($protocol);
}
}
$mail = new Example_Mail_Pop3_Knock(array('host' => 'localhost',
'user' => 'test',
'password' => 'test',
'knock_ports' => array(1101, 1105, 1111)));
a. <?php
$mail = new Zend_Mail_Storage_Pop3_Tls(array('host'
='example.com','user' ='test')); ?>
b. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com','user' ='test',
'ssl' = true)); ?>
c. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com', 'user' ='test',
'ssl' = 'tls')); ?>
d. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com', 'user' ='test',
'tls' = true)); ?>
Which one of the following will NOT assign the values to the
view object?
a. <?php
$mail = new Zend_Mail_Storage_Pop3_Tls(array('host'
='example.com','user' ='test')); ?>
b. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com','user' ='test',
'ssl' = true)); ?>
c. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com', 'user' ='test',
'ssl' = 'tls')); ?>
d. <?php
$mail = new Zend_Mail_Storage_Pop3(array('host'
='example.com', 'user' ='test',
'tls' = true)); ?>
Pattern Basics
Zend_Controller
Zend_View
Zend_Layout
The Model View Controller (MVC) design pattern is an object-oriented design pattern for
creating applications, useful for both client and web GUI (Graphical User Interfaces). This
pattern was originally designed for the client side, but has since evolved options especially
suited for the web (Example: current Controller design).
It serves to modularize an application to separate the business logic from the user
display/interaction by the use of controllers. This separation makes it easier to alter one facet
of the application (Example: data source) without affecting the other, thereby avoiding an
entire application re-design for a simple change.
Zend Framework has been based on the MVC design, because of the patterns flexibility,
efficiency, and ease of use.
The MVC structure is most often employed when creating new applications.
The diagram below illustrates the three component layers that compose the pattern, and the
general purpose for each.
ESSENTIAL TERMS
Model: The Model is used to implement domain (business) logic, such as performing
calculations. This often involves accessing data sources. The application
designer has complete freedom to decide where it comes from and how it is
used, if it is used at all. Data within the Model can exist in a database, LDAP
server, web service, etc.
As the MVC structure provides the ability to later alter aspects without an
entire re-design, it is relatively easy to change sources by changing the Model,
not the entire application (Example: authentication from a database to an
LDAP server with expansion).
View: The View is basically synonymous with HTML for many applications. It is the
template layer, where all HTML rendering takes place, and where everything to
be displayed to a user is assembled. It does not contain either business or
application logic.
Controller: The Controller layer of the pattern is actually the only one of the three that is
required. The Controller accepts and then processes the input, while
interacting with component libraries, Models, and Views.
The Controller ultimately handles the request and outputs the results to the
user based on business logic. The system within ZF is designed to be
lightweight, modular, and extensible.
Bootstrap: The bootstrap file is the single entry point to the application all requests are
routed through this page. It is responsible for loading and dispatching the
Front Controller. Example:
require_once Zend/Controller/Front.php;
Zend_Controller_Front::run(/path/to/app/controllers);
Zend_Controller
Zend_Controller is the core of the MVC pattern within Zend Framework. Controllers allow
the Business logic (Model) to be separated from the Display logic (View) and yet still function
integrally through the use of requests and responses executed by action controllers.
This diagram depicts a sample URL and how its structure maps to the MVC pattern. It clearly
illustrates how an action is mapped to the controller, along with any parameters assigned in
key-value pairs. Keep this structure in mind as the various controllers are further discussed.
controller action
maps to the ClassName of the maps to the Method of the
Controller Being executed chosen controller to execute
Parameters
can be passed as shown
in key / value pairs
Dispatch Process
Route : takes place only once, using data in Request Object when
dispatch() is called
Zend_Controller: Extensions
The Zend Controller requires a set of ZF component extensions and plugins to function
properly, with at least one or more paths to directories containing action controllers. A variety
of methods may also be invoked to further tailor the front controller environment and that of
its helper classes. The essential extensions, both for development and for the exam, are
provided below. (See the online Reference Guide for more detail.)
Zend_Controller_Front
Zend_Controller_Front processes all requests received by the server, then routes and
dispatches them to the appropriate action controllers. Key points about this component and
its extensions:
It registers a plugin broker with itself, allowing user code to be called when certain
events occur in controller process; the event methods are defined in
Zend_Controller_Front_Plugin_Abstract
The ErrorHandler plugin and ViewRenderer action helper plugin are loaded by
default; the plugins are created by including and extending the abstract class
require_once 'Zend/Controller/Plugin/Abstract.php';
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
Zend_Controller_Action
To utilize the component, extend the action controller itself, placing the class file in the
appropriate controller directory; then create action methods corresponding to the
desired actions
Helper use getHelper() or the Plugin Brokers __get() function or the Helper's
Methods: method direct() this last option is illustrated below:
$this->_helper->MessageName
('We did something in the last request');
Zend_Controller_Action
You may optionally include a direct() method in your helper class. If defined, it allows you to
treat the helper as a method of the helper broker, in order to allow easy, one-off usage of the
helper.
Zend_Controller_Request_Abstract
Values for the controller, action, and parameters are packaged into a
request extension
Associated methods retrieve the request URI, path, $_GET & $_POST
parameters, etc.
Methods
The object provides methods for setting and retrieving controller & action
names, along with associated parameters:
getModuleName() setModuleName()
getControllerName() setControllerName()
getActionName() setActionName()
Zend_Controller_Response_Abstract
Zend_Controller_Router
Itdefinesallroutersusedinallocatingrequeststothecorrectcontrollerandaction,withoptional
parameterssetintheRequestobjectviaDispatcher_Standard.
Theroutingprocessoccursonlyoncewhentherequestisreceivedandbeforethefirstcontrolleris
dispatched
Zend_Controller_Router_Interface Thecomponentusedtodefine routers
Zend_Controller_Router_Rewrite TakesURIendpointandbreaksitintoa
controlleractionandparameters
BasedonURLpath;alsousedformatching
arbitrarypaths
Worksinconjunctionwithmod_rewriteorother
rewriters,basedonthewebserverused;the
simplestruletouseisasingleApache
mod_rewriterule,althoughothersare
supported
Userdefinedroutesareaddedbycalling
addRoute()andpassinganewinstanceofa
classimplementing
Zend_Controller_Router_Route_Interface
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
/* Create a router */
$router = $ctrl->getRouter();
// returns a rewrite router by default
$router->addRoute(
'user' ,
new Zend_Controller_Router_Route(
'user/:username',
array(
'controller' => 'user',
'action' -> 'info'
)
)
);
Zend_View
Zend_View is a class for working with the Display logic of the MVC design pattern, and
provides a system of Helpers, Output Filters, and Variable escaping.
This class is independent of template type you can use PHP as the template language, or use
other template systems with view scripts. You can also create your own view implementation
by implementing Zend_View_Interface in a custom class.
(3) Render the View (the Controller instructs Zend_View to render the output, and
transfers control of the display to the View Script)
// use a model to get the data for book authors and titles
$data = array(
array(
'author' => 'Isabelle Allende',
'title' => 'The House of Spirits'
),
array(
'author' => 'Dr. Jacob Bronowski',
'title' => 'The Ascent of Man'
)
);
</table>
<?php endif;
Note how the escape() method is used to apply output escaping to variables
Action View Enable view scripts to dispatch a specific controller action; following
Helpers the dispatch, the response object result is returned;
Action view helpers are used when a particular action could generate
re-usable content;
Partial Helper Used to render a specific template within its own variable scope;
Primarily used for re-usable template fragments with no chance of
variable name conflicts;
Also allows for calling partial view scripts from specific modules;
// Which renders
<ul>
<li>From: Team Framework</li>
<li>Subject: view partials</li
</ul>
Placeholder Used to persist content between view scripts and view instances;
Helper Also, to aggregate content, capture view script content for re-use,
add pre- and post-text to content (custom separators for aggregate);
<?php $this->placeholder('foo')->set("Text for later") ?>
<?php
echo $this->placeholder('foo');// outputs "Text for later"
Helper Paths The controller can specify a stack of paths where Zend_View should
search for helper classes;
<?php
$view = new Zend_View();
Zend_View will look at the most recently added path for a requested
helper class
<?php
$view = new Zend_View();
// Add /path/to/some/helpers class prefix 'My_View_Helper'
$view->addHelperPath('/path/to/some/helpers',
'My_View_Helper');
// Add /other/path/to/helpers prefix 'Your_View_Helper'
$view->addHelperPath('/other/path/to/helpers',
'Your_View_Helper');
// Can stack
When you call paths using addHelperPath() will look
$this->helperName(),Zend_View
// first for "/other/path/to/helpers/HelperName.php" using
// class name "My_View_Helper_HelperName",
// then for "/path/to/some/helpers/HelperName" using class
// name "Your_View_Helper_HelperName", and
// finally for "Zend/View/Helper/HelperName.php" using
// class name "Zend_View_Helper_HelperName".
Filters Can indicate a filter to use after rendering a script with setFilter()
or addFilter() or the filter option to the constructor
Zend_Layout:
Zend_Layout implements a classic Two-Step View pattern, allowing developers to wrap
application content within another view, usually the site template. Usually, this pattern has
been called a Layout, so ZF has adopted this convention.
Automatic selection and rendering of layouts when used with the ZF MVC components
Disabling of layouts, changing scripts, etc., from within action controllers and view
scripts
Following script resolution rules as defined with ViewRenderer, but also the ability to
override them
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-
Type" content="text/html; charset=utf-8" />
<title>My Site</title>
</head>
<body>
<?php
// fetch 'content' key using layout helper:
echo $this->layout()->content;
// fetch 'foo' key using placeholder helper:
echo $this->placeholder('Zend_Layout')->foo;
// fetch layout object and retrieve various keys from it:
$layout = $this->layout();
echo $layout->bar;
echo $layout->baz;
?>
</body>
</html>
Initialize Zend_Layout for use with MVC (sample code examples follow)
Zend_Layout::startMvc()
registers a front controller plugin that renders the layout with any application
content once the dispatch loop is done
registers an action helper to allow access to the layout object from the action
controllers; can grab the layout instance from within a view script using the
Layout View Helper at any time
<?php
// Put into the bootstrap file:
Zend_Layout::startMvc();
?>
<?php
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// disable layouts for this action:
$this->_helper->layout->disableLayout();
}
<?php $this->_layout()->setLayout('foo');
// set alternate layout
?>
<?php
// Returns Null if startMvc() has not been called
$layout = Zend_Layout::getMvcInstance();
?>
o assigns the default segment to the variable content (which allows for
access to application content and rendering within view scripts)
<?php
$layout = new Zend_Layout();
Sample Layout Representation (order of elements will vary depending upon chosen CSS)
<?=$this->docType(XHTML1_STRICT) ?>
<html>
<head>
<? = $this->headTitle() ?>
<? = $this->headScript() ?>
<? = $this->headStylesheet() ?>
</head>
<body>
HEADER
<? = $this->partial(header.phtml)?>
NAVIGATION
<? = $this->layout()->nav ?>
CONTENT
<? = $this->layout()->content ?>
SIDEBAR
<? = $this->layout()->sidebar ?>
FOOTER
<? = $this->partial(footer.phtml)?>
</body>
</html>
Which one of the following will NOT assign the values to the
view object?
a. <code>
$view->foo = 'bar';
$view->bar = 'baz';
</code>
b. <code>
$view->assign(array(
'foo' => 'bar',
'bar' => 'baz',
));
</code>
c. <code>
$view->assign('foo', 'bar');
$view->assign('bar', 'baz');
</code>
d. <code>
$view->assign(
array('foo' => 'bar'),
array('bar' => 'baz')
);
</code>
Which one of the following will NOT assign the values to the
view object?
a. <code>
$view->foo = 'bar';
$view->bar = 'baz';
</code>
b. <code>
$view->assign(array(
'foo' => 'bar',
'bar' => 'baz',
));
</code>
c. <code>
$view->assign('foo', 'bar');
$view->assign('bar', 'baz');
</code>
d. <code>
$view->assign(
array('foo' => 'bar'),
array('bar' => 'baz')
);
</code>
Zend_Cache
Auto-serialization Functions
Zend_Memory
Implications of File
Zend_Loader
Performance Configuration
Zend_Config
Optimization
You should be able to explain how caching works and the benefits it provides.
You should know what kinds of frontends and backends Zend Framework employs, and the
various caching options available.
You should know how to utilize the factory function for Cache and Memory.
You should know how the Memory function works within the framework, for storage and
retrieval.
You should understand the trade-off relationship between performance and the Loader.
ZEND_CACHE
Zend_Cache_Core, the core of the module, is generic, flexible and configurable. Cache
frontends that extend Zend_Cache_Core include: Output, File, Function and Class.
The addition of a frontend turns on serialization, so that any type of data can be cached. This
helps to boost performance. For example, the results of a resource-intensive query can be
cached and retrieved later (unserialized) without requiring a connection to the database and
running the query again.
<?php
require_once 'Zend/Cache.php';
$frontendOptions = array(
'lifetime' => 7200, // cache lifetime of 2 hours
'automatic_serialization' => true
);
$backendOptions = array(
'cache_dir' => './tmp/' // Directory to put the cache files
);
A core strategy for caching is to demarcate the sections in which to cache output by adding
some conditional logic, encapsulating the section within start() and end() methods.
Also, be sure to make the cache identifier, which gets passed to save() and start(),
unique; otherwise, unrelated cache records may wipe each other out or even be displayed in
place of the other.
ZEND_CACHE
Factory Method
Always use Zend_Cache::factory() to get frontend instances. Instantiating frontends
and backends yourself will not work as expected, as illustrated in this code:
<?php
// Load the Zend_Cache factory
require 'Zend/Cache.php';
<?php
// clean all records
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
ZEND_CACHE
Frontends
Zend_Cache_Core
Zend_Cache_Core is the primary frontend, the core of the module. It is generic and
extended by other classes. All frontends inherit from Zend_Cache_Core so its methods
and options are also available in other frontends.
Available Frontend Options (for detailed information, see the Programmers Guide)
caching write_control
cache_id_prefix automatic_serialization
lifetime automatic_cleaning_factor
logging ignore_user_abort
Zend_Cache_Frontend_
Available Function Frontend Options (for detailed information, see the Programmers Guide)
cache_by_defaulting logging
cached_functions non-cached_functions
ZEND_CACHE
BACKENDS
Zend_Cache_Backend_File
Zend_Cache_Backend_File stores cached records into files in a chosen directory.
Available Backend Options (for detailed information, see the Reference Guide)
cache_dir cache_file_umask
file_locking hashed_directory_level
read_control hashed_directory_umask
read_control_type metadatas_array_max_size
file_name_prefix
Zend_Cache_Backend_Sqlite
Zend_Cache_Backend_Sqlite stores cache records into a SQLite database.
cache_db_complete_path automatic_vacuum_factor
required
Zend_Cache_Backend_Memcached
Zend_Cache_Backend_Memcached stores cached records into a memcached server,
where memcached is a high-performance, distributed memory object caching system. Using
this backend requires a memcached daemon and the memcache PECL extension.
servers compression
Zend_Cache_Backend_Apc
Zend_Cache_Backend_Apc stores cached records in shared memory through the
Alternative PHP Cache (APC) extension (required).
Zend_Cache_Backend_ZendPlatform
Zend_Cache_Backend_ZendPlatform uses the Platform content caching API.
ZEND_MEMORY
<?php
require_once 'Zend/Memory.php';
$backendOptions = array(
'cache_dir' => './tmp/' // Directory where to put the swapped
memory blocks
);
$memoryManager = Zend_Memory::factory('File', $backendOptions);
$loadedFiles = array();
$loadedFiles[] = $memoryManager->create($data);
}
echo $loadedFiles[$index1]->value;
$loadedFiles[$index2]->value = $newValue;
$loadedFiles[$index3]->value[$charIndex] = '_';
ZEND_MEMORY
<?php
$backendOptions = array(
'cache_dir' => './tmp/' // Directory where to put the swapped
memory blocks
);
<?php
$memObject = $memoryManager->create($data);
<?php
$memObject = $memoryManager->createLocked($data);
ZEND_MEMORY
Destroy Objects
Memory objects are automatically destroyed and removed from memory when they go out of
scope.
<?php
$oldLimit = $memoryManager->getMemoryLimit();
// Get memory limit in bytes
$memoryManager->setMemoryLimit($newLimit);
// Set memory limit in bytes
Memory Container
Use the memory container (movable or locked) 'value' property to operate with memory
object data. An alternative way to access memory object data is to use the getRef()
method. This method must be used for PHP versions before 5.2, and may have to be used in
some other cases for performance reasons.
PERFORMANCE
Configuration
Generally, developers will use one of the Zend_Config adapter classes, such as
Zend_Config_Ini or Zend_Config_Xml, to execute the process, but it is important to
note that configuration data available in a PHP array may simply be passed to the
Zend_Config constructor in order to utilize a simple object-oriented interface.
Zend_Config_Ini and Zend_Config_Xml are much slower than loading an array directly.
Opcode Caching
Opcode caching is an important boost to performance for applications written in an
interpretive language like PHP. Instead of having to generate pages each time they are
requested, the opcode caching mechanism preserves the generated code in cache so that it
need only be generated a single time to service any number subsequent requests. This is not
technically a part of ZF, but it is a best practice for production.
<php>
$result = multiply(5, 10);
</php>
c. $memoryManager = Zend_Memory::factory('None');
d. $memoryManager = Zend_Memory::getInstance('None');
<php>
$result = multiply(5, 10);
</php>
c. $memoryManager = Zend_Memory::factory('None');
d. $memoryManager = Zend_Memory::getInstance('None');
Zend_Search_Lucene
Search - Indexing
Search - Querying
Search - Performance
You should understand the purpose of a full-text search system within a web application, and
the benefits that Zend_Search_Lucene, as the search component of ZF, provides. You should
know the basics of using Zend_Search_Lucene, including compatibility and mode of
operation.
You should be familiar with all basic aspects of indexing, parsing, documents and fields,
including index optimization.
You should know query language concepts, object constructing methods, and how to work
with results sets.
ZEND_SEARCH_LUCENE
Zend_Search_Lucene was derived from the Apache Lucene project. For more information
on Lucene, visit http://lucene.apache.org/java/docs/
File Formats
Zend_Search_Lucene index file formats are binary compatible with Java Lucene version
1.4 and greater.
It is important to note that any information can be added to the index. Application-specific
information or metadata can be stored in the document fields, and later retrieved with the
document during search. Each application must be set up to control the indexer, which means
that data can be indexed from any source accessible to your application a filesystem,
database, HTML form, etc.
ZEND_SEARCH_LUCENE
<?php
$doc = new Zend_Search_Lucene_Document();
// Field not tokenized, but is indexed and stored within index.
// Stored fields can be retrieved from the index.
$doc->addField(Zend_Search_Lucene_Field::Keyword('doctype',
'autogenerated'));
ZEND_SEARCH_LUCENE
Charset
Zend_Search_Lucene works with the UTF-8 charset internally. Index files store unicode
data in Java's "modified UTF-8 encoding". Zend_Search_Lucene core completely
supports this encoding except for "supplementary characters" - Unicode characters with
codes greater than 0xFFFF.
Actual input data encoding may be specified through the Zend_Search_Lucene API. In
general, the data is automatically converted into UTF-8 encoding. However, some text
transformations are made by text analyzers and the default text analyzer does not work with
UTF-8 because of requirements for certain extensions to be loaded. In these cases, the date is
translated into ASCII/TRANSLIT and then tokenized. Special UTF-8 analyzers, described later in
the Analyzer section, may be used.
Storage
ZEND_SEARCH_LUCENE
<?php
// Create index
$index = Zend_Search_Lucene::create('/data/my-index');
$doc = new Zend_Search_Lucene_Document();
ZEND_SEARCH_LUCENE
Updating Documents
The Lucene index file format doesn't support updating documents. Documents
should be removed and re-added to the index to effectively update them.
Zend_Search_Lucene::delete()method operates with an internal index
document id. It can be retrieved from a query hit by 'id' property:
<?php
$removePath = ...;
$docs = $index->find('path:' . $removePath);
foreach ($docs as $doc) {
$index->delete($doc->id);
}
Index Optimization
A Lucene index consists of many segments - each segment is a completely independent set of
data, which cannot be updated. A segment update needs full segment reorganization, and
new documents are added to the index by creating new segments.
Increasing the number of segments reduces index quality, but index optimization
restores it. Optimization essentially merges several segments into a new one. The
process generates one new large segment and updates the segment list ('segments'
file), but not the segments themselves.
<?php
// Open existing index
$index = Zend_Search_Lucene::open('/data/my-index');
// Optimize index
$index->optimize();
ZEND_SEARCH_LUCENE
There are two ways to search an index - the first method uses a query parser to construct a
query from a string. The second is to programmatically create your own queries through the
Zend_Search_Lucene API. Generally speaking, the query parser is designed for human-
entered text, not for program-generated text (better suited to the API method). Untokenized
fields are best added directly to queries and not through the query parser. If a field's values are
generated programmatically by the application, then the query clauses for this field should
also be constructed programmatically.
Analyzer
An analyzer, which is used by the query parser, is designed to convert human-entered text to
terms. Program-generated values, like dates, keywords, etc., should be added with the query
API.
In a query form, fields that are general text should use the query parser. All others, such as
date ranges, keywords, etc., are better added directly through the query API. A field with a
limited set of values that can be specified with a pull-down menu should not be added to a
query string subsequently parsed; instead, it should be added as a TermQuery clause.
Boolean queries allow the programmer to logically combine two or more queries into
new one, the best way to add additional criteria to a search defined by a query string.
Both ways use the same API method to search through the index:
<?php
require_once 'Zend/Search/Lucene.php';
$index = Zend_Search_Lucene::open('/data/my_index');
$index->find($query);
Note: the query parser uses the standard analyzer to tokenize separate parts of a query
string; all transformations applied to indexed text are also applied to query strings.
The standard analyzer may transform the query string to lower case for case-
insensitivity, remove stop-words, and stem among other modifications. The API
method doesn't transform or filter input terms in any way, making it more suitable for
computer generated or untokenized fields.
ZEND_SEARCH_LUCENE
Analyzer(continued)
Zend_Search_LucenecontainsasetofUTF8compatibleanalyzers:
Zend_Search_Lucene_Analysis_Analyzer_Common_ +
Utf8 or Utf8Num or Utf8_CaseInsensitive or Utf8Num_CaseInsensitive
SearchResults
ThesearchresultisanarrayofZend_Search_Lucene_Search_QueryHitobjects.
Eachofthesehastwoproperties:$hit->idisadocumentnumberwithintheindexand
$hit->scoreisascoreofthehitinasearchresult.Theresultsareorderedbyscore
(descendingfromhighestscore).
TheZend_Search_Lucene_Search_QueryHitobjectalsoexposeseachfieldofthe
Zend_Search_Lucene_Documentfoundinthesearchasapropertyofthehit.Stored
fieldsarealwaysreturnedinUTF8encoding.Optionally,theoriginal
Zend_Search_Lucene_Documentobjectcanbereturnedfromthe
Zend_Search_Lucene_Search_QueryHit.Youcanretrievestoredpartsofthe
documentbyusingthegetDocument()methodoftheindexobjectandthengetthem
usinggetFieldValue().Example:
<?php
require_once 'Zend/Search/Lucene.php';
$index = Zend_Search_Lucene::open('/data/my_index');
$hits = $index->find($query);
foreach ($hits as $hit) {
// return Zend_Search_Lucene_Document object for this hit
echo $document = $hit->getDocument();
// return Zend_Search_Lucene_Field object
// from Zend_Search_Lucene_Document
echo $document->getField('title');
// return the string value of Zend_Search_Lucene_Field object
echo $document->getFieldValue('title');
// same as getFieldValue()
echo $document->title;
}
ZEND_SEARCH_LUCENE
Short syntax automatically retrieves a document from an index (although it needs additional
time and increases memory usage). Short index is not suitable for 'id' and 'score'
document fields (if they are present) because of special 'id' and 'score' hit properties
name conflicts.
$hit->title
// identical to $hit->getDocument()->title and also
// identical to $hit->getDocument()->getFieldValue('title')
Short syntax is very important for pagination implementation. Whole result set ids and scores
should be stored somewhere (for example, using Zend_Cache) without actual document
retrieval (only 'id' and 'score' properties are accessed). Then, any required parts of ids or
scores should be used to get documents using the $index->getDocument($id) method.
ZEND_SEARCH_LUCENE
As the score computation uses up essential search time, a reduction in the number of results
scored represents a corresponding increase in Search performance.
Results Scoring
Zend_Search_Lucene uses the same scoring algorithms as Java Lucene. All hits in the
search result are ordered by score by default. Hits with greater score come first, and
documents having higher scores should match the query more precisely than documents
having lower scores. A hit's score can be retrieved by accessing the score property of the hit:
<?php
$currentResultSetLimit = Zend_Search_Lucene::getResultSetLimit();
Zend_Search_Lucene::setResultSetLimit($newLimit);
Results Sorting
By default, the search results are ordered by score. This default can be overridden by setting a
sort field (or a list of fields), sort type and sort order parameters.
<?php
$hits = $index->find($query);
Output Escaping
Zend_View ZF Protections
Zend_Filter ZF Protections
Zend_Db ZF Protections
Zend_Form ZF Protections
Secure Authentication
Zend_Auth ZF Protections
ZF Protections
You will need to know the basics around security the most common types of security attacks
and breaches, and the most common measures to employ to help prevent or mitigate such
attacks.
Output Escaping
Secure Authentication
OUTPUT ESCAPING
A critical function for view scripts to perform is to escape output properly, as it helps to fend
off security attacks like cross-site scripting.
A best practice rule is always to escape variables when outputting them, unless you are using
a function or method or helper that performs this step on its own.
<?php
To escape using an alternate way, call the setEscape() method at the Controller
level to instruct Zend_View on what escaping callback to use
<?php
// create a Zend_View instance
$view = new Zend_View();
Cross-site scripting attacks are an injection of HTML, CSS, or script code into a page. JavaScript
is especially a threat; its primary cause is displaying data mis-interpreted by the browser.
Filters are commonly used to escape HTML elements, helping to avoid such attacks. If, for
example, a form field is populated with untrustworthy data (and any data input from the
outside is untrustworthy!), then this value should either not contain HTML (removal), or if it
does, then have that HTML escaped.
<?php
require_once 'Zend/Filter/HtmlEntities.php';
SQL injection attacks are those in which applications are manipulated to return data to a user
that should not have the privilege to access/read such data.
$name = $_GET[Name];
//$_GET[Name] = "O'Reilly";
$sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
echo $sql;
// SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
Zend_Db has some built-in features that help to mitigate such attacks, although there is no
substitute for good programming.
When inserting data from an array, the values are inserted as parameters by default, reducing
the risk of some types of security issues. Consequently, you do not need to apply escaping or
quoting to values in a data array.
Cross-Site Request Forgery (XSRF) attacks employ an almost opposite approach to Cross-Site
Scripting (XSS). XSRF attacks disguise themselves as a trusted user to attack a web site,
whereas XSS attacks disguise themselves as a trusted web site to attack a user.
To protect against XSRF attacks originating from third party sites, you have options
Another option available is the use of hashed identifiers in submitted forms (typically
the most dangerous activity, like changing a password) can reduce the damage of a
XSRF attack. Once a unique hash has been used to service a request, it is subsequently
invalidated, and any request using that ID is not honored.
Zend_Form_Element_Hash, used in conjunction with Zend_Form::isValid()
helps to automate the hashing/validation mechanism.
Filters (such as Zend_Filter) are commonly used to escape HTML elements. If, for
example, a form field is populated with untrustworthy data (and any data input from
the outside is untrustworthy!), then this value should either not contain HTML
(removal), or if it does, then have that HTML escaped.
(Note: there may be times when HTML output needs to be displayed for example,
when using a JavaScript-based HTML editor; in these cases, you would need to build
either a validator or filter that employs a whitelist approach.
SECURE AUTHENTICATION
Authentication is the process of verifying a users identity against some set of pre-established
criteria.
Zend_Auth provides an API for conducting authentication, along with adapters designed
for the most common uses.
Here are some things to keep in mind (see the Authorization section for more detail):
o Singleton pattern means only one instance of the class is available at any one time
o The new operator and the clone keyword will not work with this class use
Zend_Auth::getInstance() instead
o Use of Zend_Auth is not a substitute for proper encryption of communications
The adapters authenticate against a particular service, like LDAP, RDBMS, etc.; while their
behavior and options will vary, they share some common actions:
o return results
There are three golden rules to follow when providing security to web applications and their
environments:
a. $this->filter($data)
b. $this->escape($data)
c. $this->htmlEntities($data)
d. $data->escape()
a. TRUE
b. FALSE
a. $this->filter($data)
b. $this->escape($data)
c. $this->htmlEntities($data)
d. $data->escape()
a. TRUE
b. FALSE
XmlRpc_Client
Call
XmlRpc_Server
Rest_Client
Rest_Server
Handle
You should be able to explain the function of the XmlRpc Clients and Servers, and provide
code for related functions, methods, and classes.
You should know how to specify exceptions that may be used as fault responses.
You should know the purpose of consumable services, and which are available to Zend
Framework.
ZEND_XMLRPC_CLIENT
Method Calls
The constructor of Zend_XmlRpc_Client receives the URL of the remote XML-RPC server
endpoint as its first parameter. The new instance returned can call any number of remote
methods at that endpoint, by instantiating it and then using the call() instance method.
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://www.zend.com/xmlrpc');
echo $client->call('test.sayHello'); // hello
The XML-RPC value returned from the remote method call will be automatically unmarshaled
and cast to the equivalent PHP native type. In the example above, a PHP string is returned
and immediately ready for use. The first parameter of the call() method receives the name
of the remote method to call. Any required parameters can be sent by supplying a second,
optional parameter to call() with an array of values to pass to the remote method.
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://www.zend.com/xmlrpc');
$arg1 = 1.1;
$arg2 = 'foo';
$result = $client->call('test.sayHello', array($arg1, $arg2));
// $result is a native PHP type
If no parameters are required, this option may either be left out or an empty array() passed
to it. Parameters can contain native PHP types, Zend_XmlRpc_Value objects, or a mix. The
call() method will automatically convert the XML-RPC response and return its PHP native
type. getLastResponse() makes a Zend_XmlRpc_Response object available for the
return value.
Request to Response
The call() instance method of Zend_XmlRpc_Client builds a request object
(Zend_XmlRpc_Request) and sends it to another method, doRequest(). This returns a
response object (Zend_XmlRpc_Response). doRequest()can also be directly used.
ZEND_XMLRPC_CLIENT
Another way to call remote methods with the XML-RPC client is to use the server proxy, a PHP
object that proxies a remote XML-RPC namespace, making it work as close to a native PHP
object as possible. To instantiate a server proxy, call the getProxy() instance method of
Zend_XmlRpc_Client, which returns an instance of
Zend_XmlRpc_Client_ServerProxy. Any method call on the server proxy object will be
forwarded to the remote, and parameters may be passed like any other PHP method.
<?php
require_once 'Zend/XmlRpc/Client.php';
//test.Hello(1,2)returns "hello"
$hello = $server->test->sayHello(1, 2);
The getProxy() method receives an optional argument specifying which namespace of the
remote server to proxy. If it does not receive a namespace, the default namespace will be
proxied.
If an HTTP error occurs, such as the remote HTTP server returns a 404 Not Found, a
Zend_XmlRpc_Client_HttpException will be thrown. Ex:
<?php
require_once 'Zend/XmlRpc/Client.php';
try {
$client->call('bar', array($arg1, $arg2));
ZEND_XMLRPC_CLIENT
An XML-RPC fault is analogous to a PHP exception. It is a special type returned from an XML-
RPC method call that has both an error code and an error message. XML-RPC faults are
handled differently depending on the context of how the Zend_XmlRpc_Client is used.
When the call() method or the server proxy object is used, an XML-RPC fault will result in a
Zend_XmlRpc_Client_FaultException being thrown. The code and message of the
exception will map directly to their respective values in the original XML-RPC fault response.
<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://www.zend.com/xmlrpc');
try {
$client->call('badMethod');
} catch (Zend_XmlRpc_Client_FaultException $e) {
// $e->getCode() returns 1
Zend_Db contains a factory() method by which you may
instantiate a database adapter object
If doRequest() is used to make the request, it will not throw the exception. Instead, it will
return a Zend_XmlRpc_Response object containing the fault, which can be checked with
the isFault() instance method of Zend_XmlRpc_Response.
ZEND_XMLRPC_SERVER
Basic Usage:
<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'My/Service/Class.php';
Server Structure:
ZEND_XMLRPC_SERVER
When attaching items to a server, functions and class methods must have full docblocks with,
minimally, the parameter and return type annotations. Without this information, the servers
will not work.
Attaching a Function:
This example illustrates the relatively simple process of attaching a function as a dispatchable
XML-RPC method, also handling incoming calls.
<?php
require_once 'Zend/XmlRpc/Server.php';
/**
* Return the MD5 sum of a value
*
* @param string $value Value to md5sum
* @return string MD5 sum of value
*/
function md5Value($value)
{
return md5($value);
}
Attaching a Class:
The code example below attaches a class' public methods as dispatchable XML-RPC methods.
<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Services/Comb.php';
ZEND_XMLRPC_SERVER
Custom Responses:
Possible uses of a custom object would be to log responses, or to send responses back to
STDOUT. Be sure to use Zend_XmlRpc_Server::setResponseClass() prior to calling
handle().
Handling Exceptions:
Zend_XmlRpc_Server catches exceptions generated by a dispatched method, and
generates an XML-RPC fault response when such an exception is caught.
By default, however, the exception messages and codes are not used in a fault response. This
is an intentional decision to protect your code; exceptions expose information about the code
or environment that can create a security risk.
<?php
Zend_XmlRpc_Server_Fault::attachFaultException('My Exception');
If you utilize an exception class that your other project exceptions inherit, a whole family of
exceptions can be whitelisted. Zend_XmlRpc_Server_Exceptions are always whitelisted,
for reporting specific internal errors (undefined methods, etc.).
Any exception not specifically whitelisted will generate a fault response with a code of '404'
and a message of 'Unknown error'.
Attaching many classes to an XML-RPC server instance can tie up resources; each class must
introspect using the Reflection API (via Zend_Server_Reflection), which in turn
generates a list of all possible method signatures to provide to the server class. To offset this
performance hit, Zend_XmlRpc_Server_Cache can be used to cache the server definition
between requests. When combined with __autoload(), this can greatly increase
performance.
ZEND_XMLRPC_SERVER
Attaching many classes to an XML-RPC server instance can tie up resources; each class must
introspect using the Reflection API (via Zend_Server_Reflection), which in turn
generates a list of all possible method signatures to provide to the server class. To offset this
performance hit, Zend_XmlRpc_Server_Cache can be used to cache the server definition
between requests. When combined with __autoload(), this can greatly increase
performance. A sample use case follows:
function __autoload($class)
{
Zend_Loader::loadClass($class);
}
if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
require_once 'My/Services/Glue.php';
require_once 'My/Services/Paste.php';
require_once 'My/Services/Tape.php';
// glue. namespace
$server->setClass('My_Services_Glue', 'glue');
// paste. namespace
$server->setClass('My_Services_Paste', 'paste');
// tape. namespace
$server->setClass('My_Services_Tape', 'tape');
Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
}
echo $server->handle();
The above example attempts to retrieve a server definition from xmlrpc.cache in the same
directory as the script. If unsuccessful, it loads the service classes it needs, attaches them to the
server instance, and then attempts to create a new cache file with the server definition.
ZEND_REST_CLIENT
REST Web Services use service-specific XML formats; consequently, the manner for accessing a
REST web service is different for each service. REST web services typically use URL parameters
(GET data) or path information for requesting data and POST data for sending data.
The Zend Framework provides both Client and Server capabilities that, when used together,
allow for a much more "local" interface experience via virtual object property access. The
Server component automatically exposes functions and classes using a meaningful and
simple XML format. When accessing these services using the Client, the return data can be
easily retrieved from the remote call.
Using the Zend_Rest_Client is very similar to using SoapClient objects . Simply call the
REST service procedures as Zend_Rest_Client methods and specify the service's full
address in the Zend_Rest_Client constructor.
<?php
/**
* Connect to framework.zend.com server and retrieve a greeting
*/
require_once 'Zend/Rest/Client.php';
$client = new Zend_Rest_Client('http://framework.zend.com/rest');
echo $client->sayHello('Dave', 'Day')->get(); // "Hello Dave,
Good Day"
Zend_Rest_Client attempts to make remote methods look as much like native methods
as possible, only that method call must be followed with one of either get(), post(),
put() or delete(). This call may be made via method chaining or in separate method calls.
<?php
$client->sayHello('Dave', 'Day');
echo $client->get();
ZEND_REST_CLIENT
Responses
<?php
$result = $client->sayHello('Dave', 'Day')->get();
if ($result->isSuccess()) {
echo $result; // "Hello Dave, Good Day"
}
In the example above, the request result as an object, used to call isSuccess(), and then
using __toString()echoes the object to get the result.
ZEND_REST_SERVER
<?php
require_once 'Zend/Rest/Server.php';
require_once 'My/Service/Class.php';
<?php
require_once 'Zend/Rest/Server.php';
/**
* Say Hello
*
* @param string $who
* @param string $when
* @return string
*/
function sayHello($who, $when)
{
return "Hello $who, Good $when";
}
ZEND_REST_SERVER
<?php
require_once 'Zend/Rest/Server.php';
/**
* Say Hello
*
* @param string $who
* @param string $when
* @return SimpleXMLElement
*/
function sayHello($who, $when)
{
$xml ='<?xml version="1.0" encoding="ISO-8859-1"?>
<mysite>
<value>Hey $who! Hope you're having a good $when</value>
<code>200</code>
</mysite>';
$xml = simplexml_load_string($xml);
return $xml;
}
$server->handle();
ZEND_SERVICE
While Zend_Service is extensible, Zend also provides support for popular web services.
Examples of web service support packaged with Zend Framework include:
HTTP Clients:
For those Zend services that utilize HTTP requests, change the HTTP client of
Zend_Rest_Client to change which HTTP client the service uses.
<?php
$myHttpClient = new My_Http_Client();
Zend_Service_Akismet::setHttpClient($myHttpClient);
When making more than one request with a service, configure the HTTP client to keep
connections alive and speed the requests.
<?php
Zend_Service_Akismet::getHttpClient()->setConfig(array(
'keepalive' => true
));